diff options
Diffstat (limited to 'gcc/gthr-win32.h')
-rw-r--r-- | gcc/gthr-win32.h | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/gcc/gthr-win32.h b/gcc/gthr-win32.h index b761804..3e1aac7 100644 --- a/gcc/gthr-win32.h +++ b/gcc/gthr-win32.h @@ -343,9 +343,18 @@ typedef struct { void *sema; } __gthread_mutex_t; +typedef struct { + long counter; + long depth; + DWORD owner; + void *sema; +} __gthread_recursive_mutex_t; + #define __GTHREAD_ONCE_INIT {0, -1} #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function #define __GTHREAD_MUTEX_INIT_DEFAULT {-1, 0} +#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_mutex_init_function +#define __GTHREAD_RECURSIVE_MUTEX_INIT_DEFAULT {-1, 0} #if __MINGW32_MAJOR_VERSION >= 1 || \ (__MINGW32_MAJOR_VERSION == 0 && __MINGW32_MINOR_VERSION > 2) @@ -472,6 +481,33 @@ __gthread_mutex_unlock (__gthread_mutex_t *mutex) return 0; } +static inline int +__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex) +{ + if (__gthread_active_p ()) + return __gthr_win32_recursive_mutex_lock (mutex); + else + return 0; +} + +static inline int +__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex) +{ + if (__gthread_active_p ()) + return __gthr_win32_recursive_mutex_trylock (mutex); + else + return 0; +} + +static inline int +__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex) +{ + if (__gthread_active_p ()) + return __gthr_win32_recursive_mutex_unlock (mutex); + else + return 0; +} + #else /* ! __GTHREAD_HIDE_WIN32API */ #include <windows.h> @@ -610,6 +646,83 @@ __gthread_mutex_unlock (__gthread_mutex_t *mutex) return 0; } +static inline void +__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex) +{ + mutex->counter = -1; + mutex->depth = 0; + mutex->owner = 0; + mutex->sema = CreateSemaphore (NULL, 0, 65535, NULL); +} + +static inline int +__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex) +{ + if (__gthread_active_p ()) + { + DWORD me = GetCurrentThreadId(); + if (InterlockedIncrement (&mutex->counter) == 0) + { + mutex->depth = 1; + mutex->owner = me; + } + else if (mutex->owner == me) + { + InterlockedDecrement (&mx->lock_idx); + ++(mutex->depth); + } + else if (WaitForSingleObject (mutex->sema, INFINITE) == WAIT_OBJECT_0) + { + mutex->depth = 1; + mutex->owner = me; + } + else + { + /* WaitForSingleObject returns WAIT_FAILED, and we can only do + some best-effort cleanup here. */ + InterlockedDecrement (&mutex->counter); + return 1; + } + } + return 0; +} + +static inline int +__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex) +{ + if (__gthread_active_p ()) + { + DWORD me = GetCurrentThreadId(); + if (__GTHR_W32_InterlockedCompareExchange (&mutex->counter, 0, -1) < 0) + { + mutex->depth = 1; + mutex->owner = me; + } + else if (mutex->owner == me) + ++(mutex->depth); + else + return 1; + } + return 0; +} + +static inline int +__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex) +{ + if (__gthread_active_p ()) + { + --(mutex->depth); + if (mutex->depth == 0) + { + mutex->owner = 0; + + if (InterlockedDecrement (&mutex->counter) >= 0) + return ReleaseSemaphore (mutex->sema, 1, NULL) ? 0 : 1; + } + } + return 0; +} + #endif /* __GTHREAD_HIDE_WIN32API */ #ifdef __cplusplus |