[PATCH/RFC] mingw: implement PTHREAD_MUTEX_INITIALIZER
From: Erik Faye-Lund <hidden>
Date: 2016-06-15 22:52:19
Subsystem:
the rest · Maintainer:
Linus Torvalds
Signed-off-by: Erik Faye-Lund <redacted> --- Every now and then, someone suggest using PTHREAD_MUTEX_INITIALIZER, but some times gets show down by our lack of support on Windows. I'm working on something myself that could benefit from this, so I gave it a stab. The result looks promising to me, but I haven't really debugged it yet. But is there a fundamental reason why we haven't done something like this before? :) compat/win32/pthread.c | 28 +++++++++++++++++++++++++--- compat/win32/pthread.h | 18 ++++++++++++------ 2 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/compat/win32/pthread.c b/compat/win32/pthread.c
index 010e875..14f91d5 100644
--- a/compat/win32/pthread.c
+++ b/compat/win32/pthread.c@@ -57,6 +57,28 @@ pthread_t pthread_self(void) return t; } +int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) +{ + InitializeCriticalSection(&mutex->cs); + mutex->autoinit = 0; + return 0; +} + +int pthread_mutex_lock(pthread_mutex_t *mutex) +{ + if (mutex->autoinit) { + if (InterlockedCompareExchange(&mutex->autoinit, -1, 1) != -1) { + pthread_mutex_init(mutex, NULL); + mutex->autoinit = 0; + } else + while (mutex->autoinit != 0) + ; /* wait for other thread */ + } + + EnterCriticalSection(&mutex->cs); + return 0; +} + int pthread_cond_init(pthread_cond_t *cond, const void *unused) { cond->waiters = 0;
@@ -85,7 +107,7 @@ int pthread_cond_destroy(pthread_cond_t *cond) return 0; } -int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex) +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { int last_waiter;
@@ -99,7 +121,7 @@ int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex) * waiters count above, so there's no problem with * leaving mutex unlocked before we wait on semaphore. */ - LeaveCriticalSection(mutex); + LeaveCriticalSection(&mutex->cs); /* let's wait - ignore return value */ WaitForSingleObject(cond->sema, INFINITE);
@@ -133,7 +155,7 @@ int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex) */ } /* lock external mutex again */ - EnterCriticalSection(mutex); + EnterCriticalSection(&mutex->cs); return 0; }
diff --git a/compat/win32/pthread.h b/compat/win32/pthread.h
index 2e20548..647e6d4 100644
--- a/compat/win32/pthread.h
+++ b/compat/win32/pthread.h@@ -16,14 +16,20 @@ /* * Defines that adapt Windows API threads to pthreads API */ -#define pthread_mutex_t CRITICAL_SECTION +typedef struct { + CRITICAL_SECTION cs; + LONG volatile autoinit; +} pthread_mutex_t; -#define pthread_mutex_init(a,b) (InitializeCriticalSection((a)), 0) -#define pthread_mutex_destroy(a) DeleteCriticalSection((a)) -#define pthread_mutex_lock EnterCriticalSection -#define pthread_mutex_unlock LeaveCriticalSection +#define PTHREAD_MUTEX_INITIALIZER { { 0 }, 1 } typedef int pthread_mutexattr_t; + +int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *); +#define pthread_mutex_destroy(a) DeleteCriticalSection(&(a)->cs) +int pthread_mutex_lock(pthread_mutex_t *); +#define pthread_mutex_unlock(a) LeaveCriticalSection(&(a)->cs) + #define pthread_mutexattr_init(a) (*(a) = 0) #define pthread_mutexattr_destroy(a) do {} while (0) #define pthread_mutexattr_settype(a, t) 0
@@ -47,7 +53,7 @@ typedef struct { extern int pthread_cond_init(pthread_cond_t *cond, const void *unused); extern int pthread_cond_destroy(pthread_cond_t *cond); -extern int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex); +extern int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); extern int pthread_cond_signal(pthread_cond_t *cond); extern int pthread_cond_broadcast(pthread_cond_t *cond);
--
1.7.7.msysgit.1.1.g7b316