From bb6a20313bc7f10b947b2fe0ae1f2da0767e8f18 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Sun, 12 May 2019 19:48:51 +0300 Subject: [PATCH] Few things --- there are: - Fix bug within index allocator - Removed obsolete locking stuff from allocator - Stupid test added --- Makefile.am | 9 +++- configure.ac | 11 +++-- include/tdata/bitwise.h | 35 +++++++--------- include/tdata/idx_allocator.h | 13 +----- lib/idx_allocator.c | 38 +++++------------ tests/.gitignore | 1 + tests/Makefile.am | 19 +++++++++ tests/idxa.c | 79 +++++++++++++++++++++++++++++++++++ 8 files changed, 142 insertions(+), 63 deletions(-) create mode 100644 tests/.gitignore create mode 100644 tests/Makefile.am create mode 100644 tests/idxa.c diff --git a/Makefile.am b/Makefile.am index 4b1e1d9..e576da6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,13 @@ ## Process this file with automake to produce Makefile.in -SUBDIRS = include lib +## options +EXTRA = + +if BUILD_TESTS +EXTRA += tests +endif + +SUBDIRS = include lib $(EXTRA) libtdatadocdir = ${prefix}/doc/libtdata libtdatadoc_DATA = \ diff --git a/configure.ac b/configure.ac index 793931e..08915d1 100644 --- a/configure.ac +++ b/configure.ac @@ -48,15 +48,18 @@ dnl ***************** dnl ***** options ***** dnl ***************** -AC_ARG_ENABLE([build_examples], - AS_HELP_STRING([--enable-build-examples], [Enable examples build])) +AC_ARG_ENABLE([build_tests], + AS_HELP_STRING([--enable-build-tests], [Enable build tests])) -AS_IF([test "x$enable_build_examples" = "xyes"], [ - AC_DEFINE([BUILD_EXAMPLES], 1, [build of examples enabled]) +AS_IF([test "x$enable_build_tests" = "xyes"], [ + AC_DEFINE([BUILD_TESTS], 1, [build of tests enabled]) ]) +AM_CONDITIONAL(BUILD_TESTS, test "x$enable_build_tests" = "xyes") + AC_OUTPUT([ Makefile lib/libtdata.pc lib/Makefile +tests/Makefile include/Makefile]) diff --git a/include/tdata/bitwise.h b/include/tdata/bitwise.h index 36b91d7..6a9a8ad 100644 --- a/include/tdata/bitwise.h +++ b/include/tdata/bitwise.h @@ -28,11 +28,10 @@ /* TODO: add arch deps */ //#include -/* TODO: add linux headers tests */ -#include - -#ifdef __BITS_PER_LONG -#define BITS_PER_LONG __BITS_PER_LONG +#ifdef BUILD_HOST_32BIT +#define BITS_PER_LONG 32 +#else +#define BITS_PER_LONG 64 #endif #if BITS_PER_LONG == 64 @@ -59,7 +58,7 @@ typedef struct __bitmap { #ifndef ARCH_BIT_SET static inline void bit_set(void *bitmap, int bit) { - *(unsigned long *)bitmap |= (1 << bit); + *(unsigned long *)bitmap |= (1UL << bit); } #else #define bit_set(bitmap, bit) arch_bit_set(bitmap, bit) @@ -76,7 +75,7 @@ static inline void bit_set(void *bitmap, int bit) #ifndef ARCH_BIT_CLEAR static inline void bit_clear(void *bitmap, int bit) { - *(unsigned long *)bitmap &= ~(1 << bit); + *(unsigned long *)bitmap &= ~(1UL << bit); } #else #define bit_clear(bitmap, bit) arch_bit_clear(bitmap, bit) @@ -93,7 +92,7 @@ static inline void bit_clear(void *bitmap, int bit) #ifndef ARCH_BIT_TOGGLE static inline void bit_toggle(void *bitmap, int bit) { - *(unsigned long *)bitmap ^= (1 << bit); + *(unsigned long *)bitmap ^= (1UL << bit); } #else #define bit_toggle(bitmap, bit) arch_bit_toggle(bitmap, bit) @@ -111,7 +110,7 @@ static inline void bit_toggle(void *bitmap, int bit) #ifndef ARCH_BIT_TEST static inline int bit_test(void *bitmap, int bitno) { - return ((*(unsigned long *)bitmap & (1 << bitno)) >> bitno); + return ((*(unsigned long *)bitmap & (1UL << bitno)) >> bitno); } #else #define bit_test(bitmap, bitno) arch_bit_test(bitmap, bitno) @@ -133,7 +132,7 @@ static inline int bit_test(void *bitmap, int bitno) static inline int bit_test_and_set(void *bitmap, int bitno) { int val = (*(unsigned long *)bitmap & (1 << bitno)); - *(unsigned long *)bitmap |= (1 << bitno); + *(unsigned long *)bitmap |= (1UL << bitno); return val; } @@ -157,7 +156,7 @@ static inline int bit_test_and_set(void *bitmap, int bitno) static inline int bit_test_and_reset(void *bitmap, int bitno) { int val = (*(unsigned long *)bitmap & (1 << bitno)); - *(unsigned long *)bitmap &= ~(1 << bitno); + *(unsigned long *)bitmap &= ~(1UL << bitno); return val; } @@ -175,23 +174,21 @@ static inline int bit_test_and_reset(void *bitmap, int bitno) #ifndef ARCH_BIT_FIND_LSF static inline long bit_find_lsf(unsigned long word) { - long c = -1; + long c = 0; - for (; word; c++, word >>= 1) { - if ((word & 0x01)) { - c++; - break; - } + while(c <= ((sizeof(unsigned long)*8) - 1)) { + if(word & (1UL << (unsigned long)c)) return c; + c++; } - return c; + return -1; } #else #define bit_find_lsf(word) arch_bit_find_lsf(word) #endif /* ARCH_BIT_FIND_LSF */ #ifndef ARCH_ZERO_BIT_FIND_LSF -#define zero_bit_find_lsf(word) bit_find_lsf(~(word)) +#define zero_bit_find_lsf(word) bit_find_lsf(~(unsigned long)(word)) #else #define zero_bit_find_lsf(word) arch_zero_bit_find_lsf(word) #endif diff --git a/include/tdata/idx_allocator.h b/include/tdata/idx_allocator.h index 4a8af1d..a3d4c55 100644 --- a/include/tdata/idx_allocator.h +++ b/include/tdata/idx_allocator.h @@ -43,7 +43,6 @@ #define __IDX_ALLOCATOR_H__ #include -#include typedef unsigned long ulong_t; @@ -51,13 +50,6 @@ typedef unsigned long ulong_t; #define WORDS_PER_ITEM (BYTES_PER_ITEM / sizeof(ulong_t)) /**< Number of machine words(ulong_t) per second-level bitmap item */ #define IDX_INVAL ~0UL /**< Invalid index value */ -#define ida_lock_init(lock) pthread_mutex_init(lock, NULL) -#define ida_lock_destroy(lock) pthread_mutex_destroy(lock); -#define ida_lock(a) pthread_mutex_lock(&a->lock) -#define ida_unlock(a) pthread_mutex_unlock(&a->lock) -#define ida_lockable(a) (a->lck) - -typedef pthread_mutex_t ida_lock_t; /** * @struct idx_allocator_t @@ -68,8 +60,6 @@ typedef struct __idx_allocator { ulong_t max_id; /**< Maximum index value(exclusive) */ ulong_t *main_bmap; /**< First-level(main) bitmap that splits second-level bitmap on several parts */ ulong_t *ids_bmap; /**< Second-level bitmap whose each bit corresponds to particular unique identifier */ - ida_lock_t lock; - int lck; } idx_allocator_t; #define idx_allocator_initialized(ida) (((idx_allocator_t*)(ida))->max_id) @@ -78,7 +68,8 @@ typedef struct __idx_allocator { * @brief Initialize an index allocator. * @param ida - A pointer to particular index allocator * @param idx_max - Maximum index value. - * @lockable - flag to indicate the allocator must support locking itself + * @lockable - flag to indicate the allocator must support locking itself, + * deprecated and will be removed within next major version bump */ int idx_allocator_init(idx_allocator_t *ida, ulong_t idx_max, int lockable); diff --git a/lib/idx_allocator.c b/lib/idx_allocator.c index 14484b5..4180011 100644 --- a/lib/idx_allocator.c +++ b/lib/idx_allocator.c @@ -52,7 +52,6 @@ */ #define MIN_IDA_SIZE (WORDS_PER_ITEM * sizeof(ulong_t)) -#define MAX_UNLOCKED_ATTEMPTS 3 /* there macros defined only on new glibc (from 12-jul-2013), let's use our own */ #ifndef is_powerof2 @@ -74,11 +73,9 @@ ulong_t idx_allocate(idx_allocator_t *ida) { ulong_t id = IDX_INVAL; long fnfi = 0; - size_t i, main_offs = 0, main_sz; - int natm = 0; /* attempt number */ + size_t i = 0, main_offs = 0, main_sz; main_sz = __get_main_bmap_size(ida) / sizeof(ulong_t); - i = 0; if (ida->ids_bmap != NULL) { for (;;) { @@ -104,17 +101,12 @@ ulong_t idx_allocate(idx_allocator_t *ida) continue; } - if (ida_lockable(ida) /*&& atomic_test_and_set_bit(ida->ids_bmap + j, res_id)*/) { - natm++; - if (natm == MAX_UNLOCKED_ATTEMPTS) - ida_lock(ida); - } else { - bit_set(ida->ids_bmap + j, res_id); - } + bit_set(ida->ids_bmap + j, res_id); id = res_id + j * BITS_PER_LONG; if (id >= ida->max_id) { bit_clear(ida->ids_bmap + j, res_id); + printf("%s:%d IDXINVAL\n", __FILE__, __LINE__); id = IDX_INVAL; } @@ -122,15 +114,14 @@ ulong_t idx_allocate(idx_allocator_t *ida) } bit_set(ida->main_bmap + main_offs, - (fnfi - (main_offs * WORDS_PER_ITEM * BITS_PER_LONG)) / WORDS_PER_ITEM); - if ((ida->main_bmap[i] & ~0UL) == ~0UL) - i++; + (fnfi - (main_offs * WORDS_PER_ITEM * BITS_PER_LONG)) / + WORDS_PER_ITEM); + if ((ida->main_bmap[i] & ~0UL) == ~0UL) i++; } - else - break; + else break; } - } - else { + } else { + while (i < main_sz) { fnfi = zero_bit_find_lsf(ida->main_bmap[i]); if (fnfi >= 0) { @@ -149,8 +140,6 @@ ulong_t idx_allocate(idx_allocator_t *ida) } out: - if (natm == MAX_UNLOCKED_ATTEMPTS) - ida_unlock(ida); return id; } @@ -219,12 +208,6 @@ int idx_allocator_init(idx_allocator_t *ida, ulong_t idx_max, int lockable) goto error; } -#if 0 - if (lockable && ida_lock_init(&ida->lock)) - goto error; -#endif - ida->lck = 0; /* cutty, we don't use the lockable due to the very arch specifics */ - memset(ida->main_bmap, 0, __get_main_bmap_size(ida)); ida->max_id = idx_max; return 0; @@ -247,7 +230,6 @@ void idx_allocator_destroy(idx_allocator_t *ida) free(ida->main_bmap); - if (ida_lockable(ida)) - ida_lock_destroy(&ida->lock); + return; } diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..892a90e --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +idxatest diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..b9c7bef --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,19 @@ +## AUTOMAKE_OPTIONS = foreign + +AM_CPPFLAGS = \ + -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ + -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \ + -DPACKAGE_DATA_DIR=\""$(pkgdatadir)"\" \ + -DCNFPATH=\""$(prefix)/etc"\" \ + -I$(top_srcdir)/include + +AM_CFLAGS = -Wall -g + +# where to find libsxmp +libtdata = $(top_builddir)/lib/.libs/libtdata.la + +bin_PROGRAMS = idxatest + +idxatest_SOURCES = idxa.c +idxatest_LDADD = $(libtdata) -lpthread + diff --git a/tests/idxa.c b/tests/idxa.c new file mode 100644 index 0000000..5fd378f --- /dev/null +++ b/tests/idxa.c @@ -0,0 +1,79 @@ +/* + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * (c) Copyright 2014 Alexander Vdolainen + * + * Index allocator tests + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IDXMAX 131072 + +int main(int argc, char **argv) +{ + idx_allocator_t idxa; + ulong_t r = 0, i = 0; + + memset(&idxa, 0, sizeof(idxa)); + + if((r = idx_allocator_init(&idxa, IDXMAX, 0))) { + fprintf(stderr, "%d:(%s): IDX init failed with %lu\n", __LINE__, + __FUNCTION__, r); + goto __finiv; + } + + /* one thread */ + /* (1) use the half of pool and free it */ + for(i = 0; i < IDXMAX/2; i++) { + r = idx_allocate(&idxa); + if(r != i) { + fprintf(stderr, "%d:(%s):error: expected %lu instead of %lu\n", + __LINE__, __FUNCTION__, i, r); + r = -1; + goto __finiv1; + } + } + + /* (2) use all pool and free the second part */ + for(i = IDXMAX/2; i < IDXMAX; i++) { + r = idx_allocate(&idxa); + if(r != i) { + fprintf(stderr, "%d:(%s):error: expected %lu instead of %lu\n", + __LINE__, __FUNCTION__, i, r); + r = -1; + goto __finiv1; + } + } + /* (3) fill second part and free all and try to allocate 1/4 */ + /* (4) free all */ + + __finiv1: + + idx_allocator_destroy(&idxa); + + __finiv: + return r; +}