winpthreads: mutex.c: update static function `mutex_impl` This function now returns zero on success and an error code on failure. This allows to propagate error code from `pthread_mutex_init` to the caller. Signed-off-by: Kirill Makurin <maiddaisuki@outlook.com> Signed-off-by: LIU Hao <lh_mouse@126.com>
diff --git a/mingw-w64-libraries/winpthreads/src/mutex.c b/mingw-w64-libraries/winpthreads/src/mutex.c index 5859b63..6db9d5a 100644 --- a/mingw-w64-libraries/winpthreads/src/mutex.c +++ b/mingw-w64-libraries/winpthreads/src/mutex.c
@@ -117,27 +117,35 @@ */ #define STATIC_MUTEX_INITIALIZER(m) ((uintptr_t)(m) >= (uintptr_t)-3) -/* Return the implementation part of a mutex, creating it if necessary. - Return NULL on out-of-memory error. */ -static WINPTHREADS_INLINE mutex_impl_t *mutex_impl(pthread_mutex_t *m) +/** + * Obtain pointer to `mutex_impl_t` structure pointed to by `m`. + * + * If `m` points to statically initialzied `pthread_mutex_t` object, + * allocate `mutex_impl_t` structure and store its address in `*m`. + * + * On success, stores pointer to `mutex_impl_t` structure in `*mi`. + * + * Returns zero on success and an error-code on failure. + */ +static WINPTHREADS_INLINE int mutex_impl(pthread_mutex_t *m, mutex_impl_t **mi) { - mutex_impl_t *mi = (mutex_impl_t *)*m; + *mi = (mutex_impl_t *)*m; /** * We need to avoid race condition when more than one thread attempts to use * same statically initialized `pthread_mutex_t` object at the same time. * - * Store newly initialized mutex in local variable `mi`, and only then store - * it in `m`. + * Store newly initialized mutex in `mi`, which is a local variable supplied + * by the caller, and only then store it in `m`. * * If some other thread was faster then us, destroy newly created mutex * and use mutex pointed to by `m`. */ - if (unlikely (STATIC_MUTEX_INITIALIZER (mi))) { + if (unlikely (STATIC_MUTEX_INITIALIZER (*mi))) { pthread_mutexattr_t mutexAttr; int mutexType; - mutex_impl_t *volatile initializer = mi; + mutex_impl_t *volatile initializer = *mi; switch ((pthread_mutex_t)initializer) { case PTHREAD_NORMAL_MUTEX_INITIALIZER: @@ -156,38 +164,47 @@ int error_code = pthread_mutexattr_init (&mutexAttr); if (error_code) { - return NULL; + return error_code; } pthread_mutexattr_settype (&mutexAttr, mutexType); - error_code = pthread_mutex_init ((pthread_mutex_t *)&mi, &mutexAttr); + error_code = pthread_mutex_init ((pthread_mutex_t *)mi, &mutexAttr); pthread_mutexattr_destroy (&mutexAttr); if (error_code) { - return NULL; + return error_code; } - void *mutex = InterlockedCompareExchangePointer ((void **)m, mi, initializer); + void *mutex = InterlockedCompareExchangePointer ((void **)m, *mi, initializer); /** * Some other thread was faster than us. */ if (unlikely (mutex != initializer)) { - pthread_mutex_destroy ((pthread_mutex_t *)&mi); - mi = mutex; + pthread_mutex_destroy ((pthread_mutex_t *)mi); + *mi = mutex; } } - return mi; + if (unlikely (*mi == NULL)) { + return EINVAL; + } + + return 0; } /* Lock a mutex. Give up after 'timeout' ms (with ETIMEDOUT), or never if timeout=INFINITE. */ static WINPTHREADS_INLINE int pthread_mutex_lock_intern(pthread_mutex_t *m, DWORD timeout) { - mutex_impl_t *mi = mutex_impl(m); - if (mi == NULL) - return ENOMEM; + mutex_impl_t *mi = NULL; + + int error_code = mutex_impl (m, &mi); + + if (error_code) { + return error_code; + } + mutex_state_t old_state = InterlockedExchange((long *)&mi->state, Locked); if (unlikely(old_state != Unlocked)) { /* The mutex is already locked. */ @@ -271,11 +288,13 @@ int pthread_mutex_unlock(pthread_mutex_t *m) { - /* Here m might an initialiser of an error-checking or recursive mutex, in - which case the behaviour is well-defined, so we can't skip this check. */ - mutex_impl_t *mi = mutex_impl(m); - if (mi == NULL) - return ENOMEM; + mutex_impl_t *mi = NULL; + + int error_code = mutex_impl (m, &mi); + + if (error_code) { + return error_code; + } if (unlikely(mi->type != Normal)) { if (mi->state == Unlocked) @@ -297,9 +316,13 @@ int pthread_mutex_trylock(pthread_mutex_t *m) { - mutex_impl_t *mi = mutex_impl(m); - if (mi == NULL) - return ENOMEM; + mutex_impl_t *mi = NULL; + + int error_code = mutex_impl (m, &mi); + + if (error_code) { + return error_code; + } if (InterlockedCompareExchange((long *)&mi->state, Locked, Unlocked) == Unlocked) { if (mi->type != Normal)