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:
1 parent
5ef15e2a67
commit
0d21ac12bf
6 files changed
+311
-216
No files matched your search
@@ -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
@@ -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
@@ -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; \
|
||||
} \
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user