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:
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
+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_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();
}
+22 -26
View File
@@ -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; \
} \
+222 -120
View File
@@ -37,96 +37,161 @@
#include <threads.h>
#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 <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
#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 <pthread.h>
#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) \
+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;
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);
+5 -6
View File
@@ -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);
}