rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

commit 07b377929d857a151a0871c9e83dc923d828ca21
parent d6567505c614c362b6d34f164855effadc447709
Author: vaplv <vaplv@free.fr>
Date:   Sat,  1 Feb 2014 17:50:45 +0100

Merge remote-tracking branch 'origin/branch-c89' into branch-c89

Conflicts:
	src/test_condition.c

Diffstat:
M.gitignore | 3+++
Msrc/CMakeLists.txt | 131+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Msrc/atomic.h | 96++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/clock_time.c | 76+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Msrc/clock_time.h | 91+++++++++++++++++++++++--------------------------------------------------------
Msrc/condition.h | 17++++++-----------
Asrc/free_list.h | 136+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/image.c | 15++++++++-------
Msrc/library.c | 50++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/library.h | 4----
Msrc/list.h | 20++++++++++----------
Msrc/mem_allocator.c | 289+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Msrc/mem_allocator.h | 29+++++++++++++++++++++++------
Msrc/mutex.h | 38++++++++++++++++++++------------------
Asrc/platform.h.in | 8++++++++
Dsrc/pthread/condition.h | 47-----------------------------------------------
Dsrc/pthread/mutex.h | 116-------------------------------------------------------------------------------
Asrc/pthread/pthread_condition.c | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/pthread/pthread_mutex.c | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/ref_count.h | 5+++--
Msrc/rsys.h | 83++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Asrc/rsys_version.h.in | 9+++++++++
Msrc/signal.h | 1+
Msrc/test_atomic.c | 27++++++---------------------
Msrc/test_condition.c | 69++++++++++++++++++++++++++++++++++++++++-----------------------------
Asrc/test_free_list.c | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_list.c | 12++++++++----
Msrc/test_mem_allocator.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Msrc/test_mutex.c | 265+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/test_ref.c | 2+-
Msrc/test_signal.c | 22+++++++++++++---------
Asrc/test_time.c | 28++++++++++++++++++++++++++++
32 files changed, 1388 insertions(+), 630 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -2,6 +2,7 @@ CMakeCache.txt CMakeFiles Makefile +tmp [Bb]uild *.swp *.[ao] @@ -9,3 +10,5 @@ Makefile *.cmake tags cmake_build +rsys_version.h +platform.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt @@ -12,82 +12,113 @@ find_package(OpenMP) ################################################################################ # Setup compile flags/parameters ################################################################################ -set(CMAKE_DEBUG_POSTFIX "-dbg") -set(CMAKE_C_FLAGS "-pedantic -std=c99 -Wall -Wextra -Wcast-align -Wmissing-declarations -Wmissing-prototypes -fvisibility=hidden -fstrict-aliasing -fPIC -Wl,-z,defs -Wconversion") +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(BUILD_32-BIT OFF CACHE BOOL "Force code generation for 32-bit environment") +endif(CMAKE_SIZEOF_VOID_P EQUAL 8) + +set(C_FLAGS "-pedantic -std=c89 -fvisibility=hidden -fstrict-aliasing") +set(C_FLAGS_WARN "-Wall -Wextra -Wcast-align -Wmissing-declarations -Wmissing-prototypes -Wconversion") +set(C_FLAGS_LINK "-Wl,--no-undefined") +if(CMAKE_HOST_UNIX) + set(C_FLAGS_UNIX "-fPIC") +endif(CMAKE_HOST_UNIX) +if(BUILD_32-BIT) + set(C_FLAGS "${C_FLAGS} -m32") +endif(BUILD_32-BIT) + +set(CMAKE_C_FLAGS "${C_FLAGS} ${C_FLAGS_UNIX} ${C_FLAGS_WARN} ${C_FLAGS_LINK}") set(CMAKE_C_FLAGS_DEBUG "-g -DDEBUG") -set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") +set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG") if(CMAKE_USE_PTHREADS_INIT) add_definitions(-DRSYS_USE_PTHREADS) endif() -add_definitions(-D_POSIX_C_SOURCE=200112L) ################################################################################ # Define targets ################################################################################ +set(VERSION_MAJOR 0) +set(VERSION_MINOR 0) +set(VERSION_PATCH 0) +configure_file(rsys_version.h.in ${CMAKE_CURRENT_SOURCE_DIR}/rsys_version.h) + +set(RSYS_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) +message(STATUS "Current library version: ${RSYS_VERSION}") + set(RSYS_FILES_SRC - clock_time.c - image.c - library.c - mem_allocator.c) - -set(RSYS_FILES_INC - atomic.h - clock_time.h - image.h - library.h - list.h - mem_allocator.h - ref_count.h - signal.h - rsys.h) + clock_time.c + image.c + library.c + mem_allocator.c + pthread/pthread_condition.c + pthread/pthread_mutex.c) +set(RSYS_FILES_INC_COMMON + atomic.h + clock_time.h + free_list.h + image.h + library.h + list.h + mem_allocator.h + mutex.h + ref_count.h + rsys.h + signal.h) + +set(RSYS_FILES_INC_INSTALL ${RSYS_FILES_INC_COMMON} rsys_version.h) +set(RSYS_FILES_INC_EDIT ${RSYS_FILES_INC_COMMON} rsys_version.h.in) add_library(rsys SHARED ${RSYS_FILES_SRC} ${RSYS_FILES_INC}) -target_link_libraries(rsys dl) -set_target_properties(rsys PROPERTIES DEFINE_SYMBOL RSYS_SHARED_BUILD) +target_link_libraries(rsys ${CMAKE_THREAD_LIBS_INIT}) +set_target_properties(rsys PROPERTIES + DEFINE_SYMBOL RSYS_SHARED_BUILD + VERSION ${RSYS_VERSION} + SOVERSION ${VERSION_MAJOR}) + +if(CMAKE_HOST_UNIX) + target_link_libraries(rsys dl) +endif(CMAKE_HOST_UNIX) + +source_group(src FILES ${RSYS_FILES_SRC} ${RSYS_FILES_INC_EDIT}) ################################################################################ # Add tests ################################################################################ -add_executable(test_library test_library.c) -target_link_libraries(test_library rsys) -add_test(test_library test_library) - -add_executable(test_list test_list.c) -target_link_libraries(test_list rsys) -add_test(test_list test_list) - -add_executable(test_mem_allocator test_mem_allocator.c) -target_link_libraries(test_mem_allocator rsys) -add_test(test_mem_allocator test_mem_allocator) - -add_executable(test_atomic test_atomic.c) -add_test(test_atomic test_atomic) - -add_executable(test_ref test_ref.c) -add_test(test_ref test_ref) +macro(new_test _name) + add_executable(${_name} ${_name}.c) + + set(_libraries ${ARGN}) + foreach(_lib ${_libraries}) + target_link_libraries(${_name} ${_lib}) + endforeach(_lib) + + add_test(${_name} ${_name}) +endmacro(new_test) + +new_test(test_atomic) +new_test(test_free_list rsys) +new_test(test_library rsys) +new_test(test_list rsys) +new_test(test_mem_allocator rsys) +new_test(test_ref) +new_test(test_signal rsys) +new_test(test_time rsys) if(NOT OPENMP_FOUND) message(STATUS "No OpenMP support: multi-threaded tests cannot be generated") else() - add_executable(test_mutex test_mutex.c) - target_link_libraries(test_mutex rsys) - add_test(test_mutex test_mutex) - - add_executable(test_condition test_condition.c) - add_test(test_condition test_condition) - + new_test(test_condition rsys) + new_test(test_mutex rsys) set_target_properties(test_mutex test_condition PROPERTIES COMPILE_FLAGS ${OpenMP_C_FLAGS}) set_target_properties(test_mutex test_condition PROPERTIES LINK_FLAGS ${OpenMP_C_FLAGS}) endif() -add_executable(test_signal test_signal.c) -target_link_libraries(test_signal rsys) -add_test(test_signal test_signal) - ################################################################################ # Define output & install directories ################################################################################ -install(TARGETS rsys LIBRARY DESTINATION lib) +install(TARGETS rsys + ARCHIVE DESTINATION bin + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin) install(FILES ${RSYS_FILES_INC} DESTINATION include/rsys) diff --git a/src/atomic.h b/src/atomic.h @@ -3,54 +3,64 @@ #include "rsys.h" -/******************************************************************************* +/* * GCC implementation - ******************************************************************************/ + */ #ifdef COMPILER_GCC -typedef int atomic_int_T; -typedef size_t atomic_size_T; - -#define ATOMIC_INCR(Atom) __sync_add_and_fetch((Atom), 1) -#define ATOMIC_DECR(Atom) __sync_sub_and_fetch((Atom), 1) -#define ATOMIC_ADD(Atom, Val) __sync_add_and_fetch((Atom), (Val)) -#define ATOMIC_SUB(Atom, Val) __sync_sub_and_fetch((Atom), (Val)) -#define ATOMIC_FETCH_AND_INCR(Atom) __sync_fetch_and_add((Atom), 1) -#define ATOMIC_FETCH_AND_DECR(Atom) __sync_fetch_and_sub((Atom), 1) -#define ATOMIC_FETCH_AND_ADD(Atom, Val) __sync_fetch_and_add((Atom), (Val)) -#define ATOMIC_FETCH_AND_SUB(Atom, Val) __sync_fetch_and_sub((Atom), (Val)) -#define ATOMIC_CMP_AND_SWAP(Atom, NewVal, Comparand) \ - __sync_val_compare_and_swap(Atom, Comparand, NewVal) - -/******************************************************************************* - * Other implementation - ******************************************************************************/ -#else -typedef int atomic_int_T; -typedef size_t atomic_size_T; - -#define ATOMIC_INCR(Atom) ASSERT(0), (void)0 -#define ATOMIC_DECR(Atom) ASSERT(0), (void)0 -#define ATOMIC_ADD(Atom, Val) ASSERT(0), (void)0 -#define ATOMIC_SUB(Atom, Val) ASSERT(0), (void)0 -#define ATOMIC_FETCH_AND_INCR(Atom) ASSERT(0), (void)0 -#define ATOMIC_FETCH_AND_DECR(Atom) ASSERT(0), (void)0 -#define ATOMIC_FETCH_AND_ADD(Atom, Val) ASSERT(0), (void)0 -#define ATOMIC_FETCH_AND_SUB(Atom, Val) ASSERT(0), (void)0 -#define ATOMIC_CMP_AND_SWAP(Atom, NewVal, Comparand) ASSERT(0), (void)0 +typedef int32_t atomic32_T; +typedef int64_t atomic64_T; -#endif /* COMPILER_XXX */ +#define ATOMIC_INCR(A) __sync_add_and_fetch((A), 1) +#define ATOMIC_DECR(A) __sync_sub_and_fetch((A), 1) +#define ATOMIC_ADD(A, V) __sync_fetch_and_add((A), (int32_t)V) +#define ATOMIC_SUB(A, V) __sync_fetch_and_sub((A), (int32_t)V) +#define ATOMIC_CAS(Atom, NewVal, Comparand) /* Return the initial value */ \ + __sync_val_compare_and_swap((Atom), (int32_t)(Comparand), (int32_t)(NewVal)) +#define ATOMIC_SET(A, V) ATOMIC_CAS((A), V, (*A)) /*Return the initial value*/ + +/* + * MSVC implementation + */ +#elif defined COMPILER_MSVC +# include <Windows.h> + +typedef long atomic32_T; +typedef LONGLONG atomic64_T; -/******************************************************************************* - * Generic implementation - ******************************************************************************/ -#define ATOMIC_FETCH_AND_STORE(Atom, Val, Res) \ - for(;;) { \ - *Res = *Atom; \ - if(ATOMIC_CMP_AND_SWAP(Atom, Val, *Res) == *Res) \ - break; \ - /* TODO add a yield/pause operation */ \ - } +#define ATOMIC_INCR(A) \ + sizeof(*A) == 32 ? _InterlockedIncrement(A) \ +: (sizeof(*A) == 64 ? _InterlockedIncrement64(A) \ +: FATAL("Unexpected atomic type"), (void)0) +#define ATOMIC_DECR(A) \ + sizeof(*A) == 32 ? _InterlockedDecrement(A) \ +: (sizeof(*A) == 64 ? _InterlockedDecrement64(A) \ +: FATAL("Unexpected atomic type"), (void)0) +#define ATOMIC_ADD(A, V) \ + sizeof(*A) == 32 ? _InterlockedExchangeAdd((A), (long)(V)) \ +: (sizeof(*A) == 64 ? _InterlockedExchangeAdd64((A), (LONGLONG)(V)) \ +: FATAL("Unexpected atomic type"), (void)0) +#define ATOMIC_SUB(A, V) \ + sizeof(*A) == 32 ? _InterlockedExchangeAdd((A), -(long)(V)) \ +: (sizeof(*A) == 64 ? _InterlockedExchangeAdd64((A), -(LONGLONG)(V)) \ +: FATAL("Unexpected atomic type"), (void)0) +#define ATOMIC_CAS(Atom, NewVal, Cmp) \ + sizeof(*A) == 32 \ +? _InterlockedCompareExchange((Atom), (long)(NewVal), (long)(Cmp)) \ +: (sizeof(*A) == 64 \ +? _InterlockedCompareExchange64((A), -(LONGLONG)(NewVal), (LONGLONG)(Cmp)) \ +: FATAL("Unexpected atomic type"), (void)0) +#define ATOMIC_SET(A, V) \ + sizeof(*A) == 32 ? _InterlockedExchange((A), (long)(V)) \ +: (sizeof(*A) == 64 ? _InterlockedExchange64((A), (LONGLONG)(V)) \ +: FATAL("Unexpected atomic type"), (void)0) + +/* + * Terra incognita + */ +#else +# error "Unsupported compiler" +#endif /* COMPILER_XXX */ #endif /* ATOMIC_H */ diff --git a/src/clock_time.c b/src/clock_time.c @@ -1,18 +1,68 @@ +#define _POSIX_C_SOURCE 200112L + #include "clock_time.h" -#include <inttypes.h> +#include <time.h> #include <string.h> -#define NSEC_PER_USEC 1000L -#define NSEC_PER_MSEC (1000L * NSEC_PER_USEC) -#define NSEC_PER_SEC (1000L * NSEC_PER_MSEC) -#define NSEC_PER_MIN (60L * NSEC_PER_SEC) -#define NSEC_PER_HOUR (60L * NSEC_PER_MIN) -#define NSEC_PER_DAY (24L * NSEC_PER_HOUR) +#define TIME_TO_NSEC(Time) ((Time)->nsec + (Time)->sec * 1000000000L) +#define NSEC_PER_USEC (int64_t)1000 +#define NSEC_PER_MSEC ((int64_t)1000 * NSEC_PER_USEC) +#define NSEC_PER_SEC ((int64_t)1000 * NSEC_PER_MSEC) +#define NSEC_PER_MIN ((int64_t)60 * NSEC_PER_SEC) +#define NSEC_PER_HOUR ((int64_t)60 * NSEC_PER_MIN) +#define NSEC_PER_DAY ((int64_t)24 * NSEC_PER_HOUR) + +void +time_current(struct time* t) +{ + struct timespec time; + int err = 0; (void) err; + ASSERT(t); + + err = clock_gettime(CLOCK_REALTIME, &time); + ASSERT(err == 0); + t->sec = (int64_t)time.tv_sec; + t->nsec = (int64_t)time.tv_nsec; +} + +void +time_sleep(const struct time* t) +{ + struct timespec time; + time.tv_sec = (time_t)t->sec; + time.tv_nsec = (long)t->nsec; + clock_nanosleep(CLOCK_REALTIME, 0, &time, NULL); +} + +void +time_sub(struct time* res, const struct time* a, const struct time* b) +{ + ASSERT(res && a && b); + res->sec = a->sec - b->sec; + res->nsec = a->nsec - b->nsec; + if(res->nsec < 0) { + --res->sec; + res->nsec += 1000000000L; + } +} + +void +time_add(struct time* res, const struct time* a, const struct time* b) +{ + ASSERT(res && a && b); + + res->sec = a->sec + b->sec; + res->nsec = a->nsec + b->nsec; + if(res->nsec >= 1000000000L) { + ++res->sec; + res->nsec -= 1000000000L; + } +} int64_t -time_val(const time_T* time, enum time_unit unit) +time_val(const struct time* time, enum time_unit unit) { - int64_t val = TIME_TO_NSEC__(time); + int64_t val = TIME_TO_NSEC(time); switch(unit) { case TIME_NSEC: /* Do nothing. */ @@ -42,7 +92,7 @@ time_val(const time_T* time, enum time_unit unit) void time_dump - (const time_T* time, + (const struct time* time, int flag, size_t* real_dump_len, char* dump, @@ -53,11 +103,11 @@ time_dump ASSERT(time && (!max_dump_len || dump)); - #define DUMP(time, suffix) \ + #define DUMP(Time, Suffix) \ { \ const int len = snprintf \ (dump, available_dump_space, \ - "%" PRIi64 " %s",time, time > 1 ? suffix "s ": suffix " "); \ + "%li %s", (long)Time, Time > 1 ? Suffix "s ": Suffix " "); \ ASSERT(len >= 0); \ if(real_dump_len) { \ real_dump_len += len; \ @@ -72,7 +122,7 @@ time_dump } \ } (void) 0 - time_nsec = TIME_TO_NSEC__(time); + time_nsec = TIME_TO_NSEC(time); if(flag & TIME_DAY) { const int64_t nb_days = time_nsec / NSEC_PER_DAY; DUMP(nb_days, "day"); diff --git a/src/clock_time.h b/src/clock_time.h @@ -3,35 +3,11 @@ #include "rsys.h" -#ifndef PLATFORM_UNIX - #error "Unsupported platform" -#endif - -#if _POSIX_C_SOURCE < 200112L - #include <sys/time.h> - - #define CURRENT_TIME__(Time) gettimeofday((Time), NULL) - #define GREATER_TIME_UNIT__(Time) (Time)->tv_sec - #define SMALLER_TIME_UNIT__(Time) (Time)->tv_usec - #define GREATER_TO_SMALLER_TIME_UNIT__ 1000000L - #define TIME_TO_NSEC__(Time) \ - (((Time)->tv_usec + (Time)->tv_sec * 1000000L) * 1000L) - - typedef struct timeval time_T; -#else - #include <time.h> - - #define CURRENT_TIME__(Time) clock_gettime(CLOCK_REALTIME, (Time)) - #define GREATER_TIME_UNIT__(Time) (Time)->tv_sec - #define SMALLER_TIME_UNIT__(Time) (Time)->tv_nsec - #define GREATER_TO_SMALLER_TIME_UNIT__ 1000000000L - #define TIME_TO_NSEC__(Time) \ - ((time)->tv_nsec + (Time)->tv_sec * 1000000000L) - - typedef struct timespec time_T; -#endif - -#include <stddef.h> +struct time { + /* Internal data */ + int64_t sec; + int64_t nsec; +}; enum time_unit { TIME_NSEC = BIT(0), @@ -43,53 +19,38 @@ enum time_unit { TIME_DAY = BIT(6) }; -static FINLINE void -time_current(time_T* time) -{ - int err = 0; (void) err; - ASSERT(time); - err = CURRENT_TIME__(time); - ASSERT(err == 0); - -} +#ifdef __cplusplus +extern "C" { +#endif -static FINLINE void -time_sub(time_T* res, const time_T* a, const time_T* b) -{ - ASSERT(res && a && b); - GREATER_TIME_UNIT__(res) = GREATER_TIME_UNIT__(a) - GREATER_TIME_UNIT__(b); - SMALLER_TIME_UNIT__(res) = SMALLER_TIME_UNIT__(a) - SMALLER_TIME_UNIT__(b); - if(SMALLER_TIME_UNIT__(res) < 0) { - --GREATER_TIME_UNIT__(res); - SMALLER_TIME_UNIT__(res) += GREATER_TO_SMALLER_TIME_UNIT__; - } -} +RSYS_API void +time_current + (struct time* time); -static FINLINE void -time_add(time_T* res, const time_T* a, const time_T* b) -{ - ASSERT(res && a && b); +RSYS_API void +time_sleep + (const struct time* time); - GREATER_TIME_UNIT__(res) = GREATER_TIME_UNIT__(a) + GREATER_TIME_UNIT__(b); - SMALLER_TIME_UNIT__(res) = SMALLER_TIME_UNIT__(a) + SMALLER_TIME_UNIT__(b); - if(SMALLER_TIME_UNIT__(res) >= GREATER_TO_SMALLER_TIME_UNIT__) { - ++GREATER_TIME_UNIT__(res); - SMALLER_TIME_UNIT__(res) -= GREATER_TO_SMALLER_TIME_UNIT__; - } -} +RSYS_API void +time_sub + (struct time* res, + const struct time* a, + const struct time* b); -#ifdef __cplusplus -extern "C" { -#endif +RSYS_API void +time_add + (struct time* res, + const struct time* a, + const struct time* b); RSYS_API int64_t time_val - (const time_T* time, + (const struct time* time, enum time_unit unit); RSYS_API void time_dump - (const time_T* time, + (const struct time* time, int flag, size_t* real_dump_len, /* May be NULL. */ char* dump, /* May be NULL. */ diff --git a/src/condition.h b/src/condition.h @@ -5,18 +5,13 @@ #include "mutex.h" struct cond; +struct mutex; -static FINLINE void cond_init(struct cond* cond); -static FINLINE void cond_destroy(struct cond* cond); -static FINLINE void cond_wait(struct cond* cond, struct mutex* mutex); -static FINLINE void cond_signal(struct cond* cond); -static FINLINE void cond_broadcast(struct cond* cond); - -#ifdef RSYS_USE_PTHREADS - #include "pthread/condition.h" -#else - #error "No supported thread library is defined" -#endif +RSYS_API struct cond* cond_create(void); /* NULL <=> error */ +RSYS_API void cond_destroy(struct cond* cond); +RSYS_API void cond_wait(struct cond* cond, struct mutex* mutex); +RSYS_API void cond_signal(struct cond* cond); +RSYS_API void cond_broadcast(struct cond* cond); #endif /* CONDITION_H */ diff --git a/src/free_list.h b/src/free_list.h @@ -0,0 +1,136 @@ +#ifndef FITEM_TYPE +# ifndef FREE_LIST_H +# define FREE_LIST_H + +#include "rsys.h" + +#define FITEM \ + struct { \ + struct fid id; \ + uint32_t next; \ + } fitem__ + +struct fid { + uint32_t index; /* Index into the free list */ + uint32_t name; /* Unique id that identifies this item */ +}; + +static const struct fid FID_NULL = { UINT32_MAX, UINT32_MAX }; +#define IS_FID_NULL(Fid) ((Fid).index == UINT32_MAX) +#define FID_EQ(Fid0, Fid1) \ + ((Fid0).index == (Fid1).index && (Fid0).name == (Fid1).name) + +# endif /* FREE_LIST_H */ +#else + +#define FLIST_FUNC__(Func) CONCAT(CONCAT(CONCAT(flist_, FITEM_TYPE), _), Func) +#define FLIST_TYPE__ CONCAT(flist_, FITEM_TYPE) + +#include "mem_allocator.h" +#include <string.h> + +struct FLIST_TYPE__ { + uint32_t head; + uint32_t name_next; + struct FITEM_TYPE* items; + uint32_t nitems; + struct mem_allocator* allocator; +}; + +static FINLINE void +FLIST_FUNC__(init) + (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + struct FLIST_TYPE__* list) +{ + ASSERT(list); + list->head = UINT32_MAX; + list->name_next = 0; + list->items = NULL; + list->nitems = 0; + list->allocator = allocator ? allocator : &mem_default_allocator; +} + +static FINLINE void +FLIST_FUNC__(release)(struct FLIST_TYPE__* list) +{ + ASSERT(list); + MEM_FREE(list->allocator, list->items); +} + +static FINLINE char +FLIST_FUNC__(hold)(struct FLIST_TYPE__* list, struct fid id) +{ + ASSERT(list); + return id.index < list->nitems + && list->items[id.index].fitem__.id.name == id.name; +} + +static FINLINE struct FITEM_TYPE* +FLIST_FUNC__(get)(struct FLIST_TYPE__* list, struct fid id) +{ + ASSERT(list); + if(FLIST_FUNC__(hold)(list, id)) { + return list->items + id.index; + } else { + return NULL; + } +} + +static INLINE struct fid +FLIST_FUNC__(add)(struct FLIST_TYPE__* list) +{ + struct fid id; + ASSERT(list); + + id.name = list->name_next++; + if(list->head != UINT32_MAX) { + id.index = list->head; + list->items[id.index].fitem__.id = id; + list->head = list->items[list->head].fitem__.next; + } else { + const uint32_t nitems_new = list->nitems ? list->nitems * 2 : 16; + uint32_t iitem = 0; + struct FITEM_TYPE item; + memset(&item, 0, sizeof(struct FITEM_TYPE)); + + id.index = list->nitems; + list->items = MEM_REALLOC + (list->allocator, + list->items, + nitems_new * sizeof(struct FITEM_TYPE)); + FOR_EACH(iitem, list->nitems, nitems_new - 1) { + list->items[iitem].fitem__.next = iitem + 1; + } + list->items[id.index].fitem__.id = id; + list->items[nitems_new - 1].fitem__.next = UINT32_MAX; + list->head = list->nitems + 1; + list->nitems = nitems_new; + } + return id; +} + +static FINLINE void +FLIST_FUNC__(del)(struct FLIST_TYPE__* list, struct fid id) +{ + ASSERT(list); + if(FLIST_FUNC__(hold)(list, id)) { + struct FITEM_TYPE* item = FLIST_FUNC__(get)(list, id); + item->fitem__.id.name = UINT32_MAX; + item->fitem__.next = list->head; + list->head = item->fitem__.id.index; + } +} + +static FINLINE struct fid +CONCAT(FITEM_TYPE,_id_get)(const struct FITEM_TYPE* item) +{ + ASSERT(item); + return item->fitem__.id; +} + +#undef FLIST_TYPE__ +#undef FLIST_FUNC__ +#undef FITEM_TYPE + +#endif /* ifdef FITEM_TYPE */ + diff --git a/src/image.c b/src/image.c @@ -1,3 +1,4 @@ +#define _POSIX_C_SOURCE 200112L /* snprintf support */ #include "image.h" #include <stdio.h> #include <string.h> @@ -22,22 +23,23 @@ image_ppm_write goto error; } - #define FWRITE(fp, string) \ + #define FWRITE(Fp, String) \ { \ - const size_t i = fwrite(string, sizeof(char), strlen(string), fp); \ - if( i != strlen(string) * sizeof(char) ) { \ + const size_t i = fwrite(String, sizeof(char), strlen(String), Fp); \ + if( i != strlen(String) * sizeof(char) ) { \ goto error; \ } \ } (void)0 - #define SNPRINTF(b, sz, ...) \ + + #define SNPRINTF(Buf, Sz, Str, Arg0, Arg1, Arg2) \ { \ - const int i = snprintf(b, sz, __VA_ARGS__); \ + const int i = snprintf(Buf, Sz, Str, Arg0, Arg1, Arg2); \ if( i >= BUFSIZ ) { \ goto error; \ } \ } (void)0 - SNPRINTF(buf, BUFSIZ, "%s\n%i %i\n%i\n", "P3\n", width, height, 255); + SNPRINTF(buf, BUFSIZ, "P3\n\n%i %i\n%i\n", width, height, 255); FWRITE(fp, buf); if(Bpp) { @@ -68,4 +70,3 @@ error: goto exit; } - diff --git a/src/library.c b/src/library.c @@ -1,14 +1,51 @@ #include "library.h" + +#if defined(OS_WINDOWS) +#include <Windows.h> +void* +library_open(const char* filename) +{ + if(!filename) + return NULL; + return (void*)LoadLibraryA(filename); +} + +int +library_close(void* lib) +{ + BOOL b; + + if(!lib) + return -1; + + b = FreeLibrary((HMODULE)lib); + if(!b) + return -1; + + return 0; +} + +void* +library_get_symbol(void* lib, const char* sym) +{ + union { FARPROC proc; void* ptr; } ucast; + STATIC_ASSERT(sizeof(FARPROC) == sizeof(void*), Unexpected_type_size); + ucast.proc = GetProcAddress((HMODULE)lib, sym); + return ucast.ptr; +} + +#elif defined(OS_UNIX) #include <dlfcn.h> #include <stdio.h> void* library_open(const char* filename) { + void* handle = NULL; if(!filename) return NULL; - void* handle = dlopen(filename, RTLD_NOW|RTLD_GLOBAL); + handle = dlopen(filename, RTLD_NOW|RTLD_GLOBAL); if(!handle) { fprintf(stderr, "%s\n", dlerror()); } @@ -18,11 +55,14 @@ library_open(const char* filename) void* library_get_symbol(void* lib, const char* sym) { + void* tmp_sym = NULL; + char* err = NULL; + if(!lib || !sym) return NULL; - void* tmp_sym = dlsym(lib, sym); - char* err = dlerror(); + tmp_sym = dlsym(lib, sym); + err = dlerror(); if(err == NULL) { return tmp_sym; } else { @@ -34,10 +74,11 @@ library_get_symbol(void* lib, const char* sym) int library_close(void* handle) { + int err = 0; if(!handle) return -1; - const int err = dlclose(handle); + err = dlclose(handle); if(err) { fprintf(stderr, "%s\n", dlerror()); return -1; @@ -45,4 +86,5 @@ library_close(void* handle) return 0; } +#endif /* OS_<XXX> */ diff --git a/src/library.h b/src/library.h @@ -3,10 +3,6 @@ #include "rsys.h" -#ifdef PLATFORM_UNIX - #define SHARED_LIBRARY_NAME(Lib) "lib"Lib".so" -#endif - #ifdef __cplusplus extern "C" { #endif diff --git a/src/list.h b/src/list.h @@ -36,22 +36,22 @@ del_node__(struct list_node* prev, struct list_node* next) * Helper macros ******************************************************************************/ #define LIST_FOR_EACH(Pos, List) \ - for(struct list_node* Pos = (List)->next; Pos != (List); Pos = Pos->next) + for(Pos = (List)->next; Pos != (List); Pos = Pos->next) #define LIST_FOR_EACH_REVERSE(Pos, List) \ - for(struct list_node* Pos = (List)->prev; Pos != (List); Pos = Pos->prev) + for(Pos = (List)->prev; Pos != (List); Pos = Pos->prev) /* Safe against removal of list entry. */ -#define LIST_FOR_EACH_SAFE(Pos, List) \ - for(struct list_node* Pos = (List)->next,* tmp ## COUNTER ## __ = Pos->next; \ - Pos != (List); \ - Pos = tmp ## COUNTER ## __ , tmp ## COUNTER ## __ = Pos->next) +#define LIST_FOR_EACH_SAFE(Pos, Tmp, List) \ + for((Pos) = (List)->next, (Tmp) = (Pos)->next; \ + (Pos) != (List); \ + (Pos) = Tmp, Tmp = (Pos)->next) /* Safe against removal of list entry. */ -#define LIST_FOR_EACH_REVERSE_SAFE(Pos, List) \ - for(struct list_node* Pos = (List)->prev,* tmp ## COUNTER ## __ = Pos->prev; \ - Pos != (List); \ - Pos = tmp ## COUNTER ## __, tmp ## COUNTER ## __ = Pos->prev) +#define LIST_FOR_EACH_REVERSE_SAFE(Pos, Tmp, List) \ + for((Pos) = (List)->prev, (Tmp) = (Pos)->prev; \ + (Pos) != (List); \ + (Pos) = Tmp, Tmp = (Pos)->prev) /****************************************************************************** * Node list functions diff --git a/src/mem_allocator.c b/src/mem_allocator.c @@ -1,21 +1,185 @@ +#define _POSIX_C_SOURCE 200112L /* snprintf support */ #include "atomic.h" #include "mem_allocator.h" #include "math.h" + +#include <errno.h> #include <malloc.h> #include <string.h> #define IS_POWER_OF_2(i) ((i) > 0 && ((i) & ((i)-1)) == 0) +#ifdef OS_WINDOWS +# ifdef MINGW + /* On MINGW the _aligned_msize function is not defined. THe size is thus + * stored into the memory block header */ +# define MEM_HEADER_SIZE (2 * sizeof(size_t)) +# else +# define MEM_HEADER_SIZE (1 * sizeof(size_t)) +# endif +#endif + +struct alloc_counter { + atomic64_T nb_allocs; + atomic64_T allocated_size; +}; + +/******************************************************************************* + * Common allocation functions + ******************************************************************************/ +static struct alloc_counter g_alloc_counter = { 0, 0 }; + +void* +mem_alloc(const size_t size) +{ + void* mem = NULL; + if(size) { +#if defined(OS_UNIX) + mem = malloc(size); +#elif defined(OS_WINDOWS) + const size_t DEFAULT_ALIGNMENT = 16; + mem = _aligned_offset_malloc + (size + MEM_HEADER_SIZE, DEFAULT_ALIGNMENT, MEM_HEADER_SIZE); +# ifdef MINGW + ((size_t*)mem)[0] = DEFAULT_ALIGNMENT; + ((size_t*)mem)[1] = size + MEM_HEADER_SIZE; +# endif + mem = ((char*)mem) + MEM_HEADER_SIZE; +#endif + } + if(mem) { + ATOMIC_ADD(&g_alloc_counter.allocated_size, mem_size(mem)); + ATOMIC_INCR(&g_alloc_counter.nb_allocs); + } + return mem; +} + +void* +mem_calloc(const size_t nelmts, const size_t size) +{ + void* mem = NULL; + const size_t alloc_size = nelmts * size; + mem = mem_alloc(alloc_size); + if(mem) { + memset(mem, 0, alloc_size); + } + return mem; +} + +void* +mem_realloc(void* mem, const size_t size) +{ + void* new_mem = NULL; + + if(mem == NULL) { + new_mem = mem_alloc(size); + } else if(size == 0) { + mem_free(mem); + } else { + const size_t old_size = mem_size(mem); + + ASSERT + ( old_size < SIZE_MAX + && g_alloc_counter.allocated_size >= (int64_t)old_size); + ATOMIC_SUB( &g_alloc_counter.allocated_size, old_size); + +#if defined(OS_WINDOWS) + mem = ((char*)mem) - MEM_HEADER_SIZE; + new_mem = _aligned_offset_realloc + (mem, size + MEM_HEADER_SIZE, ((size_t*)mem)[0], MEM_HEADER_SIZE); +# ifdef MINGW + ((size_t*)new_mem)[1] = size + MEM_HEADER_SIZE; +# endif + new_mem = ((char*)new_mem) + MEM_HEADER_SIZE; +#elif defined(OS_UNIX) + new_mem = realloc( mem, size ); +#endif + ATOMIC_ADD(&g_alloc_counter.allocated_size, mem_size(new_mem)); + } + return new_mem; + +} +void* +mem_alloc_aligned(const size_t size, const size_t alignment) +{ + void* mem = NULL; + + if(size + && IS_POWER_OF_2( alignment ) + && alignment <= 32768 /* 32 KB */) { +#if defined(OS_WINDOWS) + mem = _aligned_offset_malloc + (size + MEM_HEADER_SIZE, alignment, MEM_HEADER_SIZE); + ((size_t*)mem)[0] = alignment; +# ifdef MINGW + ((size_t*)mem)[1] = size + MEM_HEADER_SIZE; +# endif + mem = ((char*)mem) + MEM_HEADER_SIZE; +#elif defined(OS_UNIX) + const int result = posix_memalign + (&mem, (alignment < sizeof(void*)) ? sizeof(void*) : alignment, size); + (void)result; /* avoid warning in Release */ + /* The following assert may not occur due to previous conditions */ + ASSERT(result != EINVAL); + ASSERT((result != ENOMEM) || (mem == NULL)); +#endif + if(mem) { + ATOMIC_ADD(&g_alloc_counter.allocated_size, mem_size(mem)); + ATOMIC_INCR(&g_alloc_counter.nb_allocs); + } + } + return mem; +} + +void +mem_free(void* mem) +{ + if(mem) { + ASSERT + ( g_alloc_counter.nb_allocs != 0 + && mem_size(mem) < SIZE_MAX + && g_alloc_counter.allocated_size >= (int64_t)mem_size(mem)); + ATOMIC_SUB(&g_alloc_counter.allocated_size, mem_size(mem)); + ATOMIC_DECR(&g_alloc_counter.nb_allocs); +#if defined(OS_WINDOWS) + mem = ((char*)mem) - MEM_HEADER_SIZE; + _aligned_free( mem ); +#elif defined(OS_UNIX) + free( mem ); +#endif + } +} + +size_t +mem_size(void* mem) +{ + size_t mem_size = 0; + if(mem) { +#if defined(OS_WINDOWS) + void* raw_mem = ((char*)mem) - MEM_HEADER_SIZE; +# ifdef MINGW + mem_size = ((size_t*)raw_mem)[1]; +# else + mem_size = _aligned_msize(raw_mem, ((size_t*)raw_mem)[0], sizeof(size_t)); +# endif +#elif defined(OS_UNIX) + mem_size = malloc_usable_size(mem); +#endif + } + return mem_size; +} + +size_t +mem_allocated_size(void) +{ + return (size_t)g_alloc_counter.allocated_size; +} + /******************************************************************************* * Default allocator functions ******************************************************************************/ #define TRACK_DEFAULT_ALLOC /* Enable the tracking of default allocations */ -struct alloc_counter { - atomic_size_T nb_allocs; - atomic_size_T allocated_size; -}; - static void* default_alloc (void* data, @@ -29,18 +193,18 @@ default_alloc (void)fileline; if(size) { - mem = malloc(size); - #ifndef TRACK_DEFAULT_ALLOC + mem = mem_alloc(size); +#ifndef TRACK_DEFAULT_ALLOC (void)data; - #else +#else ASSERT(data); if(mem) { struct alloc_counter* counter = data; - const size_t size_mem = malloc_usable_size(mem); + const size_t size_mem = mem_size(mem); ATOMIC_ADD(&counter->allocated_size, size_mem); ATOMIC_INCR(&counter->nb_allocs); } - #endif /* TRACK_DEFAULT_ALLOC */ +#endif /* TRACK_DEFAULT_ALLOC */ } return mem; } @@ -49,20 +213,20 @@ static void default_free(void* data, void* mem) { if(mem) { - #ifndef TRACK_DEFAULT_ALLOC +#ifndef TRACK_DEFAULT_ALLOC (void)data; - #else +#else struct alloc_counter* counter = data; - size_t size_mem = malloc_usable_size(mem); + size_t size_mem = mem_size(mem); ASSERT ( (data != NULL) & (counter->nb_allocs != 0) - & (counter->allocated_size >= size_mem)); + & (counter->allocated_size >= (int64_t)size_mem)); ATOMIC_SUB(&counter->allocated_size, size_mem); ATOMIC_DECR(&counter->nb_allocs); - #endif /* TRACK_DEFAULT_ALLOC */ - free(mem); +#endif /* TRACK_DEFAULT_ALLOC */ + mem_free(mem); } } @@ -94,12 +258,12 @@ default_realloc { void* new_mem = NULL; - #ifndef TRACK_DEFAULT_ALLOC +#ifndef TRACK_DEFAULT_ALLOC (void)data; (void)filename; (void)fileline; - new_mem = realloc(mem, size); - #else + new_mem = mem_realloc(mem, size); +#else ASSERT(data); if(!mem) { new_mem = default_alloc(data, size, filename, fileline); @@ -108,22 +272,23 @@ default_realloc default_free(data, mem); } else { struct alloc_counter* counter = data; - const size_t size_old = malloc_usable_size(mem); + const size_t size_old = mem_size(mem); + size_t size_new = 0; - ASSERT(counter->allocated_size >= size_old); + ASSERT(counter->allocated_size >= (int64_t)size_old); ATOMIC_SUB(&counter->allocated_size, size_old); - new_mem = realloc(mem, size); - const size_t size_new = malloc_usable_size(new_mem); + new_mem = mem_realloc(mem, size); + size_new = mem_size(new_mem); ATOMIC_ADD(&counter->allocated_size, size_new); } } - #endif /* TRACK_DEFAULT_ALLOC */ +#endif /* TRACK_DEFAULT_ALLOC */ return new_mem; } static void* -default_aligned_alloc +default_alloc_aligned (void* data, const size_t size, const size_t alignment, @@ -136,33 +301,40 @@ default_aligned_alloc (void)fileline; if(size && IS_POWER_OF_2(alignment)) { - mem = memalign(alignment, size); - #ifndef TRACK_DEFAULT_ALLOC + mem = mem_alloc_aligned(size, alignment); +#ifndef TRACK_DEFAULT_ALLOC (void)data; #else ASSERT(data); if(mem) { struct alloc_counter* counter = data; - const size_t size_mem = malloc_usable_size(mem); + const size_t size_mem = mem_size(mem); ATOMIC_ADD(&counter->allocated_size, size_mem); ATOMIC_INCR(&counter->nb_allocs); } - #endif /* TRACK_DEFAULT_ALLOC */ +#endif /* TRACK_DEFAULT_ALLOC */ } return mem; } static size_t +default_mem_size(void* data, void* mem) +{ + (void)data; + return mem_size(mem); +} + +static size_t default_allocated_size(const void* data) { - #ifndef TRACK_DEFAULT_ALLOC +#ifndef TRACK_DEFAULT_ALLOC (void)data; return 0; - #else +#else const struct alloc_counter* counter = data; ASSERT(counter != NULL); - return counter->allocated_size; - #endif /* TRACK_DEFAULT_ALLOC */ + return (size_t)counter->allocated_size; +#endif /* TRACK_DEFAULT_ALLOC */ } static size_t @@ -171,12 +343,13 @@ default_dump char* dump, const size_t max_dump_len) { - #ifndef TRACK_DEFAULT_ALLOC +#ifndef TRACK_DEFAULT_ALLOC (void)data; if(dump && max_dump_len) dump[0] = '\0'; return 0; - #else + +#else const struct alloc_counter* counter = data; size_t dump_len = 0; int len = 0; @@ -186,17 +359,17 @@ default_dump len = snprintf (dump, max_dump_len, - "%zu bytes allocated in %zu allocations.", - counter->allocated_size, - counter->nb_allocs); + "%lu bytes allocated in %lu allocations.", + (unsigned long)counter->allocated_size, + (unsigned long)counter->nb_allocs); ASSERT(len >= 0); dump_len = (size_t)len; if((size_t)len >= (max_dump_len - 1)) /* -1 <=> null char. */ - dump[max_dump_len] = '\0'; + dump[max_dump_len-1] = '\0'; return dump_len; - #endif +#endif } /******************************************************************************* @@ -220,7 +393,7 @@ struct mem_node { }; static void* -proxy_aligned_alloc +proxy_alloc_aligned (void* data, const size_t size, const size_t align, @@ -239,12 +412,12 @@ proxy_aligned_alloc if((IS_POWER_OF_2(align) == 0) || align > 32768) return NULL; - align_adjusted = align < PROXY_DEFAULT_ALIGNMENT + align_adjusted = align < PROXY_DEFAULT_ALIGNMENT ? PROXY_DEFAULT_ALIGNMENT : align; node_header_size = ALIGN_SIZE(sizeof(struct mem_node), align_adjusted); node_size = node_header_size + size; - node = MEM_ALIGNED_ALLOC(proxy_data->allocator, node_size, align_adjusted); + node = MEM_ALLOC_ALIGNED(proxy_data->allocator, node_size, align_adjusted); if(!node) return NULL; @@ -269,7 +442,7 @@ proxy_alloc const char* filename, const unsigned int fileline) { - return proxy_aligned_alloc + return proxy_alloc_aligned (data, size, PROXY_DEFAULT_ALIGNMENT, filename, fileline); } @@ -282,7 +455,7 @@ proxy_calloc const unsigned int fileline) { size_t allocation_size = nbelmts * size; - void* mem = proxy_aligned_alloc + void* mem = proxy_alloc_aligned (data, allocation_size, PROXY_DEFAULT_ALIGNMENT, filename, fileline); if(mem) mem = memset(mem, 0, allocation_size); @@ -329,7 +502,7 @@ proxy_realloc proxy_free(data, mem); return NULL; } else if(mem == NULL) { - return proxy_aligned_alloc + return proxy_alloc_aligned (data, size, PROXY_DEFAULT_ALIGNMENT, filename, fileline); } else { struct mem_node* node = NULL; @@ -343,7 +516,7 @@ proxy_realloc if(node->size == size) { return mem; } else { - void* dst = proxy_aligned_alloc + void* dst = proxy_alloc_aligned (data, size, alignment, filename, fileline); if(!dst) { proxy_free(data, mem); @@ -358,6 +531,18 @@ proxy_realloc } static size_t +proxy_mem_size(void* data, void* mem) +{ + const uintptr_t alignment = (uintptr_t) + (((char*)mem)[-1] | (((char*)mem)[-2] << 8)); + struct mem_node* node = (struct mem_node*) + ((uintptr_t)mem - ALIGN_SIZE(sizeof(struct mem_node), alignment)); + struct proxy_data* proxy_data = (struct proxy_data*)data; + ASSERT( data ); + return MEM_SIZE(proxy_data->allocator, node); +} + +static size_t proxy_allocated_size(const void* data) { const struct proxy_data* proxy_data = NULL; @@ -367,7 +552,7 @@ proxy_allocated_size(const void* data) ASSERT(data); proxy_data = data; for(node = proxy_data->node_list; node != NULL; node = node->next) { - allocated_size += malloc_usable_size(node); + allocated_size += mem_size(node); } return allocated_size; } @@ -393,7 +578,7 @@ proxy_dump avaible_dump_space, "%s: %lu bytes allocated at %s:%u%s", proxy_data->name, - (long unsigned)malloc_usable_size(node), + (long unsigned)mem_size(node), node->filename ? node->filename : "none", node->fileline, node->next ? ".\n" : "."); @@ -424,8 +609,9 @@ EXPORT_SYM struct mem_allocator mem_default_allocator = { default_alloc, default_calloc, default_realloc, - default_aligned_alloc, + default_alloc_aligned, default_free, + default_mem_size, default_allocated_size, default_dump, (void*)&default_alloc_counter @@ -455,7 +641,8 @@ mem_init_proxy_allocator proxy_allocator->alloc = proxy_alloc; proxy_allocator->calloc = proxy_calloc; proxy_allocator->realloc = proxy_realloc; - proxy_allocator->aligned_alloc = proxy_aligned_alloc; + proxy_allocator->mem_size = proxy_mem_size; + proxy_allocator->alloc_aligned = proxy_alloc_aligned; proxy_allocator->free = proxy_free; proxy_allocator->allocated_size = proxy_allocated_size; proxy_allocator->dump = proxy_dump; diff --git a/src/mem_allocator.h b/src/mem_allocator.h @@ -28,7 +28,7 @@ struct mem_allocator { const char* filename, const unsigned int fileline); - void* (*aligned_alloc) + void* (*alloc_aligned) (void* data, const size_t size, const size_t alignment, @@ -39,6 +39,10 @@ struct mem_allocator { (void* data, void* mem); + size_t (*mem_size) + (void* data, + void* mem); + size_t (*allocated_size) (const void* data); @@ -65,13 +69,16 @@ extern struct mem_allocator mem_default_allocator; #define MEM_REALLOC(Allocator, Mem, Size) \ ((Allocator)->realloc((Allocator)->data, (Mem), (Size), __FILE__, __LINE__)) -#define MEM_ALIGNED_ALLOC(Allocator, Size, Alignment) \ - ((Allocator)->aligned_alloc \ +#define MEM_ALLOC_ALIGNED(Allocator, Size, Alignment) \ + ((Allocator)->alloc_aligned \ ((Allocator)->data, (Size), (Alignment), __FILE__, __LINE__)) #define MEM_FREE(Allocator, Mem) \ ((Allocator)->free((Allocator)->data, (Mem))) +#define MEM_SIZE(Allocator, Mem) \ + ((Allocator)->mem_size((Allocator)->data, (Mem))) + #define MEM_ALLOCATED_SIZE(Allocator) \ ((Allocator)->allocated_size((Allocator)->data)) @@ -87,13 +94,23 @@ extern struct mem_allocator mem_default_allocator; && NULL != (Allocator)->allocated_size \ && NULL != (Allocator)->dump) -/******************************************************************************* - * Proxy allocator - ******************************************************************************/ #ifdef __cplusplus extern "C" { #endif +/******************************************************************************* + * Regular allocation functions + ******************************************************************************/ +RSYS_API void* mem_alloc(const size_t size); +RSYS_API void* mem_calloc(const size_t nelmts, const size_t size); +RSYS_API void* mem_realloc(void* ptr, const size_t size); +RSYS_API void* mem_alloc_aligned(const size_t size, const size_t alignment); +RSYS_API void mem_free(void* ptr); +RSYS_API size_t mem_size(void* ptr); +RSYS_API size_t mem_allocated_size(void); +/******************************************************************************* + * Proxy allocator + ******************************************************************************/ RSYS_API void mem_init_proxy_allocator (const char* proxy_name, diff --git a/src/mutex.h b/src/mutex.h @@ -3,29 +3,31 @@ #include "rsys.h" +#ifdef __cplusplus +extern "C" { +#endif + struct mutex; -static FINLINE void mutex_init(struct mutex* mutex); -static FINLINE void mutex_destroy(struct mutex* mutex); -static FINLINE void mutex_lock(struct mutex* mutex); -static FINLINE void mutex_unlock(struct mutex* mutex); +RSYS_API struct mutex* mutex_create(void); /* NULL <=> error */ +RSYS_API void mutex_destroy(struct mutex* mutex); +RSYS_API void mutex_lock(struct mutex* mutex); +RSYS_API void mutex_unlock(struct mutex* mutex); struct mutex_spin; -static FINLINE void mutex_spin_init(struct mutex_spin* mutex); -static FINLINE void mutex_spin_destroy(struct mutex_spin* mutex); -static FINLINE void mutex_spin_lock(struct mutex_spin* mutex); -static FINLINE void mutex_spin_unlock(struct mutex_spin* mutex); +RSYS_API struct mutex_spin* mutex_spin_create(void); /* NULL <=> error */ +RSYS_API void mutex_spin_destroy(struct mutex_spin* mutex); +RSYS_API void mutex_spin_lock(struct mutex_spin* mutex); +RSYS_API void mutex_spin_unlock(struct mutex_spin* mutex); struct mutex_rw; -static FINLINE void mutex_rw_init(struct mutex_rw* mutex); -static FINLINE void mutex_rw_destroy(struct mutex_rw* mutex); -static FINLINE void mutex_rw_rlock(struct mutex_rw* mutex); -static FINLINE void mutex_rw_wlock(struct mutex_rw* mutex); -static FINLINE void mutex_rw_unlock(struct mutex_rw* mutex); - -#ifdef RSYS_USE_PTHREADS - #include "pthread/mutex.h" -#else - #error "No supported thread library is defined" +RSYS_API struct mutex_rw* mutex_rw_create(void);/* NULL <=> error */ +RSYS_API void mutex_rw_destroy(struct mutex_rw* mutex); +RSYS_API void mutex_rw_rlock(struct mutex_rw* mutex); +RSYS_API void mutex_rw_wlock(struct mutex_rw* mutex); +RSYS_API void mutex_rw_unlock(struct mutex_rw* mutex); + +#ifdef __cplusplus +} /* extern "C" */ #endif #endif /* MUTEX_H */ diff --git a/src/platform.h.in b/src/platform.h.in @@ -0,0 +1,8 @@ +#ifndef PLATFORM_H +#define PLATFORM_H + +#define SHARED_LIBRARY_PREFIX "@LIB_PREFIX@" +#define SHARED_LIBRARY_SUFFIX "@LIB_SUFFIX@" + +#endif /* PLATFORM_H */ + diff --git a/src/pthread/condition.h b/src/pthread/condition.h @@ -1,47 +0,0 @@ -#include <pthread.h> - -#ifdef NDEBUG - #define PTHREAD__(Func) pthread_##Func -#else - #define PTHREAD__(Func) ASSERT(pthread_##Func == 0) -#endif - -struct cond { pthread_cond_t cond__; }; - -void -cond_init(struct cond* cond) -{ - ASSERT(cond); - PTHREAD__(cond_init(&cond->cond__, NULL)); -} - -void -cond_destroy(struct cond* cond) -{ - ASSERT(cond); - PTHREAD__(cond_destroy(&cond->cond__)); -} - -void -cond_wait(struct cond* cond, struct mutex* mutex) -{ - ASSERT(cond); - PTHREAD__(cond_wait(&cond->cond__, &mutex->mutex__)); -} - -void -cond_signal(struct cond* cond) -{ - ASSERT(cond); - PTHREAD__(cond_signal(&cond->cond__)); -} - -void -cond_broadcast(struct cond* cond) -{ - ASSERT(cond); - PTHREAD__(cond_broadcast(&cond->cond__)); -} - -#undef PTHREAD__ - diff --git a/src/pthread/mutex.h b/src/pthread/mutex.h @@ -1,116 +0,0 @@ -#include <pthread.h> - -#ifdef NDEBUG - #define PTHREAD__(Func) pthread_##Func -#else - #define PTHREAD__(Func) ASSERT(pthread_##Func == 0) -#endif - -/******************************************************************************* - * Mutex - ******************************************************************************/ -struct mutex { pthread_mutex_t mutex__; }; - -void -mutex_init(struct mutex* mutex) -{ - ASSERT(mutex); - PTHREAD__(mutex_init(&mutex->mutex__, NULL)); -} - -void -mutex_destroy(struct mutex* mutex) -{ - ASSERT(mutex); - PTHREAD__(mutex_destroy(&mutex->mutex__)); -} - -void -mutex_lock(struct mutex* mutex) -{ - ASSERT(mutex); - PTHREAD__(mutex_lock(&mutex->mutex__)); -} - -void -mutex_unlock(struct mutex* mutex) -{ - ASSERT(mutex); - PTHREAD__(mutex_unlock(&mutex->mutex__)); -} - -/******************************************************************************* - * Spinlock - ******************************************************************************/ -struct mutex_spin { pthread_spinlock_t mutex__; }; - -void -mutex_spin_init(struct mutex_spin* mutex) -{ - ASSERT(mutex); - PTHREAD__(spin_init(&mutex->mutex__, PTHREAD_PROCESS_PRIVATE)); -} - -void -mutex_spin_destroy(struct mutex_spin* mutex) -{ - ASSERT(mutex); - PTHREAD__(spin_destroy(&mutex->mutex__)); -} - -void -mutex_spin_lock(struct mutex_spin* mutex) -{ - ASSERT(mutex); - PTHREAD__(spin_lock(&mutex->mutex__)); -} - -void -mutex_spin_unlock(struct mutex_spin* mutex) -{ - ASSERT(mutex); - PTHREAD__(spin_unlock(&mutex->mutex__)); -} - -/******************************************************************************* - * Read Write mutex - ******************************************************************************/ -struct mutex_rw { pthread_rwlock_t mutex__; }; - -static FINLINE void -mutex_rw_init(struct mutex_rw* mutex) -{ - ASSERT(mutex); - PTHREAD__(rwlock_init(&mutex->mutex__, NULL)); -} - -static FINLINE void -mutex_rw_destroy(struct mutex_rw* mutex) -{ - ASSERT(mutex); - PTHREAD__(rwlock_destroy(&mutex->mutex__)); -} - -static FINLINE void -mutex_rw_rlock(struct mutex_rw* mutex) -{ - ASSERT(mutex); - PTHREAD__(rwlock_rdlock(&mutex->mutex__)); -} - -static FINLINE void -mutex_rw_wlock(struct mutex_rw* mutex) -{ - ASSERT(mutex); - PTHREAD__(rwlock_wrlock(&mutex->mutex__)); -} - -static FINLINE void -mutex_rw_unlock(struct mutex_rw* mutex) -{ - ASSERT(mutex); - PTHREAD__(rwlock_unlock(&mutex->mutex__)); -} - -#undef PTHREAD__ - diff --git a/src/pthread/pthread_condition.c b/src/pthread/pthread_condition.c @@ -0,0 +1,50 @@ +#include "../condition.h" +#include "../mem_allocator.h" +#include <pthread.h> + +#ifdef NDEBUG + #define PTHREAD(Func) pthread_##Func +#else + #define PTHREAD(Func) ASSERT(pthread_##Func == 0) +#endif + +struct cond* +cond_create(void) +{ + pthread_cond_t* cond = mem_alloc(sizeof(pthread_cond_t)); + if(cond) + PTHREAD(cond_init(cond, NULL)); + return (struct cond*)cond; +} + +void +cond_destroy(struct cond* cond) +{ + ASSERT(cond); + PTHREAD(cond_destroy((pthread_cond_t*)cond)); + mem_free(cond); +} + +void +cond_wait(struct cond* cond, struct mutex* mutex) +{ + ASSERT(cond); + PTHREAD(cond_wait((pthread_cond_t*)cond, (pthread_mutex_t*)mutex)); +} + +void +cond_signal(struct cond* cond) +{ + ASSERT(cond); + PTHREAD(cond_signal((pthread_cond_t*)cond)); +} + +void +cond_broadcast(struct cond* cond) +{ + ASSERT(cond); + PTHREAD(cond_broadcast((pthread_cond_t*)cond)); +} + +#undef PTHREAD + diff --git a/src/pthread/pthread_mutex.c b/src/pthread/pthread_mutex.c @@ -0,0 +1,122 @@ +#define _POSIX_C_SOURCE 200112L /* Spin lock and mutex rw */ +#include "../mem_allocator.h" +#include "../mutex.h" +#include <pthread.h> + +#ifdef NDEBUG + #define PTHREAD(Func) pthread_##Func +#else + #define PTHREAD(Func) ASSERT(pthread_##Func == 0) +#endif + +/******************************************************************************* + * Mutex + ******************************************************************************/ +struct mutex* +mutex_create(void) +{ + pthread_mutex_t* mutex = mem_alloc(sizeof(pthread_mutex_t)); + if(mutex) + PTHREAD(mutex_init(mutex, NULL)); + return (struct mutex*)mutex; +} + +void +mutex_destroy(struct mutex* mutex) +{ + ASSERT(mutex); + PTHREAD(mutex_destroy((pthread_mutex_t*)mutex)); + mem_free(mutex); +} + +void +mutex_lock(struct mutex* mutex) +{ + ASSERT(mutex); + PTHREAD(mutex_lock((pthread_mutex_t*)mutex)); +} + +void +mutex_unlock(struct mutex* mutex) +{ + ASSERT(mutex); + PTHREAD(mutex_unlock((pthread_mutex_t*)mutex)); +} + +/******************************************************************************* + * Spinlock + ******************************************************************************/ +struct mutex_spin* +mutex_spin_create(void) +{ + pthread_spinlock_t* spin = mem_alloc(sizeof(pthread_spinlock_t)); + if(spin) + PTHREAD(spin_init(spin, PTHREAD_PROCESS_PRIVATE)); + return (struct mutex_spin*)spin; +} + +void +mutex_spin_destroy(struct mutex_spin* mutex) +{ + ASSERT(mutex); + PTHREAD(spin_destroy((pthread_spinlock_t*)mutex)); + mem_free(mutex); +} + +void +mutex_spin_lock(struct mutex_spin* mutex) +{ + ASSERT(mutex); + PTHREAD(spin_lock((pthread_spinlock_t*)mutex)); +} + +void +mutex_spin_unlock(struct mutex_spin* mutex) +{ + ASSERT(mutex); + PTHREAD(spin_unlock((pthread_spinlock_t*)mutex)); +} + +/******************************************************************************* + * Read Write mutex + ******************************************************************************/ +struct mutex_rw* +mutex_rw_create(void) +{ + pthread_rwlock_t* mutex = mem_alloc(sizeof(pthread_rwlock_t)); + if(mutex) + PTHREAD(rwlock_init(mutex, NULL)); + return (struct mutex_rw*)mutex; +} + +void +mutex_rw_destroy(struct mutex_rw* mutex) +{ + ASSERT(mutex); + PTHREAD(rwlock_destroy((pthread_rwlock_t*)mutex)); + mem_free(mutex); +} + +void +mutex_rw_rlock(struct mutex_rw* mutex) +{ + ASSERT(mutex); + PTHREAD(rwlock_rdlock((pthread_rwlock_t*)mutex)); +} + +void +mutex_rw_wlock(struct mutex_rw* mutex) +{ + ASSERT(mutex); + PTHREAD(rwlock_wrlock((pthread_rwlock_t*)mutex)); +} + +void +mutex_rw_unlock(struct mutex_rw* mutex) +{ + ASSERT(mutex); + PTHREAD(rwlock_unlock((pthread_rwlock_t*)mutex)); +} + +#undef PTHREAD + diff --git a/src/ref_count.h b/src/ref_count.h @@ -4,7 +4,7 @@ #include "atomic.h" #include "rsys.h" -typedef atomic_int_T ref_T; +typedef atomic32_T ref_T; static FINLINE void ref_init(ref_T* ref) @@ -23,10 +23,11 @@ ref_get(ref_T* ref) static FINLINE int ref_put(ref_T* ref, void (*release)(ref_T*)) { + int curr = 0; ASSERT(NULL != ref); ASSERT(NULL != release); - const int curr = ATOMIC_DECR(ref); + curr = ATOMIC_DECR(ref); ASSERT(curr >= 0); if(0 == curr) { diff --git a/src/rsys.h b/src/rsys.h @@ -14,16 +14,24 @@ * Platform ******************************************************************************/ #if defined(__unix__) || defined(__unix) || defined(unix) - #define PLATFORM_UNIX + #define OS_UNIX +#elif defined(_WIN32) + #define OS_WINDOWS #else - #error "Unsupported platform" + #error "Unsupported OS" +#endif + +#if defined(__MINGW32__) + #define MINGW #endif /******************************************************************************* * Compiler ******************************************************************************/ -#if defined( __GNUC__ ) +#if defined(__GNUC__) #define COMPILER_GCC +#elif defined(_MSC_VER) + #define COMPILER_MSVC #else #error "Unsupported compiler" #endif @@ -31,9 +39,29 @@ /******************************************************************************* * Symbol visibility ******************************************************************************/ -#define EXPORT_SYM __attribute__((visibility("default"))) -#define IMPORT_SYM -#define LOCAL_SYM __attribute__((visibility("hidden"))) +#if defined(COMPILER_GCC) + #define EXPORT_SYM __attribute__((visibility("default"))) + #define IMPORT_SYM + #define LOCAL_SYM __attribute__((visibility("hidden"))) +#elif defined(COMPILER_MSVC) + #define FDN_SYMBOL_EXPORT __declspec(dllexport) + #define FDN_SYMBOL_IMPORT __declspec(dllimport) + #define FDN_SYMBOL_LOCAL +#endif + +#if defined(OS_UNIX) + #define SHARED_LIBRARY_PREFIX "lib" + #define SHARED_LIBRARY_SUFFIX ".so" +#elif defined(OS_WINDOWS) + #if defined(MINGW) + #define SHARED_LIBRARY_PREFIX "lib" + #else + #define SHARED_LIBRARY_PREFIX + #endif + #define SHARED_LIBRARY_SUFFIX ".dll" +#endif + +#define SHARED_LIBRARY_NAME(Lib) SHARED_LIBRARY_PREFIX Lib SHARED_LIBRARY_SUFFIX #if defined(RSYS_SHARED_BUILD) #define RSYS_API extern EXPORT_SYM @@ -44,9 +72,15 @@ /******************************************************************************* * Code inlining ******************************************************************************/ -#define FINLINE inline __attribute__((always_inline)) -#define INLINE inline -#define NOINLINE __attribute__((noinline)) +#if defined(COMPILER_GCC) + #define FINLINE __inline__ __attribute__((always_inline)) + #define INLINE __inline__ + #define NOINLINE __attribute__((noinline)) +#elif defined(COMPILER_MSVC) + #define FINLINE __forceinline + #define INLINE __inline + #define NOINLINE __declspec(noinline) +#endif /******************************************************************************* * Data alignment @@ -66,7 +100,8 @@ #define ASSERT(C) assert(C) #endif -#define STATIC_ASSERT(Cond, Msg) char STATIC_ASSERT_##Msg[1 - 2*(!(Cond))] +#define STATIC_ASSERT(Cond, Msg) \ + char STATIC_ASSERT_##Msg[1 - 2*(!(Cond))] __attribute__((unused)) #define FATAL(Msg) \ { \ @@ -94,6 +129,17 @@ #define UNLIKELY(X) __builtin_expect((X), 0) /******************************************************************************* + * Iteration + ******************************************************************************/ +/* Iterate over [Start, End) */ +#define FOR_EACH(Id, Start, End) \ + for((Id) = (Start); (Id) < (End); ++(Id)) + +/* Reverse iterrate over [Start, End) */ +#define FOR_EACH_REVERSE(Type, Id, Start, End) \ + for((Id) = (Start); (Id) > (End); --(Id)) + +/******************************************************************************* * SIMD instruction sets ******************************************************************************/ #ifdef __SSE__ @@ -123,15 +169,6 @@ ((Type*)((uintptr_t)Ptr - offsetof(Type, Member))) #define COUNTER __COUNTER__ -#define FOR_EACH(Type, Id, Start, End) \ - for(Type (Id) = (Start), CONCAT(end__, __LINE__) = (End); \ - (Id) < CONCAT(end__, __LINE__); \ - ++(Id)) - -#define FOR_EACH_REVERSE(Type, Id, Start, End) \ - for(Type (Id) = (Start), CONCAT(end__, __LINE__) = (End); \ - (Id) > CONCAT(end__, __LINE__); \ - --(Id)) #define SWAP(Type, A, B) \ { \ @@ -140,16 +177,10 @@ (B) = tmp__; \ } (void)0 -#define IS_MEMORY_OVERLAPPED(D0, Sz0, D1, Sz1) \ - (((intptr_t)(D0) >= (intptr_t)(D1) && \ - (intptr_t)(D0) < ((intptr_t)(D1) + (intptr_t)(Sz1))) || \ - (((intptr_t)(D0) + (intptr_t)(Sz0)) >= (intptr_t)(D1) && \ - ((intptr_t)(D0) + (intptr_t)(Sz0)) < ((intptr_t)(D1) + (intptr_t)(Sz1)))) - #define STR__(X) #X #define STR(X) STR__(X) #define OFFSET_PTR(Ptr, Offset) (void*)((uintptr_t)(Ptr) + (Offset)) -#endif /* SNLSYS_H */ +#endif /* RSYS_H */ diff --git a/src/rsys_version.h.in b/src/rsys_version.h.in @@ -0,0 +1,9 @@ +#ifndef RSYS_VERSION_H +#define RSYS_VERSION_H + +#define RSYS_VERSION_MAJOR @VERSION_MAJOR@ +#define RSYS_VERSION_MINOR @VERSION_MINOR@ +#define RSYS_VERSION_PATCH @VERSION_PATCH@ + +#endif /* RSYS_VERSION_H */ + diff --git a/src/signal.h b/src/signal.h @@ -57,6 +57,7 @@ signal_connect_callback(signal_T* signal, struct callback* clbk) static FINLINE void signal_invoke(signal_T* signal, void* args) { + struct list_node* pos = NULL; LIST_FOR_EACH(pos, signal) { struct callback* clbk = CONTAINER_OF(pos, struct callback, node); clbk->func(args, clbk->data); diff --git a/src/test_atomic.c b/src/test_atomic.c @@ -4,45 +4,30 @@ int main(int argc, char** argv) { - (void)argc, (void)argv; - - atomic_int_T atom = 0; + atomic32_T atom = 0; int tmp; + (void)argc, (void)argv; tmp = ATOMIC_INCR(&atom); CHECK(atom, 1); CHECK(tmp, 1); tmp = ATOMIC_ADD(&atom, 5); CHECK(atom, 6); - CHECK(tmp, 6); + CHECK(tmp, 1); tmp = ATOMIC_DECR(&atom); CHECK(atom, 5); CHECK(tmp, 5); tmp = ATOMIC_SUB(&atom, 7); CHECK(atom, -2); - CHECK(tmp, -2); - - atom = 0; - tmp = ATOMIC_FETCH_AND_INCR(&atom); - CHECK(atom, 1); - CHECK(tmp, 0); - tmp = ATOMIC_FETCH_AND_ADD(&atom, 5); - CHECK(atom, 6); - CHECK(tmp, 1); - tmp = ATOMIC_FETCH_AND_DECR(&atom); - CHECK(atom, 5); - CHECK(tmp, 6); - tmp = ATOMIC_FETCH_AND_SUB(&atom, 7); - CHECK(atom, -2); CHECK(tmp, 5); - tmp = ATOMIC_CMP_AND_SWAP(&atom, 0, -1); + tmp = ATOMIC_CAS(&atom, 0, -1); CHECK(atom, -2); CHECK(tmp, -2); - tmp = ATOMIC_CMP_AND_SWAP(&atom, 0, -2); + tmp = ATOMIC_CAS(&atom, 0, -2); CHECK(atom, 0); CHECK(tmp, -2); - ATOMIC_FETCH_AND_STORE(&atom, 9, &tmp); + tmp = ATOMIC_SET(&atom, 9); CHECK(atom, 9); CHECK(tmp, 0); diff --git a/src/test_condition.c b/src/test_condition.c @@ -64,9 +64,9 @@ struct stream { struct list_node list_fill; struct list_node list_flush; - struct mutex mutex; - struct cond cond_fill; - struct cond cond_flush; + struct mutex* mutex; + struct cond* cond_fill; + struct cond* cond_flush; }; struct buff @@ -78,67 +78,78 @@ struct buff static void read(struct stream* stream) { + size_t i = 0; ASSERT(stream); - for(size_t i = 0; i < sizeof(src_str)/sizeof(const char*); ++i) { - mutex_lock(&stream->mutex); + FOR_EACH(i, 0, sizeof(src_str)/sizeof(const char*)) { + struct list_node* buff_node = NULL; + struct buff* buff = NULL; + + mutex_lock(stream->mutex); if(is_list_empty(&stream->list_flush)) { - cond_wait(&stream->cond_flush, &stream->mutex); + cond_wait(stream->cond_flush, stream->mutex); } - mutex_unlock(&stream->mutex); + mutex_unlock(stream->mutex); - struct list_node* buff_node = list_head(&stream->list_flush); - struct buff* buff = CONTAINER_OF(buff_node, struct buff, node); + buff_node = list_head(&stream->list_flush); + buff = CONTAINER_OF(buff_node, struct buff, node); CHECK(strcmp(buff->scratch, src_str[i]), 0); printf("\n%s\n", buff->scratch); - mutex_lock(&stream->mutex); + mutex_lock(stream->mutex); list_move_tail(buff_node, &stream->list_fill); - mutex_unlock(&stream->mutex); + mutex_unlock(stream->mutex); - cond_broadcast(&stream->cond_fill); + cond_broadcast(stream->cond_fill); } } static void write(struct stream* stream) { + size_t i = 0; ASSERT(stream); - for(size_t i = 0; i < sizeof(src_str)/sizeof(const char*); ++i) { - mutex_lock(&stream->mutex); + FOR_EACH(i, 0, sizeof(src_str)/sizeof(const char*)) { + struct list_node* buff_node = NULL; + struct buff* buff = NULL; + + mutex_lock(stream->mutex); if(is_list_empty(&stream->list_fill)) { - cond_wait(&stream->cond_fill, &stream->mutex); + cond_wait(stream->cond_fill, stream->mutex); } - mutex_unlock(&stream->mutex); + mutex_unlock(stream->mutex); - struct list_node* buff_node = list_head(&stream->list_fill); - struct buff* buff = CONTAINER_OF(buff_node, struct buff, node); + buff_node = list_head(&stream->list_fill); + buff = CONTAINER_OF(buff_node, struct buff, node); ASSERT(sizeof(buff->scratch)/sizeof(char) > strlen(src_str[i])); strcpy(buff->scratch, src_str[i]); - mutex_lock(&stream->mutex); + mutex_lock(stream->mutex); list_move_tail(buff_node, &stream->list_flush); - mutex_unlock(&stream->mutex); + mutex_unlock(stream->mutex); - cond_broadcast(&stream->cond_flush); + cond_broadcast(stream->cond_flush); } } int main(int argc, char** argv) { + struct buff buff[2]; + struct stream stream; (void)argc, (void)argv; - struct stream stream; list_init(&stream.list_fill); list_init(&stream.list_flush); - mutex_init(&stream.mutex); - cond_init(&stream.cond_flush); - cond_init(&stream.cond_fill); + stream.mutex = mutex_create(); + NCHECK(stream.mutex, NULL); + stream.cond_flush = cond_create(); + NCHECK(stream.cond_flush, NULL); + stream.cond_fill = cond_create(); + NCHECK(stream.cond_fill, NULL); - struct buff buff[2]; list_init(&buff[0].node); list_init(&buff[1].node); list_add(&stream.list_fill, &buff[0].node); @@ -151,9 +162,9 @@ main(int argc, char** argv) #pragma omp section write(&stream); } - mutex_destroy(&stream.mutex); - cond_destroy(&stream.cond_flush); - cond_destroy(&stream.cond_fill); + mutex_destroy(stream.mutex); + cond_destroy(stream.cond_flush); + cond_destroy(stream.cond_fill); return 0; } diff --git a/src/test_free_list.c b/src/test_free_list.c @@ -0,0 +1,72 @@ +#include "rsys.h" +#include "free_list.h" + +struct object { + FITEM; + unsigned int i; +}; + +#define FITEM_TYPE object +#include "free_list.h" + +int +main(int argc, char** argv) +{ + #define NB_OBJ 1024 + struct flist_object list; + struct object* obj = NULL; + struct fid id[NB_OBJ]; + int i = 0; + (void)argc, (void)argv; + + FOR_EACH(i, 0, NB_OBJ) { + id[i] = FID_NULL; + } + + flist_object_init(NULL, &list); + CHECK(flist_object_hold(&list, id[0]), 0); + CHECK(flist_object_get(&list, id[0]), NULL); + + FOR_EACH(i, 0, NB_OBJ / 2) { + struct fid tmp_id; + id[i] = flist_object_add(&list); + CHECK(flist_object_hold(&list, id[i]), 1); + obj = flist_object_get(&list, id[i]); + tmp_id = object_id_get(obj); + CHECK(FID_EQ(tmp_id, id[i]), 1); + NCHECK(obj, NULL); + obj->i = 0xDECAF000 + (unsigned)i; + } + + FOR_EACH(i, 0, NB_OBJ * 2 / 3) { + const float rand_f /* in [0, 1] */ = (float)rand() / (float)RAND_MAX; + const int i = (int)(rand_f * (NB_OBJ - 1)); + flist_object_del(&list, id[i]); + id[i] = FID_NULL; + } + + FOR_EACH(i, NB_OBJ / 2, NB_OBJ) { + id[i] = flist_object_add(&list); + CHECK(flist_object_hold(&list, id[i]), 1); + obj = flist_object_get(&list, id[i]); + NCHECK(obj, NULL); + obj->i = 0xDECAF000 + (unsigned)i; + } + + FOR_EACH(i, 0, NB_OBJ) { + if(IS_FID_NULL(id[i])) { + CHECK(flist_object_hold(&list, id[i]), 0); + CHECK(flist_object_get(&list, id[i]), NULL); + } else { + CHECK(flist_object_hold(&list, id[i]), 1); + obj = flist_object_get(&list, id[i]); + CHECK(obj->i, 0xDECAF000 + (unsigned)i); + } + } + + flist_object_release(&list); + + CHECK(MEM_ALLOCATED_SIZE(&mem_default_allocator), 0); + + return 0; +} diff --git a/src/test_list.c b/src/test_list.c @@ -10,6 +10,8 @@ main(int argc, char** argv) char c; } elmt0, elmt1, elmt2; struct list_node list, list1; + struct list_node* n = NULL; + struct list_node* tmp = NULL; int i = 0; (void)argc; @@ -137,9 +139,10 @@ main(int argc, char** argv) CHECK(i, 0); i = 0; - LIST_FOR_EACH_SAFE(n, &list1) { + LIST_FOR_EACH_SAFE(n, tmp, &list1) { + struct elmt* e = NULL; list_move_tail(n, &list); - struct elmt* e = CONTAINER_OF(n, struct elmt, node); + e = CONTAINER_OF(n, struct elmt, node); CHECK(e->c, 'a' + i); ++i; } @@ -148,9 +151,10 @@ main(int argc, char** argv) CHECK(is_list_empty(&list), 0); i = 3; - LIST_FOR_EACH_REVERSE_SAFE(n, &list) { + LIST_FOR_EACH_REVERSE_SAFE(n, tmp, &list) { + struct elmt* e = NULL; list_move(n, &list1); - struct elmt* e = CONTAINER_OF(n, struct elmt, node); + e = CONTAINER_OF(n, struct elmt, node); --i; CHECK(e->c, 'a' + i); } diff --git a/src/test_mem_allocator.c b/src/test_mem_allocator.c @@ -1,24 +1,82 @@ #include "mem_allocator.h" #include "rsys.h" -#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> static void -regular_test(struct mem_allocator* allocator) +test_regular(void) { - char dump[BUFSIZ]; void* p = NULL; void* q[3] = {NULL, NULL, NULL}; size_t i = 0; - p = MEM_ALIGNED_ALLOC(allocator, 1024, ALIGNOF(char)); + p = mem_alloc_aligned(1024, ALIGNOF(char)); + NCHECK(p, NULL); + CHECK(IS_ALIGNED((uintptr_t)p, ALIGNOF(char)), 1); + mem_free( p ); + + q[0] = mem_alloc_aligned(10, 64); + q[1] = mem_alloc(58); + q[2] = mem_alloc(78); + NCHECK(q[0], NULL); + NCHECK(q[1], NULL); + NCHECK(q[2], NULL); + CHECK(IS_ALIGNED((uintptr_t )q[0], 64 ), 1); + + p = mem_calloc(1, 4); + NCHECK(p, NULL); + FOR_EACH(i, 0, 4) { + CHECK(((char*)p)[i], 0); + } + FOR_EACH(i, 0, 4) { + ((char*)p)[i] = (char)i; + } + + mem_free(q[1]); + + p = mem_realloc(p, 8); + FOR_EACH(i, 0, 4) { + CHECK(((char*)p)[i], (char)i); + } + FOR_EACH(i, 4, 8) { + ((char*)p)[i] = (char)i; + } + + mem_free(q[2]); + + p = mem_realloc(p, 5); + FOR_EACH(i, 0, 5) { + CHECK(((char*)p )[i], (char)i); + } + + mem_free(p); + + p = NULL; + p = mem_realloc(NULL, 16); + NCHECK(p, NULL); + p = mem_realloc(p, 0); + + mem_free(q[0]); + + CHECK(mem_alloc_aligned(1024, 0 ), NULL); + CHECK(mem_alloc_aligned(1024, 3 ), NULL); +} + +static void +test_allocator(struct mem_allocator* allocator) +{ + char dump[24]; + void* p = NULL; + void* q[3] = {NULL, NULL, NULL}; + size_t i = 0; + + p = MEM_ALLOC_ALIGNED(allocator, 1024, ALIGNOF(char)); NCHECK(p, NULL); CHECK(IS_ALIGNED((uintptr_t)p, ALIGNOF(char)), 1); MEM_FREE(allocator, p); - q[0] = MEM_ALIGNED_ALLOC(allocator, 10, 8); + q[0] = MEM_ALLOC_ALIGNED(allocator, 10, 8); q[1] = MEM_CALLOC(allocator, 1, 58); q[2] = MEM_ALLOC(allocator, 78); NCHECK(q[0], NULL); @@ -33,7 +91,7 @@ regular_test(struct mem_allocator* allocator) for(i = 0; i < 4; ++i) ((char*)p)[i] = (char)i; - MEM_DUMP(allocator, dump, BUFSIZ); + MEM_DUMP(allocator, dump, 24); printf("dump:\n%s\n", dump); MEM_DUMP(allocator, dump, 16); printf("truncated dump:\n%s\n", dump); @@ -62,8 +120,8 @@ regular_test(struct mem_allocator* allocator) MEM_FREE(allocator, q[0]); - CHECK(MEM_ALIGNED_ALLOC(allocator, 1024, 0), NULL); - CHECK(MEM_ALIGNED_ALLOC(allocator, 1024, 3), NULL); + CHECK(MEM_ALLOC_ALIGNED(allocator, 1024, 0), NULL); + CHECK(MEM_ALLOC_ALIGNED(allocator, 1024, 3), NULL); CHECK(MEM_ALLOCATED_SIZE(allocator), 0); } @@ -75,12 +133,15 @@ main(int argc, char** argv) (void)argc; (void)argv; - printf("Default allocator:\n"); - regular_test(&mem_default_allocator); + printf("-- Common allocation functions\n"); + test_regular(); + + printf("-- Default allocator\n"); + test_allocator(&mem_default_allocator); - printf("\nProxy allocator\n"); + printf("\n-- Proxy allocator\n"); mem_init_proxy_allocator("utest", &allocator, &mem_default_allocator); - regular_test(&allocator); + test_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); CHECK(MEM_ALLOCATED_SIZE(&mem_default_allocator), 0); diff --git a/src/test_mutex.c b/src/test_mutex.c @@ -4,61 +4,151 @@ #include <string.h> #include <omp.h> -static const char src_str[] = -"Rcvfbqr 1, XARR-QRRC VA GUR QRNQ:\n\ ----------------------------------\n\ -\n\ -BAPR LBH ORNG GUR OVT ONQNFFRF NAQ PYRNA BHG GUR ZBBA ONFR LBH'ER FHCCBFRQ GB\n\ -JVA, NERA'G LBH? NERA'G LBH? JURER'F LBHE SNG ERJNEQ NAQ GVPXRG UBZR? JUNG\n\ -GUR URYY VF GUVF? VG'F ABG FHCCBFRQ GB RAQ GUVF JNL!\n\ -\n\ -VG FGVAXF YVXR EBGGRA ZRNG, OHG YBBXF YVXR GUR YBFG QRVZBF ONFR. YBBXF YVXR\n\ -LBH'ER FGHPX BA GUR FUBERF BS URYY. GUR BAYL JNL BHG VF GUEBHTU.\n\ -\n\ -GB PBAGVAHR GUR QBBZ RKCREVRAPR, CYNL GUR FUBERF BS URYY NAQ VGF NZNMVAT\n\ -FRDHRY, VASREAB!\n\ -\n\ -Rcvfbqr 2, GUR FUBERF BS URYY:\n\ -------------------------------\n\ -\n\ -LBH'IR QBAR VG! GUR UVQRBHF PLORE- QRZBA YBEQ GUNG EHYRQ GUR YBFG QRVZBF ZBBA\n\ -ONFR UNF ORRA FYNVA NAQ LBH NER GEVHZCUNAG! OHG ... JURER NER LBH? LBH\n\ -PYNZORE GB GUR RQTR BS GUR ZBBA NAQ YBBX QBJA GB FRR GUR NJSHY GEHGU.\n\ -\n\ -QRVZBF SYBNGF NOBIR URYY VGFRYS! LBH'IR ARIRE URNEQ BS NALBAR RFPNCVAT SEBZ\n\ -URYY, OHG LBH'YY ZNXR GUR ONFGNEQF FBEEL GURL RIRE URNEQ BS LBH! DHVPXYL, LBH\n\ -ENCCRY QBJA GB GUR FHESNPR BS URYY.\n\ -\n\ -ABJ, VG'F BA GB GUR SVANY PUNCGRE BS QBBZ! -- VASREAB.\n\ -\n\ -Rcvfbqr 3, VASREAB:\n\ --------------------\n\ -\n\ -GUR YBNGUFBZR FCVQREQRZBA GUNG ZNFGREZVAQRQ GUR VAINFVBA BS GUR ZBBA ONFRF\n\ -NAQ PNHFRQ FB ZHPU QRNGU UNF UNQ VGF NFF XVPXRQ SBE NYY GVZR.\n\ -\n\ -N UVQQRA QBBEJNL BCRAF NAQ LBH RAGRE. LBH'IR CEBIRA GBB GBHTU SBE URYY GB\n\ -PBAGNVA, NAQ ABJ URYY NG YNFG CYNLF SNVE -- SBE LBH RZRETR SEBZ GUR QBBE GB\n\ -FRR GUR TERRA SVRYQF BS RNEGU! UBZR NG YNFG.\n\ -\n\ -LBH JBAQRE JUNG'F ORRA UNCCRAVAT BA RNEGU JUVYR LBH JRER ONGGYVAT RIVY\n\ -HAYRNFURQ. VG'F TBBQ GUNG AB URYY- FCNJA PBHYQ UNIR PBZR GUEBHTU GUNG QBBE\n\ -JVGU LBH ...\n\ -\n\ -Rcvfbqr 4, GUL SYRFU PBAFHZRQ:\n\ -------------------------------\n\ -\n\ -GUR FCVQRE ZNFGREZVAQ ZHFG UNIR FRAG SBEGU VGF YRTVBAF BS URYYFCNJA ORSBER\n\ -LBHE SVANY PBASEBAGNGVBA JVGU GUNG GREEVOYR ORNFG SEBZ URYY. OHG LBH FGRCCRQ\n\ -SBEJNEQ NAQ OEBHTUG SBEGU RGREANY QNZANGVBA NAQ FHSSREVAT HCBA GUR UBEQR NF N\n\ -GEHR UREB JBHYQ VA GUR SNPR BS FBZRGUVAT FB RIVY.\n\ -\n\ -ORFVQRF, FBZRBAR JNF TBAAN CNL SBE JUNG UNCCRARQ GB QNVFL, LBHE CRG ENOOVG.\n\ -\n\ -OHG ABJ, LBH FRR FCERNQ ORSBER LBH ZBER CBGRAGVNY CNVA NAQ TVOOVGHQR NF N\n\ -ANGVBA BS QRZBAF EHA NZBX VA BHE PVGVRF.\n\ -\n\ -ARKG FGBC, URYY BA RNEGU!"; +static const char src_str[] = { + 'R', 'c', 'v', 'f', 'b', 'q', 'r', ' ', '1', ',', ' ', 'X', 'A', 'R', 'R', + '-', 'Q', 'R', 'R', 'C', ' ', 'V', 'A', ' ', 'G', 'U', 'R', ' ', 'Q', 'R', + 'N', 'Q', ':', '\n', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', + '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', + '-', '-', '-', '-', '-', '-', '-', '-', '\n', '\n', 'B', 'A', 'P', 'R', ' ', + 'L', 'B', 'H', ' ', 'O', 'R', 'N', 'G', ' ', 'G', 'U', 'R', ' ', 'O', 'V', + 'T', ' ', 'O', 'N', 'Q', 'N', 'F', 'F', 'R', 'F', ' ', 'N', 'A', 'Q', ' ', + 'P', 'Y', 'R', 'N', 'A', ' ', 'B', 'H', 'G', ' ', 'G', 'U', 'R', ' ', 'Z', + 'B', 'B', 'A', ' ', 'O', 'N', 'F', 'R', ' ', 'L', 'B', 'H', '\'', 'E', 'R', + ' ', 'F', 'H', 'C', 'C', 'B', 'F', 'R', 'Q', ' ', 'G', 'B', '\n', 'J', 'V', + 'A', ',', ' ', 'N', 'E', 'R', 'A', '\'', 'G', ' ', 'L', 'B', 'H', '?', ' ', + 'N', 'E', 'R', 'A', '\'', 'G', ' ', 'L', 'B', 'H', '?', ' ', 'J', 'U', 'R', + 'E', 'R', '\'', 'F', ' ', 'L', 'B', 'H', 'E', ' ', 'S', 'N', 'G', ' ', 'E', + 'R', 'J', 'N', 'E', 'Q', ' ', 'N', 'A', 'Q', ' ', 'G', 'V', 'P', 'X', 'R', + 'G', ' ', 'U', 'B', 'Z', 'R', '?', ' ', 'J', 'U', 'N', 'G', '\n', 'G', 'U', + 'R', ' ', 'U', 'R', 'Y', 'Y', ' ', 'V', 'F', ' ', 'G', 'U', 'V', 'F', '?', + ' ', 'V', 'G', '\'', 'F', ' ', 'A', 'B', 'G', ' ', 'F', 'H', 'C', 'C', 'B', + 'F', 'R', 'Q', ' ', 'G', 'B', ' ', 'R', 'A', 'Q', ' ', 'G', 'U', 'V', 'F', + ' ', 'J', 'N', 'L', '!', '\n', '\n', 'V', 'G', ' ', 'F', 'G', 'V', 'A', 'X', + 'F', ' ', 'Y', 'V', 'X', 'R', ' ', 'E', 'B', 'G', 'G', 'R', 'A', ' ', 'Z', + 'R', 'N', 'G', ',', ' ', 'O', 'H', 'G', ' ', 'Y', 'B', 'B', 'X', 'F', ' ', + 'Y', 'V', 'X', 'R', ' ', 'G', 'U', 'R', ' ', 'Y', 'B', 'F', 'G', ' ', 'Q', + 'R', 'V', 'Z', 'B', 'F', ' ', 'O', 'N', 'F', 'R', '.', ' ', 'Y', 'B', 'B', + 'X', 'F', ' ', 'Y', 'V', 'X', 'R', '\n', 'L', 'B', 'H', '\'', 'E', 'R', ' ', + 'F', 'G', 'H', 'P', 'X', ' ', 'B', 'A', ' ', 'G', 'U', 'R', ' ', 'F', 'U', + 'B', 'E', 'R', 'F', ' ', 'B', 'S', ' ', 'U', 'R', 'Y', 'Y', '.', ' ', 'G', + 'U', 'R', ' ', 'B', 'A', 'Y', 'L', ' ', 'J', 'N', 'L', ' ', 'B', 'H', 'G', + ' ', 'V', 'F', ' ', 'G', 'U', 'E', 'B', 'H', 'T', 'U', '.', '\n', '\n', 'G', + 'B', ' ', 'P', 'B', 'A', 'G', 'V', 'A', 'H', 'R', ' ', 'G', 'U', 'R', ' ', + 'Q', 'B', 'B', 'Z', ' ', 'R', 'K', 'C', 'R', 'E', 'V', 'R', 'A', 'P', 'R', + ',', ' ', 'C', 'Y', 'N', 'L', ' ', 'G', 'U', 'R', ' ', 'F', 'U', 'B', 'E', + 'R', 'F', ' ', 'B', 'S', ' ', 'U', 'R', 'Y', 'Y', ' ', 'N', 'A', 'Q', ' ', + 'V', 'G', 'F', ' ', 'N', 'Z', 'N', 'M', 'V', 'A', 'T', '\n', 'F', 'R', 'D', + 'H', 'R', 'Y', ',', ' ', 'V', 'A', 'S', 'R', 'E', 'A', 'B', '!', '\n', '\n', + 'R', 'c', 'v', 'f', 'b', 'q', 'r', ' ', '2', ',', ' ', 'G', 'U', 'R', ' ', + 'F', 'U', 'B', 'E', 'R', 'F', ' ', 'B', 'S', ' ', 'U', 'R', 'Y', 'Y', ':', + '\n', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', + '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', + '-', '\n', '\n', 'L', 'B', 'H', '\'', 'I', 'R', ' ', 'Q', 'B', 'A', 'R', ' ', + 'V', 'G', '!', ' ', 'G', 'U', 'R', ' ', 'U', 'V', 'Q', 'R', 'B', 'H', 'F', + ' ', 'P', 'L', 'O', 'R', 'E', '-', ' ', 'Q', 'R', 'Z', 'B', 'A', ' ', 'Y', + 'B', 'E', 'Q', ' ', 'G', 'U', 'N', 'G', ' ', 'E', 'H', 'Y', 'R', 'Q', ' ', + 'G', 'U', 'R', ' ', 'Y', 'B', 'F', 'G', ' ', 'Q', 'R', 'V', 'Z', 'B', 'F', + ' ', 'Z', 'B', 'B', 'A', '\n', 'O', 'N', 'F', 'R', ' ', 'U', 'N', 'F', ' ', + 'O', 'R', 'R', 'A', ' ', 'F', 'Y', 'N', 'V', 'A', ' ', 'N', 'A', 'Q', ' ', + 'L', 'B', 'H', ' ', 'N', 'E', 'R', ' ', 'G', 'E', 'V', 'H', 'Z', 'C', 'U', + 'N', 'A', 'G', '!', ' ', 'O', 'H', 'G', ' ', '.', '.', '.', ' ', 'J', 'U', + 'R', 'E', 'R', ' ', 'N', 'E', 'R', ' ', 'L', 'B', 'H', '?', ' ', 'L', 'B', + 'H', '\n', 'P', 'Y', 'N', 'Z', 'O', 'R', 'E', ' ', 'G', 'B', ' ', 'G', 'U', + 'R', ' ', 'R', 'Q', 'T', 'R', ' ', 'B', 'S', ' ', 'G', 'U', 'R', ' ', 'Z', + 'B', 'B', 'A', ' ', 'N', 'A', 'Q', ' ', 'Y', 'B', 'B', 'X', ' ', 'Q', 'B', + 'J', 'A', ' ', 'G', 'B', ' ', 'F', 'R', 'R', ' ', 'G', 'U', 'R', ' ', 'N', + 'J', 'S', 'H', 'Y', ' ', 'G', 'E', 'H', 'G', 'U', '.', '\n', '\n', 'Q', 'R', + 'V', 'Z', 'B', 'F', ' ', 'S', 'Y', 'B', 'N', 'G', 'F', ' ', 'N', 'O', 'B', + 'I', 'R', ' ', 'U', 'R', 'Y', 'Y', ' ', 'V', 'G', 'F', 'R', 'Y', 'S', '!', + ' ', ' ', 'L', 'B', 'H', '\'', 'I', 'R', ' ', 'A', 'R', 'I', 'R', 'E', ' ', + 'U', 'R', 'N', 'E', 'Q', ' ', 'B', 'S', ' ', 'N', 'A', 'L', 'B', 'A', 'R', + ' ', 'R', 'F', 'P', 'N', 'C', 'V', 'A', 'T', ' ', 'S', 'E', 'B', 'Z', '\n', + 'U', 'R', 'Y', 'Y', ',', ' ', 'O', 'H', 'G', ' ', 'L', 'B', 'H', '\'', 'Y', + 'Y', ' ', 'Z', 'N', 'X', 'R', ' ', 'G', 'U', 'R', ' ', 'O', 'N', 'F', 'G', + 'N', 'E', 'Q', 'F', ' ', 'F', 'B', 'E', 'E', 'L', ' ', 'G', 'U', 'R', 'L', + ' ', 'R', 'I', 'R', 'E', ' ', 'U', 'R', 'N', 'E', 'Q', ' ', 'B', 'S', ' ', + 'L', 'B', 'H', '!', ' ', 'D', 'H', 'V', 'P', 'X', 'Y', 'L', ',', ' ', 'L', + 'B', 'H', '\n', 'E', 'N', 'C', 'C', 'R', 'Y', ' ', 'Q', 'B', 'J', 'A', ' ', + 'G', 'B', ' ', 'G', 'U', 'R', ' ', 'F', 'H', 'E', 'S', 'N', 'P', 'R', ' ', + 'B', 'S', ' ', 'U', 'R', 'Y', 'Y', '.', '\n', '\n', 'A', 'B', 'J', ',', ' ', + 'V', 'G', '\'', 'F', ' ', 'B', 'A', ' ', 'G', 'B', ' ', 'G', 'U', 'R', ' ', + 'S', 'V', 'A', 'N', 'Y', ' ', 'P', 'U', 'N', 'C', 'G', 'R', 'E', ' ', 'B', + 'S', ' ', 'Q', 'B', 'B', 'Z', '!', ' ', '-', '-', ' ', 'V', 'A', 'S', 'R', + 'E', 'A', 'B', '.', '\n', '\n', 'R', 'c', 'v', 'f', 'b', 'q', 'r', ' ', '3', + ',', ' ', 'V', 'A', 'S', 'R', 'E', 'A', 'B', ':', '\n', '-', '-', '-', '-', + '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', + '\n', '\n', 'G', 'U', 'R', ' ', 'Y', 'B', 'N', 'G', 'U', 'F', 'B', 'Z', 'R', + ' ', 'F', 'C', 'V', 'Q', 'R', 'E', 'Q', 'R', 'Z', 'B', 'A', ' ', 'G', 'U', + 'N', 'G', ' ', 'Z', 'N', 'F', 'G', 'R', 'E', 'Z', 'V', 'A', 'Q', 'R', 'Q', + ' ', 'G', 'U', 'R', ' ', 'V', 'A', 'I', 'N', 'F', 'V', 'B', 'A', ' ', 'B', + 'S', ' ', 'G', 'U', 'R', ' ', 'Z', 'B', 'B', 'A', ' ', 'O', 'N', 'F', 'R', + 'F', '\n', 'N', 'A', 'Q', ' ', 'P', 'N', 'H', 'F', 'R', 'Q', ' ', 'F', 'B', + ' ', 'Z', 'H', 'P', 'U', ' ', 'Q', 'R', 'N', 'G', 'U', ' ', 'U', 'N', 'F', + ' ', 'U', 'N', 'Q', ' ', 'V', 'G', 'F', ' ', 'N', 'F', 'F', ' ', 'X', 'V', + 'P', 'X', 'R', 'Q', ' ', 'S', 'B', 'E', ' ', 'N', 'Y', 'Y', ' ', 'G', 'V', + 'Z', 'R', '.', '\n', '\n', 'N', ' ', 'U', 'V', 'Q', 'Q', 'R', 'A', ' ', 'Q', + 'B', 'B', 'E', 'J', 'N', 'L', ' ', 'B', 'C', 'R', 'A', 'F', ' ', 'N', 'A', + 'Q', ' ', 'L', 'B', 'H', ' ', 'R', 'A', 'G', 'R', 'E', '.', ' ', ' ', 'L', + 'B', 'H', '\'', 'I', 'R', ' ', 'C', 'E', 'B', 'I', 'R', 'A', ' ', 'G', 'B', + 'B', ' ', 'G', 'B', 'H', 'T', 'U', ' ', 'S', 'B', 'E', ' ', 'U', 'R', 'Y', + 'Y', ' ', 'G', 'B', '\n', 'P', 'B', 'A', 'G', 'N', 'V', 'A', ',', ' ', 'N', + 'A', 'Q', ' ', 'A', 'B', 'J', ' ', 'U', 'R', 'Y', 'Y', ' ', 'N', 'G', ' ', + 'Y', 'N', 'F', 'G', ' ', 'C', 'Y', 'N', 'L', 'F', ' ', 'S', 'N', 'V', 'E', + ' ', '-', '-', ' ', 'S', 'B', 'E', ' ', 'L', 'B', 'H', ' ', 'R', 'Z', 'R', + 'E', 'T', 'R', ' ', 'S', 'E', 'B', 'Z', ' ', 'G', 'U', 'R', ' ', 'Q', 'B', + 'B', 'E', ' ', 'G', 'B', '\n', 'F', 'R', 'R', ' ', 'G', 'U', 'R', ' ', 'T', + 'E', 'R', 'R', 'A', ' ', 'S', 'V', 'R', 'Y', 'Q', 'F', ' ', 'B', 'S', ' ', + 'R', 'N', 'E', 'G', 'U', '!', ' ', ' ', 'U', 'B', 'Z', 'R', ' ', 'N', 'G', + ' ', 'Y', 'N', 'F', 'G', '.', '\n', '\n', 'L', 'B', 'H', ' ', 'J', 'B', 'A', + 'Q', 'R', 'E', ' ', 'J', 'U', 'N', 'G', '\'', 'F', ' ', 'O', 'R', 'R', 'A', + ' ', 'U', 'N', 'C', 'C', 'R', 'A', 'V', 'A', 'T', ' ', 'B', 'A', ' ', 'R', + 'N', 'E', 'G', 'U', ' ', 'J', 'U', 'V', 'Y', 'R', ' ', 'L', 'B', 'H', ' ', + 'J', 'R', 'E', 'R', ' ', 'O', 'N', 'G', 'G', 'Y', 'V', 'A', 'T', ' ', 'R', + 'I', 'V', 'Y', '\n', 'H', 'A', 'Y', 'R', 'N', 'F', 'U', 'R', 'Q', '.', ' ', + 'V', 'G', '\'', 'F', ' ', 'T', 'B', 'B', 'Q', ' ', 'G', 'U', 'N', 'G', ' ', + 'A', 'B', ' ', 'U', 'R', 'Y', 'Y', '-', ' ', 'F', 'C', 'N', 'J', 'A', ' ', + 'P', 'B', 'H', 'Y', 'Q', ' ', 'U', 'N', 'I', 'R', ' ', 'P', 'B', 'Z', 'R', + ' ', 'G', 'U', 'E', 'B', 'H', 'T', 'U', ' ', 'G', 'U', 'N', 'G', ' ', 'Q', + 'B', 'B', 'E', '\n', 'J', 'V', 'G', 'U', ' ', 'L', 'B', 'H', ' ', '.', '.', + '.', '\n', '\n', 'R', 'c', 'v', 'f', 'b', 'q', 'r', ' ', '4', ',', ' ', 'G', + 'U', 'L', ' ', 'S', 'Y', 'R', 'F', 'U', ' ', 'P', 'B', 'A', 'F', 'H', 'Z', + 'R', 'Q', ':', '\n', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', + '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', + '-', '-', '-', '-', '\n', '\n', 'G', 'U', 'R', ' ', 'F', 'C', 'V', 'Q', 'R', + 'E', ' ', 'Z', 'N', 'F', 'G', 'R', 'E', 'Z', 'V', 'A', 'Q', ' ', 'Z', 'H', + 'F', 'G', ' ', 'U', 'N', 'I', 'R', ' ', 'F', 'R', 'A', 'G', ' ', 'S', 'B', + 'E', 'G', 'U', ' ', 'V', 'G', 'F', ' ', 'Y', 'R', 'T', 'V', 'B', 'A', 'F', + ' ', 'B', 'S', ' ', 'U', 'R', 'Y', 'Y', 'F', 'C', 'N', 'J', 'A', ' ', 'O', + 'R', 'S', 'B', 'E', 'R', '\n', 'L', 'B', 'H', 'E', ' ', 'S', 'V', 'A', 'N', + 'Y', ' ', 'P', 'B', 'A', 'S', 'E', 'B', 'A', 'G', 'N', 'G', 'V', 'B', 'A', + ' ', 'J', 'V', 'G', 'U', ' ', 'G', 'U', 'N', 'G', ' ', 'G', 'R', 'E', 'E', + 'V', 'O', 'Y', 'R', ' ', 'O', 'R', 'N', 'F', 'G', ' ', 'S', 'E', 'B', 'Z', + ' ', 'U', 'R', 'Y', 'Y', '.', ' ', 'O', 'H', 'G', ' ', 'L', 'B', 'H', ' ', + 'F', 'G', 'R', 'C', 'C', 'R', 'Q', '\n', 'S', 'B', 'E', 'J', 'N', 'E', 'Q', + ' ', 'N', 'A', 'Q', ' ', 'O', 'E', 'B', 'H', 'T', 'U', 'G', ' ', 'S', 'B', + 'E', 'G', 'U', ' ', 'R', 'G', 'R', 'E', 'A', 'N', 'Y', ' ', 'Q', 'N', 'Z', + 'A', 'N', 'G', 'V', 'B', 'A', ' ', 'N', 'A', 'Q', ' ', 'F', 'H', 'S', 'S', + 'R', 'E', 'V', 'A', 'T', ' ', 'H', 'C', 'B', 'A', ' ', 'G', 'U', 'R', ' ', + 'U', 'B', 'E', 'Q', 'R', ' ', 'N', 'F', ' ', 'N', '\n', 'G', 'E', 'H', 'R', + ' ', 'U', 'R', 'E', 'B', ' ', 'J', 'B', 'H', 'Y', 'Q', ' ', 'V', 'A', ' ', + 'G', 'U', 'R', ' ', 'S', 'N', 'P', 'R', ' ', 'B', 'S', ' ', 'F', 'B', 'Z', + 'R', 'G', 'U', 'V', 'A', 'T', ' ', 'F', 'B', ' ', 'R', 'I', 'V', 'Y', '.', + '\n', '\n', 'O', 'R', 'F', 'V', 'Q', 'R', 'F', ',', ' ', 'F', 'B', 'Z', 'R', + 'B', 'A', 'R', ' ', 'J', 'N', 'F', ' ', 'T', 'B', 'A', 'A', 'N', ' ', 'C', + 'N', 'L', ' ', 'S', 'B', 'E', ' ', 'J', 'U', 'N', 'G', ' ', 'U', 'N', 'C', + 'C', 'R', 'A', 'R', 'Q', ' ', 'G', 'B', ' ', 'Q', 'N', 'V', 'F', 'L', ',', + ' ', 'L', 'B', 'H', 'E', ' ', 'C', 'R', 'G', ' ', 'E', 'N', 'O', 'O', 'V', + 'G', '.', '\n', '\n', 'O', 'H', 'G', ' ', 'A', 'B', 'J', ',', ' ', 'L', 'B', + 'H', ' ', 'F', 'R', 'R', ' ', 'F', 'C', 'E', 'R', 'N', 'Q', ' ', 'O', 'R', + 'S', 'B', 'E', 'R', ' ', 'L', 'B', 'H', ' ', 'Z', 'B', 'E', 'R', ' ', 'C', + 'B', 'G', 'R', 'A', 'G', 'V', 'N', 'Y', ' ', 'C', 'N', 'V', 'A', ' ', 'N', + 'A', 'Q', ' ', 'T', 'V', 'O', 'O', 'V', 'G', 'H', 'Q', 'R', ' ', 'N', 'F', + ' ', 'N', '\n', 'A', 'N', 'G', 'V', 'B', 'A', ' ', 'B', 'S', ' ', 'Q', 'R', + 'Z', 'B', 'A', 'F', ' ', 'E', 'H', 'A', ' ', 'N', 'Z', 'B', 'X', ' ', 'V', + 'A', ' ', 'B', 'H', 'E', ' ', 'P', 'V', 'G', 'V', 'R', 'F', '.', '\n', '\n', + 'A', 'R', 'K', 'G', ' ', 'F', 'G', 'B', 'C', ',', ' ', 'U', 'R', 'Y', 'Y', + ' ', 'B', 'A', ' ', 'R', 'N', 'E', 'G', 'U', '!', '\n' +}; enum mutex_type { MUTEX_COMMON, @@ -68,9 +158,9 @@ enum mutex_type { struct string { - struct mutex mutex; - struct mutex_spin mutex_spin; - struct mutex_rw mutex_rw; + struct mutex* mutex; + struct mutex_spin* mutex_spin; + struct mutex_rw* mutex_rw; char str[sizeof(src_str)/sizeof(char) + 1 /* +1 <=< '\0'*/ ]; int i; }; @@ -84,48 +174,48 @@ string_write(struct string* string, const enum mutex_type type) case MUTEX_COMMON: { for(;;) { - mutex_lock(&string->mutex); + mutex_lock(string->mutex); if((unsigned)string->i >= sizeof(src_str)/sizeof(char) + 1) { - mutex_unlock(&string->mutex); + mutex_unlock(string->mutex); break; } string->str[string->i] = src_str[string->i]; ++string->i; - mutex_unlock(&string->mutex); + mutex_unlock(string->mutex); } } break; case MUTEX_SPIN: { for(;;) { - mutex_spin_lock(&string->mutex_spin); + mutex_spin_lock(string->mutex_spin); if((unsigned)string->i >= sizeof(src_str)/sizeof(char) + 1) { - mutex_spin_unlock(&string->mutex_spin); + mutex_spin_unlock(string->mutex_spin); break; } string->str[string->i] = src_str[string->i]; ++string->i; - mutex_spin_unlock(&string->mutex_spin); + mutex_spin_unlock(string->mutex_spin); } } break; case MUTEX_RW: { for(;;) { - mutex_rw_wlock(&string->mutex_rw); + mutex_rw_wlock(string->mutex_rw); if((unsigned)string->i >= sizeof(src_str)/sizeof(char) + 1) { - mutex_rw_unlock(&string->mutex_rw); + mutex_rw_unlock(string->mutex_rw); break; } string->str[string->i] = src_str[string->i]; ++string->i; - mutex_rw_unlock(&string->mutex_rw); + mutex_rw_unlock(string->mutex_rw); } } break; @@ -136,33 +226,47 @@ string_write(struct string* string, const enum mutex_type type) static void string_read(struct string* string) { - ASSERT(string); int i = 0; + ASSERT(string); do { - mutex_rw_rlock(&string->mutex_rw); + mutex_rw_rlock(string->mutex_rw); i = string->i; - mutex_rw_unlock(&string->mutex_rw); + mutex_rw_unlock(string->mutex_rw); } while( (unsigned)i < sizeof(src_str)/sizeof(char)); - mutex_rw_rlock(&string->mutex_rw); + mutex_rw_rlock(string->mutex_rw); printf("%s\n", string->str); - mutex_rw_unlock(&string->mutex_rw); + mutex_rw_unlock(string->mutex_rw); } static void test_mutex(const enum mutex_type type) { - struct string string = { .str = { [0] = '\0' }, .i = 0 }; + struct string string; + struct time time_start, time_end, time_res; + char dump[32]; + + string.str[0] = '\0'; + string.i = 0; + switch(type) { - case MUTEX_COMMON: mutex_init(&string.mutex); break; - case MUTEX_SPIN: mutex_spin_init(&string.mutex_spin); break; - case MUTEX_RW: mutex_rw_init(&string.mutex_rw); break; + case MUTEX_COMMON: + string.mutex = mutex_create(); + NCHECK(string.mutex, NULL); + break; + case MUTEX_SPIN: + string.mutex_spin = mutex_spin_create(); + NCHECK(string.mutex_spin, NULL); + break; + case MUTEX_RW: + string.mutex_rw = mutex_rw_create(); + NCHECK(string.mutex_rw, NULL); + break; default: ASSERT(0); break; } - time_T time_start, time_end, time_res; time_current(&time_start); #pragma omp parallel @@ -186,7 +290,6 @@ test_mutex(const enum mutex_type type) time_current(&time_end); time_sub(&time_res, &time_end, &time_start); - char dump[32]; time_dump (&time_res, TIME_MSEC|TIME_USEC, @@ -203,9 +306,9 @@ test_mutex(const enum mutex_type type) } switch(type) { - case MUTEX_COMMON: mutex_destroy(&string.mutex); break; - case MUTEX_SPIN: mutex_spin_destroy(&string.mutex_spin); break; - case MUTEX_RW: mutex_rw_destroy(&string.mutex_rw); break; + case MUTEX_COMMON: mutex_destroy(string.mutex); break; + case MUTEX_SPIN: mutex_spin_destroy(string.mutex_spin); break; + case MUTEX_RW: mutex_rw_destroy(string.mutex_rw); break; default: ASSERT(0); break; } } diff --git a/src/test_ref.c b/src/test_ref.c @@ -15,9 +15,9 @@ release(ref_T* ref) int main(int argc, char** argv) { + struct test test; (void)argc, (void)argv; - struct test test; ref_init(&test.ref); test.val = (int)0xDEADBEEF; diff --git a/src/test_signal.c b/src/test_signal.c @@ -37,27 +37,31 @@ sig1_func(void* arg, void* data) int main(int argc, char** argv) { - (void)argc, (void)argv; - struct ctxt ctxt; - signal_T signals[SIGNALS_COUNT]; - FOR_EACH(int, i, 0, SIGNALS_COUNT) signal_init(&signals[i]); - + struct ctxt ctxt; struct callback clbk0_a; struct callback clbk0_b; struct callback clbk0_c; struct callback clbk1_a; struct callback clbk1_b; + int i = 0; + int array[] = { 12, -1, 2, 1 }; + + (void)argc, (void)argv; + + FOR_EACH(i, 0, SIGNALS_COUNT) + signal_init(&signals[i]); + callback_init(&clbk0_a); callback_init(&clbk0_b); callback_init(&clbk0_c); callback_init(&clbk1_a); callback_init(&clbk1_b); callback_setup(&clbk0_a, sig0_func1, NULL); - callback_setup(&clbk0_b, sig0_func2, (int[]){12}); - callback_setup(&clbk0_c, sig0_func2, (int[]){-1}); - callback_setup(&clbk1_a, sig1_func, (int[]){2}); - callback_setup(&clbk1_b, sig1_func, (int[]){1}); + callback_setup(&clbk0_b, sig0_func2, array + 0); + callback_setup(&clbk0_c, sig0_func2, array + 1); + callback_setup(&clbk1_a, sig1_func, array + 2); + callback_setup(&clbk1_b, sig1_func, array + 3); ctxt.sig0_func1_invoked = 0; ctxt.sig0_func2_sum = 0; diff --git a/src/test_time.c b/src/test_time.c @@ -0,0 +1,28 @@ +#include "clock_time.h" +#include <stdlib.h> + +int +main(int argc, char** argv) +{ + struct time start, end, res; + char dump[512]; + int64_t time = 0; + int64_t i = 0; + (void)argc, (void)argv; + + time_current(&start); + FOR_EACH(i, 0, INT32_MAX / 64); /* Active wait */ + time_current(&end); + + time_sub(&res, &end, &start); + time = time_val(&res, TIME_NSEC); + CHECK(time > 0, 1 ); + CHECK(time_val(&res, TIME_USEC), time / 1000); + CHECK(time_val(&res, TIME_MSEC), time / 1000000); + CHECK(time_val(&res, TIME_SEC), time / 1000000000); + + time_dump + (&res, TIME_SEC|TIME_MSEC|TIME_USEC|TIME_NSEC, NULL, dump, sizeof(dump)); + printf("%s\n", dump); + return 0; +}