From 0d21ac12bfdd22afd3d6551cef4e23ca4713be7c Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Fri, 17 Mar 2017 22:02:17 +0100 Subject: [PATCH] Port mutex to use static inline instead of MACRO: * cleaner * fix bug in existing code detected by the changes. *** Break API (you need to go to lower case instead of upper case) *** --- README.md | 57 ++++---- example/ex04.c | 22 +-- m-buffer.h | 48 +++--- m-mutex.h | 342 ++++++++++++++++++++++++++++--------------- tests/test-mbuffer.c | 47 +++--- tests/test-mmutex.c | 11 +- 6 files changed, 311 insertions(+), 216 deletions(-) diff --git a/README.md b/README.md index 7640c79c..90e76b1b 100644 --- a/README.md +++ b/README.md @@ -1653,41 +1653,41 @@ It was needed due to the low adoption rate of the C11 equivalent layer. Example: - M_THREAD_T idx_p; - M_THREAD_T idx_c; + m_thread_t idx_p; + m_thread_t idx_c; - M_THREAD_CREATE (idx_p, conso_function, NULL); - M_THREAD_CREATE (idx_c, prod_function, NULL); - M_THREAD_JOIN(idx_p; - M_THREAD_JOIN(idx_c); + m_thread_create (idx_p, conso_function, NULL); + m_thread_create (idx_c, prod_function, NULL); + m_thread_join (idx_p; + m_thread_join (idx_c); #### methods The following methods are available: -#### M\_MUTEX\_T +#### m\_mutex\_t A type representating a mutex. -##### void M\_MUTEX\_INIT(mutex) +##### void m\_mutex\_init(mutex) -Initialize the variable mutex of type M\_MUTEX\_T. +Initialize the variable mutex of type m\_mutex\_t. If the initialization fails, the program aborts. -##### void M\_MUTEX\_CLEAR(mutex) +##### void m\_mutex\_clear(mutex) -Clear the variable mutex of type M\_MUTEX\_T. +Clear the variable mutex of type m\_mutex\_t. If the variable is not initialized, the behavior is undefined. -##### void M\_MUTEX\_LOCK(mutex) +##### void m\_mutex\_lock(mutex) -Lock the variable mutex of type M\_MUTEX\_T for exclusive use. +Lock the variable mutex of type m\_mutex\_t for exclusive use. If the variable is not free, it will wait indefinitely until it is. If the variable is not initialized, the behavior is undefined. -##### void M\_MUTEX\_UNLOCK(mutex) +##### void m\_mutex\_unlock(mutex) -Unlock the variable mutex of type M\_MUTEX\_T for exclusive use. +Unlock the variable mutex of type m\_mutex\_t for exclusive use. If the variable is not locked, the behavior is undefined. If the variable is not initialized, the behavior is undefined. @@ -1708,41 +1708,41 @@ Example: } } -#### M\_COND\_T +#### m\_cond\_t A type representating a conditionnal variable, used within a mutex section. -##### void M\_COND\_INIT(cond) +##### void m\_cond\_init(m\_cond\_t cond) -Initialize the conditional variable cond of type M\_COND\_T. +Initialize the conditional variable cond of type m\_cond\_t. If the initialization failed, the program aborts. -##### void M\_COND\_CLEAR(cond) +##### void m\_cond\_clear(m\_cond\_t cond) -Clear the variable cond of type M\_COND\_T. +Clear the variable cond of type m\_cond\_t. If the variable is not initialized, the behavior is undefined. -##### void M\_COND\_SIGNAL(cond) +##### void m\_cond\_signal(m\_cond\_t cond) Within a mutex exclusive section, -signal that the event associated to the variable cond of type M\_COND\_T +signal that the event associated to the variable cond of type m\_cond\_t has occured to other threads. If the variable is not initialized, the behavior is undefined. -##### void M\_COND\_WAIT(cond, mutex) +##### void m\_cond\_wait(m\_cond\_t cond, m\_mutex\_t mutex) Within a mutex exclusive section defined by mutex, -wait indefinitely for the event associated to the variable cond of type M\_COND\_T +wait indefinitely for the event associated to the variable cond of type m\_cond\_t to occur. IF multiple threads wait for the same event, which thread to awoken is not specified. If any variable is not initialized, the behavior is undefined. -#### M\_THREAD\_T +#### m\_thread\_t A type representating an id of a thread. -##### M\_THREAD\_CREATE(thread, function, argument) +##### void m\_thread\_create(m\_thread\_t thread, void (*function)(void*), void *argument) Create a new thread and set the it of the thread to 'thread'. The new thread run the code function(argument) with @@ -1750,13 +1750,10 @@ argument a 'void \*' and function taking a 'void \*' and returning nothing. If the initialization fails, the program aborts. -##### M\_THREAD\_JOIN(thread) +##### void m\_thread\_join(m\_thread\_tthread) Wait for the thread 'thread' to exit. -##### M\_THREAD\_EXIT(arg) - -Quit the current thread. 'arg' is currently unused. ###M-ALGO diff --git a/example/ex04.c b/example/ex04.c index 192fe160..15b51e0e 100644 --- a/example/ex04.c +++ b/example/ex04.c @@ -104,7 +104,7 @@ BUFFER_DEF(bigdata, shared_bigdata_t, MY_QUEUE_SIZE, buffer_bigdata_t buf_t1tot2; buffer_bigdata_t buf_t1tot3; buffer_bigdata_t buf_t3tot4; -M_THREAD_T t1, t2, t3, t4; +m_thread_t t1, t2, t3, t4; static void initbuf(void) { @@ -122,6 +122,7 @@ static void clearbuf(void) static void thread1 (void *arg) { + (void) arg; while (continue_threading_g) { shared_bigdata_t ptr; shared_bigdata_init_new (ptr); @@ -133,6 +134,7 @@ static void thread1 (void *arg) } static void thread2 (void *arg) { + (void) arg; while (continue_threading_g) { shared_bigdata_t ptr; shared_bigdata_init (ptr); @@ -143,6 +145,7 @@ static void thread2 (void *arg) } static void thread3 (void *arg) { + (void) arg; while (continue_threading_g) { shared_bigdata_t ptr; shared_bigdata_init (ptr); @@ -154,6 +157,7 @@ static void thread3 (void *arg) } static void thread4 (void *arg) { + (void) arg; while (continue_threading_g) { shared_bigdata_t ptr; shared_bigdata_init (ptr); @@ -168,18 +172,18 @@ static void init(void) { initbuf(); continue_threading_g = true; - M_THREAD_CREATE(t1, thread1, NULL); - M_THREAD_CREATE(t2, thread2, NULL); - M_THREAD_CREATE(t3, thread3, NULL); - M_THREAD_CREATE(t4, thread4, NULL); + m_thread_create(t1, thread1, NULL); + m_thread_create(t2, thread2, NULL); + m_thread_create(t3, thread3, NULL); + m_thread_create(t4, thread4, NULL); } static void clear(void) { - M_THREAD_JOIN(t1); - M_THREAD_JOIN(t2); - M_THREAD_JOIN(t3); - M_THREAD_JOIN(t4); + m_thread_join(t1); + m_thread_join(t2); + m_thread_join(t3); + m_thread_join(t4); clearbuf(); } diff --git a/m-buffer.h b/m-buffer.h index bd2079b3..10ae1724 100644 --- a/m-buffer.h +++ b/m-buffer.h @@ -57,9 +57,9 @@ typedef enum { #define BUFFERI_DEF2(name, type, m_size, policy, oplist) \ typedef struct M_C3(buffer_, name, _s) { \ - M_MUTEX_T mutex; \ - M_COND_T there_is_data; \ - M_COND_T there_is_room_for_data; \ + m_mutex_t mutex; \ + m_cond_t there_is_data; \ + m_cond_t there_is_room_for_data; \ BUFFERI_IF_CTE_SIZE(m_size)( ,size_t size;) \ size_t idx_prod, idx_cons, number; \ type *data; \ @@ -72,9 +72,9 @@ static inline void \ BUFFERI_IF_CTE_SIZE(m_size)(assert(size == m_size), v->size = size); \ v->idx_prod = v->idx_cons = v->number = 0; \ if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \ - M_MUTEX_INIT(v->mutex); \ - M_COND_INIT(v->there_is_data); \ - M_COND_INIT(v->there_is_room_for_data); \ + m_mutex_init(v->mutex); \ + m_cond_init(v->there_is_data); \ + m_cond_init(v->there_is_room_for_data); \ } else \ assert(((policy)&BUFFER_UNBLOCKING) == BUFFER_UNBLOCKING); \ v->data = M_MEMORY_REALLOC (type, NULL, BUFFERI_SIZE(m_size)); \ @@ -109,17 +109,13 @@ static inline void \ static inline void \ M_C3(buffer_, name, _clear)(M_C3(buffer_, name,_t) v) \ { \ - int rc; \ M_C3(bufferi_, name, _clear_obj)(v); \ M_MEMORY_FREE (v->data); \ v->data = NULL; \ if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \ - rc = M_MUTEX_CLEAR(v->mutex); \ - assert (rc == 0); \ - rc = M_COND_CLEAR(v->there_is_data); \ - assert (rc == 0); \ - rc = M_COND_CLEAR(v->there_is_room_for_data); \ - assert (rc == 0); \ + m_mutex_clear(v->mutex); \ + m_cond_clear(v->there_is_data); \ + m_cond_clear(v->there_is_room_for_data); \ } \ } \ \ @@ -128,12 +124,12 @@ static inline void \ { \ assert (v->number <= BUFFERI_SIZE(m_size)); \ if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) \ - M_MUTEX_LOCK(v->mutex); \ + m_mutex_lock(v->mutex); \ if (((policy)&BUFFER_PUSH_INIT_POP_MOVE) != 0) \ M_C3(bufferi_, name, _clear_obj)(v); \ if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \ - M_COND_SIGNAL(v->there_is_room_for_data); \ - M_MUTEX_UNLOCK(v->mutex); \ + m_cond_signal(v->there_is_room_for_data); \ + m_mutex_unlock(v->mutex); \ } \ } \ \ @@ -155,14 +151,14 @@ static inline void \ M_C3(buffer_, name, _push)(M_C3(buffer_, name,_t) v, type const data) \ { \ if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \ - M_MUTEX_LOCK(v->mutex); \ + m_mutex_lock(v->mutex); \ while (((policy)&BUFFER_PUSH_OVERWRITE) == 0 \ && M_C3(buffer_, name, _full_p)(v)) { \ if (((policy) & BUFFER_UNBLOCKING) == BUFFER_UNBLOCKING) { \ - M_MUTEX_UNLOCK(v->mutex); \ + m_mutex_unlock(v->mutex); \ return false; \ } \ - M_COND_WAIT(v->there_is_room_for_data, v->mutex); \ + m_cond_wait(v->there_is_room_for_data, v->mutex); \ } \ } else if (((policy)&BUFFER_PUSH_OVERWRITE) == 0 \ && M_C3(buffer_, name, _full_p)(v)) \ @@ -195,8 +191,8 @@ static inline void \ v->number ++; \ \ if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \ - M_COND_SIGNAL(v->there_is_data); \ - M_MUTEX_UNLOCK(v->mutex); \ + m_cond_signal(v->there_is_data); \ + m_mutex_unlock(v->mutex); \ } \ return true; \ } \ @@ -205,13 +201,13 @@ static inline void \ M_C3(buffer_, name, _pop)(type *data, M_C3(buffer_, name,_t) v) \ { \ if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \ - M_MUTEX_LOCK(v->mutex); \ + m_mutex_lock(v->mutex); \ while (M_C3(buffer_, name, _empty_p)(v)) { \ if (((policy) & BUFFER_UNBLOCKING) == BUFFER_UNBLOCKING) { \ - M_MUTEX_UNLOCK(v->mutex); \ + m_mutex_unlock(v->mutex); \ return false; \ } \ - M_COND_WAIT(v->there_is_data, v->mutex); \ + m_cond_wait(v->there_is_data, v->mutex); \ } \ } else if (M_C3(buffer_, name, _empty_p)(v)) \ return false; \ @@ -234,8 +230,8 @@ static inline void \ v->number --; \ \ if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \ - M_COND_SIGNAL(v->there_is_room_for_data); \ - M_MUTEX_UNLOCK(v->mutex); \ + m_cond_signal(v->there_is_room_for_data); \ + m_mutex_unlock(v->mutex); \ } \ return true; \ } \ diff --git a/m-mutex.h b/m-mutex.h index 63aa9ae2..f1c77186 100644 --- a/m-mutex.h +++ b/m-mutex.h @@ -37,96 +37,161 @@ #include -#define M_MUTEX_T mtx_t -#define M_MUTEX_INIT(_mutex) do { \ - int rc = mtx_init(&(_mutex), mtx_plain); \ - M_ASSERT_INIT (rc == 0); \ - } while (0) -#define M_MUTEX_CLEAR(_mutex) mtx_destroy(&(_mutex)) -#define M_MUTEX_LOCK(_mutex) mtx_lock(&(_mutex)) -#define M_MUTEX_UNLOCK(_mutex) mtx_unlock(&(_mutex)) +typedef mtx_t m_mutex_t[1]; +typedef cnd_t m_cond_t[1]; +typedef thrd_t m_thread_t[1]; + +static inline void m_mutex_init(m_mutex_t m) +{ + int rc = mtx_init(m, mtx_plain); + M_ASSERT_INIT (rc == 0); +} + +static inline void m_mutex_clear(m_mutex_t m) +{ + mtx_destroy(m); +} + +static inline void m_mutex_lock(m_mutex_t m) +{ + mtx_lock(m); +} + +static inline void m_mutex_unlock(m_mutex_t m) +{ + mtx_unlock(m); +} + +static inline void m_cond_init(m_cond_t c) +{ + int rc = cnd_init(c); + M_ASSERT_INIT (rc == 0); +} + +static inline void m_cond_clear(m_cond_t c) +{ + cnd_destroy(c); +} + +static inline void m_cond_clear(m_cond_t c) +{ + cnd_signal(c); +} + +static inline void m_cond_wait(m_cond_t c, m_mutex_t m) +{ + cnd_wait(c, m); +} + +static inline void m_thread_create(m_thread_t t, void (*func)(void*), void* arg) +{ + int rc = thrd_create(t, ((int)(*)(void*))func, arg); + M_ASSERT_INIT (rc == thrd_success); +} + +static inline void m_thread_join(m_thread_t t) +{ + int rc = thrd_join(t, NULL); + assert (rc == thrd_success); +} + +// Internal type, not exported. +typedef once_flag m_oncei_t[1]; +#define M_ONCEI_INIT_VALUE { ONCE_FLAG_INIT } +static inline void m_oncei_call(m_oncei_t o, void (*func)(void)) +{ + call_once(o,func); +} -#define M_COND_T cnd_t -#define M_COND_INIT(_cond) do { \ - int rc = cnd_init(&(_cond)); \ - M_ASSERT_INIT (rc == 0); \ - } while (0) -#define M_COND_CLEAR(_cond) cnd_destroy(&(_cond)) -#define M_COND_SIGNAL(_cond) cnd_signal(&(_cond)) -#define M_COND_WAIT(_cond, _mutex) cnd_wait(&(_cond),&(_mutex)) -#define M_THREAD_T thrd_t -#define M_THREAD_CREATE(h, func, arg) do { \ - int rc = thrd_create(&(h), ((int)(*)(void*))func, arg); \ - M_ASSERT_INIT (rc == thrd_success); \ - } while (0) -#define M_THREAD_JOIN(h) do { \ - int rc = thrd_join((h), NULL); \ - assert (rc == thrd_success); \ - } while (0) -#define M_THREAD_EXIT(arg) thrd_exit(arg) -#define M_ONCEI_T once_flag -#define M_ONCEI_INIT_VALUE ONCE_FLAG_INIT -#define M_ONCEI_CALL(once,func) call_once(&(once),(func)) #elif defined(WIN32) || defined(_WIN32) /****************************** WIN32 version ******************************/ #include - -#define M_MUTEX_T HANDLE -#define M_MUTEX_INIT(_mutex) do { \ - (_mutex) = CreateMutex(NULL, FALSE, NULL); \ - M_ASSERT_INIT((_mutex) != NULL); \ - } while (0) -#define M_MUTEX_CLEAR(_mutex) CloseHandle(_mutex) -#define M_MUTEX_LOCK(_mutex) do { \ - DWORD dwWaitResult = WaitForSingleObject((_mutex), INFINITE); \ - assert (dwWaitResult == WAIT_OBJECT_0); \ - } while(0) -#define M_MUTEX_TRYLOCK(m) (WaitForSingleObject((m), 0) == WAIT_OBJECT_0) -#define M_MUTEX_UNLOCK(_mutex) ReleaseMutex(_mutex) -#define M_MUTEXI_INIT_VALUE NULL -#define M_MUTEXI_LAZY_LOCK(_mutex) do { \ - volatile HANDLE *addr = &(_mutex); \ - if (*addr == NULL) { \ - /* Try to create one, affect it atomicaly and otherwise clears it */ \ - HANDLE h = CreateMutex(NULL, FALSE, NULL); \ - if (InterlockedCompareExchangePointer((PVOID*)addr, (PVOID)h, NULL) != NULL) \ - CloseHandle(h); \ - /* FIXME: there is no way to clean the mutex at program exit... */ \ - } \ - DWORD dwWaitResult = WaitForSingleObject(*addr, INFINITE); \ - assert (dwWaitResult == WAIT_OBJECT_0); \ - } while(0) -#define M_COND_T HANDLE -#define M_COND_INIT(_cond) do { \ - (_cond) = = CreateEvent (NULL, FALSE, FALSE, NULL); \ - M_ASSERT_INIT ((_cond) != NULL); \ - } while (0) -#define M_COND_CLEAR(_cond) CloseHandle(_cond) -#define M_COND_SIGNAL(_cond) PulseEvent(_cond) -#define M_COND_WAIT(_cond, _mutex) do { \ - DWORD dwWaitResult = SignalObjectAndWait((_mutex),(_cond),INFINITE,FALSE); \ - assert (dwWaitResult == WAIT_OBJECT_0); \ - dwWaitResult = WaitForSingleObject((_mutex), INFINITE); \ - assert (dwWaitResult == WAIT_OBJECT_0); \ - } while(0) +typedef HANDLE m_mutex_t[1]; +typedef HANDLE m_cond_t[1]; +typedef HANDLE m_thread_t[1]; + +static inline void m_mutex_init(m_mutex_t m) +{ + *m = CreateMutex(NULL, FALSE, NULL); + M_ASSERT_INIT(*m != NULL); +} + +static inline void m_mutex_clear(m_mutex_t m) +{ + CloseHandle(*m); +} + +static inline void m_mutex_lock(m_mutex_t m) +{ + DWORD dwWaitResult = WaitForSingleObject(*m, INFINITE); + assert (dwWaitResult == WAIT_OBJECT_0); +} + +static inline void m_mutex_unlock(m_mutex_t m) +{ + ReleaseMutex(*m); +} + +// Internal function, not exported +#define M_MUTEXI_INIT_VALUE { NULL } +static inline m_mutexi_lazy_lock (m_mutex_t m) +{ + volatile HANDLE *addr = m; + if (*addr == NULL) { + /* Try to create one, affect it atomicaly and otherwise clears it */ + HANDLE h = CreateMutex(NULL, FALSE, NULL); + if (InterlockedCompareExchangePointer((PVOID*)addr, (PVOID)h, NULL) != NULL) + CloseHandle(h); + /* FIXME: there is no way to clean the mutex at program exit... */ + } + DWORD dwWaitResult = WaitForSingleObject(*addr, INFINITE); + assert (dwWaitResult == WAIT_OBJECT_0); +} + +static inline void m_cond_init(m_cond_t c) +{ + *c = = CreateEvent (NULL, FALSE, FALSE, NULL); + M_ASSERT_INIT (*c != NULL); +} + +static inline void m_cond_clear(m_cond_t c) +{ + CloseHandle(*c); +} + +static inline void m_cond_signal(m_cond_t c) +{ + PulseEvent(*c); +} + +static inline void m_cond_wait(m_cond_t c, m_mutex_t m) +{ + DWORD dwWaitResult = SignalObjectAndWait(*m, *c, INFINITE,FALSE); + assert (dwWaitResult == WAIT_OBJECT_0); + dwWaitResult = WaitForSingleObject(*m, INFINITE); + assert (dwWaitResult == WAIT_OBJECT_0); +} + +static inline void m_thread_create(m_thread_t t, void (*func)(void*), void *arg) +{ + *t = CreateThread(NULL, 0, (unsigned int (*)(void*)) func, arg, 0, NULL); + M_ASSERT_INIT (*t != NULL); +} + +static inline void m_thread_join(m_thread_t t) +{ + DWORD dwWaitResult = WaitForSingleObject(*t, INFINITE); + assert (dwWaitResult == WAIT_OBJECT_0); +} + + -#define M_THREAD_T HANDLE -#define M_THREAD_CREATE(h, func, arg) do { \ - (h) = CreateThread(NULL, 0, (unsigned int (*)(void*)) func, arg, \ - 0, NULL); \ - M_ASSERT_INIT ((h) != NULL); \ - } while (0) -#define M_THREAD_JOIN(h) do { \ - DWORD dwWaitResult = WaitForSingleObject((h), INFINITE); \ - assert (dwWaitResult == WAIT_OBJECT_0); \ - } while (0) -#define M_THREAD_EXIT(arg) ExitThread(arg) #else @@ -134,40 +199,77 @@ #include -#define M_MUTEX_T pthread_mutex_t -#define M_MUTEX_INIT(_mutex) do { \ - int _rc = pthread_mutex_init(&(_mutex), NULL); \ - M_ASSERT_INIT (_rc == 0); \ - } while (0) -#define M_MUTEX_CLEAR(_mutex) pthread_mutex_destroy(&(_mutex)) -#define M_MUTEX_LOCK(_mutex) pthread_mutex_lock(&(_mutex)) -#define M_MUTEX_UNLOCK(_mutex) pthread_mutex_unlock(&(_mutex)) -#define M_MUTEXI_INIT_VALUE PTHREAD_MUTEX_INITIALIZER -#define M_MUTEXI_LAZY_LOCK(_mutex) M_MUTEX_LOCK(_mutex) +typedef pthread_mutex_t m_mutex_t[1]; +typedef pthread_cond_t m_cond_t[1]; +typedef pthread_t m_thread_t[1]; -#define M_COND_T pthread_cond_t -#define M_COND_INIT(_cond) do { \ - int _rc = pthread_cond_init(&(_cond), NULL); \ - M_ASSERT_INIT (_rc == 0); \ - } while (0) -#define M_COND_CLEAR(_cond) pthread_cond_destroy(&(_cond)) -#define M_COND_SIGNAL(_cond) pthread_cond_signal(&(_cond)) -#define M_COND_WAIT(_cond, _mutex) pthread_cond_wait(&(_cond),&(_mutex)) - -#define M_THREAD_T pthread_t -#define M_THREAD_CREATE(h, func, arg) do { \ - int _rc = pthread_create(&(h), NULL, (void*(*)(void*))func, arg); \ - M_ASSERT_INIT (_rc == 0); \ - } while (0) -#define M_THREAD_JOIN(h) do { \ - int _rc = pthread_join((h), NULL); \ - assert (_rc == 0); \ - } while (0) -#define M_THREAD_EXIT(arg) pthread_exit((void*)arg) +static inline void m_mutex_init(m_mutex_t m) +{ + int _rc = pthread_mutex_init(m, NULL); + M_ASSERT_INIT (_rc == 0); +} -#define M_ONCEI_T pthread_once_t -#define M_ONCEI_INIT_VALUE PTHREAD_ONCE_INIT -#define M_ONCEI_CALL(once,func) pthread_once(&(once),(func)) +static inline void m_mutex_clear(m_mutex_t m) +{ + pthread_mutex_destroy(m); +} + +static inline void m_mutex_lock(m_mutex_t m) +{ + pthread_mutex_lock(m); +} + +static inline void m_mutex_unlock(m_mutex_t m) +{ + pthread_mutex_unlock(m); +} + +#define M_MUTEXI_INIT_VALUE { PTHREAD_MUTEX_INITIALIZER } +static inline void m_mutexi_lazy_lock(m_mutex_t m) +{ + pthread_mutex_lock(m); +} + +static inline void m_cond_init(m_cond_t c) +{ + int _rc = pthread_cond_init(c, NULL); + M_ASSERT_INIT (_rc == 0); +} + +static inline void m_cond_clear(m_cond_t c) +{ + pthread_cond_destroy(c); +} + +static inline void m_cond_signal(m_cond_t c) +{ + pthread_cond_signal(c); +} + +static inline void m_cond_wait(m_cond_t c, m_mutex_t m) +{ + pthread_cond_wait(c, m); +} + +static inline void m_thread_create(m_thread_t t, void (*func)(void*), void *arg) +{ + int _rc = pthread_create(t, NULL, (void*(*)(void*))func, arg); + M_ASSERT_INIT (_rc == 0); +} + +static inline void m_thread_join(m_thread_t t) +{ + int _rc = pthread_join(*t, NULL); + assert (_rc == 0); +} + +// Internal type, not exported. +typedef pthread_once_t m_oncei_t[1]; +#define M_ONCEI_INIT_VALUE { PTHREAD_ONCE_INIT } +static inline void m_oncei_call(m_oncei_t o, void (*func)(void)) +{ + pthread_once(o,func); +} #endif @@ -182,22 +284,22 @@ */ /* NOTE: Either using direct support by the OS (WIN32/PTHREAD) or using C11's ONCE mechanism */ -#ifdef M_MUTEXI_LAZY_LOCK -# define M_LOCK_DECL(name) M_MUTEX_T name = M_MUTEXI_INIT_VALUE +#ifdef M_MUTEXI_INIT_VALUE +# define M_LOCK_DECL(name) m_mutex_t name = M_MUTEXI_INIT_VALUE # define M_LOCK(name) \ - M_LOCKI_DO(name, M_C(local_cont_, __LINE__), M_MUTEXI_LAZY_LOCK, M_MUTEX_UNLOCK) + M_LOCKI_DO(name, M_C(local_cont_, __LINE__), m_mutexi_lazy_lock, m_mutex_unlock) #else # define M_LOCK_DECL(name) \ - M_MUTEX_T name; \ + m_mutex_t name; \ static void M_C(m_mutex_init_, name)(void) { \ - M_MUTEX_INIT(name); \ + m_mutex_init(name); \ } \ - M_ONCEI_T M_C(m_once_, name) = M_ONCEI_INIT_VALUE + m_oncei_t M_C(m_once_, name) = M_ONCEI_INIT_VALUE # define M_LOCKI_BY_ONCE(name) \ - (M_ONCEI_CALL(M_C(m_once_, name), M_C(m_mutex_init_, name)), \ - M_MUTEX_LOCK(name), (void) 0 ) + (m_oncei_call(M_C(m_once_, name), M_C(m_mutex_init_, name)), \ + m_mutex_lock(name), (void) 0 ) # define M_LOCK(name) \ - M_LOCKI_DO(name, M_C(local_cont_, __LINE__), M_LOCKI_BY_ONCE, M_MUTEX_UNLOCK) + M_LOCKI_DO(name, M_C(local_cont_, __LINE__), M_LOCKI_BY_ONCE, m_mutex_unlock) #endif #define M_LOCKI_DO(name, cont, lock, unlock) \ diff --git a/tests/test-mbuffer.c b/tests/test-mbuffer.c index 316a0b15..d7e7c0e3 100644 --- a/tests/test-mbuffer.c +++ b/tests/test-mbuffer.c @@ -39,7 +39,7 @@ BUFFER_DEF(mpz, mpz_t, 32, BUFFER_QUEUE, (INIT(mpz_init), INIT_SET(mpz_init_set) buffer_uint_t g_buff; -static void *conso(void *arg) +static void conso(void *arg) { unsigned int j; assert (arg == NULL); @@ -47,31 +47,29 @@ static void *conso(void *arg) buffer_uint_pop(&j, g_buff); assert (j < 1000); } - return NULL; } -static void *prod(void *arg) +static void prod(void *arg) { assert (arg == NULL); for(unsigned int i = 0; i < 1000;i++) buffer_uint_push(g_buff, i); - return NULL; } static void test_global(void) { - M_THREAD_T idx_p[100]; - M_THREAD_T idx_c[100]; + m_thread_t idx_p[100]; + m_thread_t idx_c[100]; buffer_uint_init(g_buff, 10); for(int i = 0; i < 100; i++) { - M_THREAD_CREATE (idx_p[i], conso, NULL); - M_THREAD_CREATE (idx_c[i], prod, NULL); + m_thread_create (idx_p[i], conso, NULL); + m_thread_create (idx_c[i], prod, NULL); } for(int i = 0; i < 100;i++) { - M_THREAD_JOIN(idx_p[i]); - M_THREAD_JOIN(idx_c[i]); + m_thread_join(idx_p[i]); + m_thread_join(idx_c[i]); } buffer_uint_clear(g_buff); @@ -178,7 +176,7 @@ BUFFER_DEF(itest, test_t *, 16, BUFFER_PUSH_INIT_POP_MOVE, static buffer_itest_t comm1; static buffer_itest_t comm2; -static void *test_conso1(void *arg) +static void test_conso1(void *arg) { test_t *p; assert (arg == NULL); @@ -188,9 +186,9 @@ static void *test_conso1(void *arg) assert (p->buffer[j] == (char) ((j * j * 17) + j * 42 + 1)); ishared_itest_clear(p); } - return NULL; } -static void *test_conso2(void *arg) + +static void test_conso2(void *arg) { test_t *p; assert (arg == NULL); @@ -200,9 +198,9 @@ static void *test_conso2(void *arg) assert (p->buffer[j] == (char) ((j * j * 17) + j * 42 + 1)); ishared_itest_clear(p); } - return NULL; } -static void *test_prod(void *arg) + +static void test_prod(void *arg) { assert (arg == NULL); for(unsigned int i = 0; i < 10;i++) { @@ -213,27 +211,26 @@ static void *test_prod(void *arg) buffer_itest_push(comm2, p); ishared_itest_clear(p); } - return NULL; } static void test_global_ishared(void) { - M_THREAD_T idx_p[100]; - M_THREAD_T idx_c1[100]; - M_THREAD_T idx_c2[100]; + m_thread_t idx_p[100]; + m_thread_t idx_c1[100]; + m_thread_t idx_c2[100]; buffer_itest_init(comm1, 16); buffer_itest_init(comm2, 16); for(int i = 0; i < 100; i++) { - M_THREAD_CREATE (idx_c1[i], test_conso1, NULL); - M_THREAD_CREATE (idx_c2[i], test_conso2, NULL); - M_THREAD_CREATE (idx_p[i], test_prod, NULL); + m_thread_create (idx_c1[i], test_conso1, NULL); + m_thread_create (idx_c2[i], test_conso2, NULL); + m_thread_create (idx_p[i], test_prod, NULL); } for(int i = 0; i < 100;i++) { - M_THREAD_JOIN(idx_p[i]); - M_THREAD_JOIN(idx_c1[i]); - M_THREAD_JOIN(idx_c2[i]); + m_thread_join(idx_p[i]); + m_thread_join(idx_c1[i]); + m_thread_join(idx_c2[i]); } buffer_itest_clear(comm1); diff --git a/tests/test-mmutex.c b/tests/test-mmutex.c index 80cd367c..4eebc8d8 100644 --- a/tests/test-mmutex.c +++ b/tests/test-mmutex.c @@ -27,26 +27,25 @@ M_LOCK_DECL(global_lock); unsigned long long n = 0; -static void *f(void *arg) +static void f(void *arg) { (void)arg; // Unused // Global lock to perform atomic addition. M_LOCK(global_lock) { n += 1; } - return NULL; -} + } static void test_global(void) { - M_THREAD_T idx_p[100]; + m_thread_t idx_p[100]; n = 0; for(int i = 0; i < 100; i++) { - M_THREAD_CREATE (idx_p[i], f, NULL); + m_thread_create (idx_p[i], f, NULL); } for(int i = 0; i < 100;i++) { - M_THREAD_JOIN(idx_p[i]); + m_thread_join(idx_p[i]); } assert (n == 100); }