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) ***
This commit is contained in:
Patrick Pelissier committed 2017-03-17 22:02:17 +01:00
1 parent 5ef15e2a67
commit 0d21ac12bf
6 files changed
+311 -216

No files matched your search

+27 -30
View File
@@ -1653,41 +1653,41 @@ It was needed due to the low adoption rate of the C11 equivalent layer.
Example: Example:
M_THREAD_T idx_p; m_thread_t idx_p;
M_THREAD_T idx_c; m_thread_t idx_c;
M_THREAD_CREATE (idx_p, conso_function, NULL); m_thread_create (idx_p, conso_function, NULL);
M_THREAD_CREATE (idx_c, prod_function, NULL); m_thread_create (idx_c, prod_function, NULL);
M_THREAD_JOIN(idx_p; m_thread_join (idx_p;
M_THREAD_JOIN(idx_c); m_thread_join (idx_c);
#### methods #### methods
The following methods are available: The following methods are available:
#### M\_MUTEX\_T #### m\_mutex\_t
A type representating a mutex. 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. 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. 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 free, it will wait indefinitely until it is.
If the variable is not initialized, the behavior is undefined. 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 locked, the behavior is undefined.
If the variable is not initialized, 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. 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. 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. 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, 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. has occured to other threads.
If the variable is not initialized, the behavior is undefined. 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, 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. to occur.
IF multiple threads wait for the same event, which thread to awoken IF multiple threads wait for the same event, which thread to awoken
is not specified. is not specified.
If any variable is not initialized, the behavior is undefined. If any variable is not initialized, the behavior is undefined.
#### M\_THREAD\_T #### m\_thread\_t
A type representating an id of a thread. 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'. Create a new thread and set the it of the thread to 'thread'.
The new thread run the code function(argument) with The new thread run the code function(argument) with
@@ -1750,13 +1750,10 @@ argument a 'void \*' and function taking a 'void \*' and returning
nothing. nothing.
If the initialization fails, the program aborts. 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. Wait for the thread 'thread' to exit.
##### M\_THREAD\_EXIT(arg)
Quit the current thread. 'arg' is currently unused.
###M-ALGO ###M-ALGO
+13 -9
View File
@@ -104,7 +104,7 @@ BUFFER_DEF(bigdata, shared_bigdata_t, MY_QUEUE_SIZE,
buffer_bigdata_t buf_t1tot2; buffer_bigdata_t buf_t1tot2;
buffer_bigdata_t buf_t1tot3; buffer_bigdata_t buf_t1tot3;
buffer_bigdata_t buf_t3tot4; buffer_bigdata_t buf_t3tot4;
M_THREAD_T t1, t2, t3, t4; m_thread_t t1, t2, t3, t4;
static void initbuf(void) static void initbuf(void)
{ {
@@ -122,6 +122,7 @@ static void clearbuf(void)
static void thread1 (void *arg) static void thread1 (void *arg)
{ {
(void) arg;
while (continue_threading_g) { while (continue_threading_g) {
shared_bigdata_t ptr; shared_bigdata_t ptr;
shared_bigdata_init_new (ptr); shared_bigdata_init_new (ptr);
@@ -133,6 +134,7 @@ static void thread1 (void *arg)
} }
static void thread2 (void *arg) static void thread2 (void *arg)
{ {
(void) arg;
while (continue_threading_g) { while (continue_threading_g) {
shared_bigdata_t ptr; shared_bigdata_t ptr;
shared_bigdata_init (ptr); shared_bigdata_init (ptr);
@@ -143,6 +145,7 @@ static void thread2 (void *arg)
} }
static void thread3 (void *arg) static void thread3 (void *arg)
{ {
(void) arg;
while (continue_threading_g) { while (continue_threading_g) {
shared_bigdata_t ptr; shared_bigdata_t ptr;
shared_bigdata_init (ptr); shared_bigdata_init (ptr);
@@ -154,6 +157,7 @@ static void thread3 (void *arg)
} }
static void thread4 (void *arg) static void thread4 (void *arg)
{ {
(void) arg;
while (continue_threading_g) { while (continue_threading_g) {
shared_bigdata_t ptr; shared_bigdata_t ptr;
shared_bigdata_init (ptr); shared_bigdata_init (ptr);
@@ -168,18 +172,18 @@ static void init(void)
{ {
initbuf(); initbuf();
continue_threading_g = true; continue_threading_g = true;
M_THREAD_CREATE(t1, thread1, NULL); m_thread_create(t1, thread1, NULL);
M_THREAD_CREATE(t2, thread2, NULL); m_thread_create(t2, thread2, NULL);
M_THREAD_CREATE(t3, thread3, NULL); m_thread_create(t3, thread3, NULL);
M_THREAD_CREATE(t4, thread4, NULL); m_thread_create(t4, thread4, NULL);
} }
static void clear(void) static void clear(void)
{ {
M_THREAD_JOIN(t1); m_thread_join(t1);
M_THREAD_JOIN(t2); m_thread_join(t2);
M_THREAD_JOIN(t3); m_thread_join(t3);
M_THREAD_JOIN(t4); m_thread_join(t4);
clearbuf(); clearbuf();
} }
+22 -26
View File
@@ -57,9 +57,9 @@ typedef enum {
#define BUFFERI_DEF2(name, type, m_size, policy, oplist) \ #define BUFFERI_DEF2(name, type, m_size, policy, oplist) \
typedef struct M_C3(buffer_, name, _s) { \ typedef struct M_C3(buffer_, name, _s) { \
M_MUTEX_T mutex; \ m_mutex_t mutex; \
M_COND_T there_is_data; \ m_cond_t there_is_data; \
M_COND_T there_is_room_for_data; \ m_cond_t there_is_room_for_data; \
BUFFERI_IF_CTE_SIZE(m_size)( ,size_t size;) \ BUFFERI_IF_CTE_SIZE(m_size)( ,size_t size;) \
size_t idx_prod, idx_cons, number; \ size_t idx_prod, idx_cons, number; \
type *data; \ type *data; \
@@ -72,9 +72,9 @@ static inline void \
BUFFERI_IF_CTE_SIZE(m_size)(assert(size == m_size), v->size = size); \ BUFFERI_IF_CTE_SIZE(m_size)(assert(size == m_size), v->size = size); \
v->idx_prod = v->idx_cons = v->number = 0; \ v->idx_prod = v->idx_cons = v->number = 0; \
if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \ if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \
M_MUTEX_INIT(v->mutex); \ m_mutex_init(v->mutex); \
M_COND_INIT(v->there_is_data); \ m_cond_init(v->there_is_data); \
M_COND_INIT(v->there_is_room_for_data); \ m_cond_init(v->there_is_room_for_data); \
} else \ } else \
assert(((policy)&BUFFER_UNBLOCKING) == BUFFER_UNBLOCKING); \ assert(((policy)&BUFFER_UNBLOCKING) == BUFFER_UNBLOCKING); \
v->data = M_MEMORY_REALLOC (type, NULL, BUFFERI_SIZE(m_size)); \ v->data = M_MEMORY_REALLOC (type, NULL, BUFFERI_SIZE(m_size)); \
@@ -109,17 +109,13 @@ static inline void \
static inline void \ static inline void \
M_C3(buffer_, name, _clear)(M_C3(buffer_, name,_t) v) \ M_C3(buffer_, name, _clear)(M_C3(buffer_, name,_t) v) \
{ \ { \
int rc; \
M_C3(bufferi_, name, _clear_obj)(v); \ M_C3(bufferi_, name, _clear_obj)(v); \
M_MEMORY_FREE (v->data); \ M_MEMORY_FREE (v->data); \
v->data = NULL; \ v->data = NULL; \
if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \ if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \
rc = M_MUTEX_CLEAR(v->mutex); \ m_mutex_clear(v->mutex); \
assert (rc == 0); \ m_cond_clear(v->there_is_data); \
rc = M_COND_CLEAR(v->there_is_data); \ m_cond_clear(v->there_is_room_for_data); \
assert (rc == 0); \
rc = M_COND_CLEAR(v->there_is_room_for_data); \
assert (rc == 0); \
} \ } \
} \ } \
\ \
@@ -128,12 +124,12 @@ static inline void \
{ \ { \
assert (v->number <= BUFFERI_SIZE(m_size)); \ assert (v->number <= BUFFERI_SIZE(m_size)); \
if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) \ 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) \ if (((policy)&BUFFER_PUSH_INIT_POP_MOVE) != 0) \
M_C3(bufferi_, name, _clear_obj)(v); \ M_C3(bufferi_, name, _clear_obj)(v); \
if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \ if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \
M_COND_SIGNAL(v->there_is_room_for_data); \ m_cond_signal(v->there_is_room_for_data); \
M_MUTEX_UNLOCK(v->mutex); \ 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) \ M_C3(buffer_, name, _push)(M_C3(buffer_, name,_t) v, type const data) \
{ \ { \
if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \ if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \
M_MUTEX_LOCK(v->mutex); \ m_mutex_lock(v->mutex); \
while (((policy)&BUFFER_PUSH_OVERWRITE) == 0 \ while (((policy)&BUFFER_PUSH_OVERWRITE) == 0 \
&& M_C3(buffer_, name, _full_p)(v)) { \ && M_C3(buffer_, name, _full_p)(v)) { \
if (((policy) & BUFFER_UNBLOCKING) == BUFFER_UNBLOCKING) { \ if (((policy) & BUFFER_UNBLOCKING) == BUFFER_UNBLOCKING) { \
M_MUTEX_UNLOCK(v->mutex); \ m_mutex_unlock(v->mutex); \
return false; \ 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 \ } else if (((policy)&BUFFER_PUSH_OVERWRITE) == 0 \
&& M_C3(buffer_, name, _full_p)(v)) \ && M_C3(buffer_, name, _full_p)(v)) \
@@ -195,8 +191,8 @@ static inline void \
v->number ++; \ v->number ++; \
\ \
if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \ if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \
M_COND_SIGNAL(v->there_is_data); \ m_cond_signal(v->there_is_data); \
M_MUTEX_UNLOCK(v->mutex); \ m_mutex_unlock(v->mutex); \
} \ } \
return true; \ return true; \
} \ } \
@@ -205,13 +201,13 @@ static inline void \
M_C3(buffer_, name, _pop)(type *data, M_C3(buffer_, name,_t) v) \ M_C3(buffer_, name, _pop)(type *data, M_C3(buffer_, name,_t) v) \
{ \ { \
if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \ 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)) { \ while (M_C3(buffer_, name, _empty_p)(v)) { \
if (((policy) & BUFFER_UNBLOCKING) == BUFFER_UNBLOCKING) { \ if (((policy) & BUFFER_UNBLOCKING) == BUFFER_UNBLOCKING) { \
M_MUTEX_UNLOCK(v->mutex); \ m_mutex_unlock(v->mutex); \
return false; \ 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)) \ } else if (M_C3(buffer_, name, _empty_p)(v)) \
return false; \ return false; \
@@ -234,8 +230,8 @@ static inline void \
v->number --; \ v->number --; \
\ \
if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \ if (((policy) & BUFFER_THREAD_UNSAFE) != BUFFER_THREAD_UNSAFE) { \
M_COND_SIGNAL(v->there_is_room_for_data); \ m_cond_signal(v->there_is_room_for_data); \
M_MUTEX_UNLOCK(v->mutex); \ m_mutex_unlock(v->mutex); \
} \ } \
return true; \ return true; \
} \ } \
+222 -120
View File
@@ -37,96 +37,161 @@
#include <threads.h> #include <threads.h>
#define M_MUTEX_T mtx_t typedef mtx_t m_mutex_t[1];
#define M_MUTEX_INIT(_mutex) do { \ typedef cnd_t m_cond_t[1];
int rc = mtx_init(&(_mutex), mtx_plain); \ typedef thrd_t m_thread_t[1];
M_ASSERT_INIT (rc == 0); \
} while (0) static inline void m_mutex_init(m_mutex_t m)
#define M_MUTEX_CLEAR(_mutex) mtx_destroy(&(_mutex)) {
#define M_MUTEX_LOCK(_mutex) mtx_lock(&(_mutex)) int rc = mtx_init(m, mtx_plain);
#define M_MUTEX_UNLOCK(_mutex) mtx_unlock(&(_mutex)) 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) #elif defined(WIN32) || defined(_WIN32)
/****************************** WIN32 version ******************************/ /****************************** WIN32 version ******************************/
#include <window.h> #include <window.h>
#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 typedef HANDLE m_mutex_t[1];
#define M_COND_INIT(_cond) do { \ typedef HANDLE m_cond_t[1];
(_cond) = = CreateEvent (NULL, FALSE, FALSE, NULL); \ typedef HANDLE m_thread_t[1];
M_ASSERT_INIT ((_cond) != NULL); \
} while (0) static inline void m_mutex_init(m_mutex_t m)
#define M_COND_CLEAR(_cond) CloseHandle(_cond) {
#define M_COND_SIGNAL(_cond) PulseEvent(_cond) *m = CreateMutex(NULL, FALSE, NULL);
#define M_COND_WAIT(_cond, _mutex) do { \ M_ASSERT_INIT(*m != NULL);
DWORD dwWaitResult = SignalObjectAndWait((_mutex),(_cond),INFINITE,FALSE); \ }
assert (dwWaitResult == WAIT_OBJECT_0); \
dwWaitResult = WaitForSingleObject((_mutex), INFINITE); \ static inline void m_mutex_clear(m_mutex_t m)
assert (dwWaitResult == WAIT_OBJECT_0); \ {
} while(0) 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 #else
@@ -134,40 +199,77 @@
#include <pthread.h> #include <pthread.h>
#define M_MUTEX_T pthread_mutex_t typedef pthread_mutex_t m_mutex_t[1];
#define M_MUTEX_INIT(_mutex) do { \ typedef pthread_cond_t m_cond_t[1];
int _rc = pthread_mutex_init(&(_mutex), NULL); \ typedef pthread_t m_thread_t[1];
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)
#define M_COND_T pthread_cond_t static inline void m_mutex_init(m_mutex_t m)
#define M_COND_INIT(_cond) do { \ {
int _rc = pthread_cond_init(&(_cond), NULL); \ int _rc = pthread_mutex_init(m, NULL);
M_ASSERT_INIT (_rc == 0); \ 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)
#define M_ONCEI_T pthread_once_t static inline void m_mutex_clear(m_mutex_t m)
#define M_ONCEI_INIT_VALUE PTHREAD_ONCE_INIT {
#define M_ONCEI_CALL(once,func) pthread_once(&(once),(func)) 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 #endif
@@ -182,22 +284,22 @@
*/ */
/* NOTE: Either using direct support by the OS (WIN32/PTHREAD) /* NOTE: Either using direct support by the OS (WIN32/PTHREAD)
or using C11's ONCE mechanism */ or using C11's ONCE mechanism */
#ifdef M_MUTEXI_LAZY_LOCK #ifdef M_MUTEXI_INIT_VALUE
# define M_LOCK_DECL(name) M_MUTEX_T name = M_MUTEXI_INIT_VALUE # define M_LOCK_DECL(name) m_mutex_t name = M_MUTEXI_INIT_VALUE
# define M_LOCK(name) \ # 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 #else
# define M_LOCK_DECL(name) \ # define M_LOCK_DECL(name) \
M_MUTEX_T name; \ m_mutex_t name; \
static void M_C(m_mutex_init_, name)(void) { \ 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) \ # define M_LOCKI_BY_ONCE(name) \
(M_ONCEI_CALL(M_C(m_once_, name), M_C(m_mutex_init_, name)), \ (m_oncei_call(M_C(m_once_, name), M_C(m_mutex_init_, name)), \
M_MUTEX_LOCK(name), (void) 0 ) m_mutex_lock(name), (void) 0 )
# define M_LOCK(name) \ # 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 #endif
#define M_LOCKI_DO(name, cont, lock, unlock) \ #define M_LOCKI_DO(name, cont, lock, unlock) \
+22 -25
View File
@@ -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; buffer_uint_t g_buff;
static void *conso(void *arg) static void conso(void *arg)
{ {
unsigned int j; unsigned int j;
assert (arg == NULL); assert (arg == NULL);
@@ -47,31 +47,29 @@ static void *conso(void *arg)
buffer_uint_pop(&j, g_buff); buffer_uint_pop(&j, g_buff);
assert (j < 1000); assert (j < 1000);
} }
return NULL;
} }
static void *prod(void *arg) static void prod(void *arg)
{ {
assert (arg == NULL); assert (arg == NULL);
for(unsigned int i = 0; i < 1000;i++) for(unsigned int i = 0; i < 1000;i++)
buffer_uint_push(g_buff, i); buffer_uint_push(g_buff, i);
return NULL;
} }
static void test_global(void) static void test_global(void)
{ {
M_THREAD_T idx_p[100]; m_thread_t idx_p[100];
M_THREAD_T idx_c[100]; m_thread_t idx_c[100];
buffer_uint_init(g_buff, 10); buffer_uint_init(g_buff, 10);
for(int i = 0; i < 100; i++) { for(int i = 0; i < 100; i++) {
M_THREAD_CREATE (idx_p[i], conso, NULL); m_thread_create (idx_p[i], conso, NULL);
M_THREAD_CREATE (idx_c[i], prod, NULL); m_thread_create (idx_c[i], prod, NULL);
} }
for(int i = 0; i < 100;i++) { for(int i = 0; i < 100;i++) {
M_THREAD_JOIN(idx_p[i]); m_thread_join(idx_p[i]);
M_THREAD_JOIN(idx_c[i]); m_thread_join(idx_c[i]);
} }
buffer_uint_clear(g_buff); 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 comm1;
static buffer_itest_t comm2; static buffer_itest_t comm2;
static void *test_conso1(void *arg) static void test_conso1(void *arg)
{ {
test_t *p; test_t *p;
assert (arg == NULL); assert (arg == NULL);
@@ -188,9 +186,9 @@ static void *test_conso1(void *arg)
assert (p->buffer[j] == (char) ((j * j * 17) + j * 42 + 1)); assert (p->buffer[j] == (char) ((j * j * 17) + j * 42 + 1));
ishared_itest_clear(p); ishared_itest_clear(p);
} }
return NULL;
} }
static void *test_conso2(void *arg)
static void test_conso2(void *arg)
{ {
test_t *p; test_t *p;
assert (arg == NULL); assert (arg == NULL);
@@ -200,9 +198,9 @@ static void *test_conso2(void *arg)
assert (p->buffer[j] == (char) ((j * j * 17) + j * 42 + 1)); assert (p->buffer[j] == (char) ((j * j * 17) + j * 42 + 1));
ishared_itest_clear(p); ishared_itest_clear(p);
} }
return NULL;
} }
static void *test_prod(void *arg)
static void test_prod(void *arg)
{ {
assert (arg == NULL); assert (arg == NULL);
for(unsigned int i = 0; i < 10;i++) { for(unsigned int i = 0; i < 10;i++) {
@@ -213,27 +211,26 @@ static void *test_prod(void *arg)
buffer_itest_push(comm2, p); buffer_itest_push(comm2, p);
ishared_itest_clear(p); ishared_itest_clear(p);
} }
return NULL;
} }
static void test_global_ishared(void) static void test_global_ishared(void)
{ {
M_THREAD_T idx_p[100]; m_thread_t idx_p[100];
M_THREAD_T idx_c1[100]; m_thread_t idx_c1[100];
M_THREAD_T idx_c2[100]; m_thread_t idx_c2[100];
buffer_itest_init(comm1, 16); buffer_itest_init(comm1, 16);
buffer_itest_init(comm2, 16); buffer_itest_init(comm2, 16);
for(int i = 0; i < 100; i++) { for(int i = 0; i < 100; i++) {
M_THREAD_CREATE (idx_c1[i], test_conso1, NULL); m_thread_create (idx_c1[i], test_conso1, NULL);
M_THREAD_CREATE (idx_c2[i], test_conso2, NULL); m_thread_create (idx_c2[i], test_conso2, NULL);
M_THREAD_CREATE (idx_p[i], test_prod, NULL); m_thread_create (idx_p[i], test_prod, NULL);
} }
for(int i = 0; i < 100;i++) { for(int i = 0; i < 100;i++) {
M_THREAD_JOIN(idx_p[i]); m_thread_join(idx_p[i]);
M_THREAD_JOIN(idx_c1[i]); m_thread_join(idx_c1[i]);
M_THREAD_JOIN(idx_c2[i]); m_thread_join(idx_c2[i]);
} }
buffer_itest_clear(comm1); buffer_itest_clear(comm1);
+5 -6
View File
@@ -27,26 +27,25 @@
M_LOCK_DECL(global_lock); M_LOCK_DECL(global_lock);
unsigned long long n = 0; unsigned long long n = 0;
static void *f(void *arg) static void f(void *arg)
{ {
(void)arg; // Unused (void)arg; // Unused
// Global lock to perform atomic addition. // Global lock to perform atomic addition.
M_LOCK(global_lock) { M_LOCK(global_lock) {
n += 1; n += 1;
} }
return NULL; }
}
static void test_global(void) static void test_global(void)
{ {
M_THREAD_T idx_p[100]; m_thread_t idx_p[100];
n = 0; n = 0;
for(int i = 0; i < 100; i++) { 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++) { for(int i = 0; i < 100;i++) {
M_THREAD_JOIN(idx_p[i]); m_thread_join(idx_p[i]);
} }
assert (n == 100); assert (n == 100);
} }