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:
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;
+}