winpthreads: tests: update pthread_mutex/mutex6*.c Signed-off-by: Kirill Makurin <maiddaisuki@outlook.com> Signed-off-by: LIU Hao <lh_mouse@126.com>
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6.c index 2b2aa29..be23e4b 100644 --- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6.c +++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6.c
@@ -1,14 +1,10 @@ /* - * mutex6.c - * - * - * -------------------------------------------------------------------------- - * * Pthreads-win32 - POSIX Threads Library for Win32 * Copyright(C) 1998 John E. Bossom * Copyright(C) 1999,2005 Pthreads-win32 contributors + * Copyright(C) 2026 mingw-w64 project * - * Contact Email: rpj@callisto.canberra.edu.au + * Contact Email: mingw-w64-public@lists.sourceforge.net * * The current list of contributors is contained * in the file CONTRIBUTORS included with the source @@ -30,64 +26,80 @@ * License along with this library in the file COPYING.LIB; * if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * -------------------------------------------------------------------------- - * - * Test the default (type not set) mutex type. - * Should be the same as PTHREAD_MUTEX_NORMAL. - * Thread locks mutex twice (recursive lock). - * Locking thread should deadlock on second attempt. - * - * Depends on API functions: - * pthread_mutex_lock() - * pthread_mutex_trylock() - * pthread_mutex_unlock() */ #include "test.h" -static volatile int lockCount = 0; +/** + * Test Summary: + * + * Main thread M creates default-type mutex L. + * + * Thread A locks L. + * + * Thread A attempts to lock L again; this must result in a dead lock. + * + * Thread M unlocks and destroys L. + */ -static pthread_mutex_t mutex; +static LONG IsThreadABlocked = FALSE; -void *locker(void *arg) +static void *ThreadA(void *arg) { - assert(pthread_mutex_lock(&mutex) == 0); - InterlockedIncrement((long *)&lockCount); + pthread_mutex_t *mutex = arg; - /* Should wait here (deadlocked) */ - assert(pthread_mutex_lock(&mutex) == 0); - InterlockedIncrement((long *)&lockCount); - assert(pthread_mutex_unlock(&mutex) == 0); + assert(pthread_mutex_lock(mutex) == 0); + /** + * Signal thread M that thread A locked L. + */ + InterlockedExchange(&IsThreadABlocked, TRUE); + /** + * Attempt to recursively lock NORMAL mutex must result in a dead lock. + * Wait for main thread to unlock... + */ + assert(pthread_mutex_lock(mutex) == 0); + /** + * Signal thread M that thread A was unblocked. + */ + InterlockedExchange(&IsThreadABlocked, FALSE); + assert(pthread_mutex_unlock(mutex) == 0); - return 0; + return arg; } int main(void) { - pthread_t t; + pthread_mutex_t mutex; + pthread_t thread; + void *result; assert(pthread_mutex_init(&mutex, NULL) == 0); - - assert(pthread_create(&t, NULL, locker, NULL) == 0); - - Sleep(1000); - - printf("lockCount = %d\n", lockCount); - assert(lockCount == 1); - - /* - * Should succeed even though we don't own the lock - * because FAST mutexes don't check ownership. + assert(pthread_create(&thread, NULL, ThreadA, &mutex) == 0); + /** + * Wait until thread A locks L. */ - assert(pthread_mutex_unlock(&mutex) == 0); + while (!IsThreadABlocked) { + YieldProcessor(); + } + Sleep(10); + /** + * Thread A must be deadlocked. + */ + assert(IsThreadABlocked); + /** + * POSIX states that calling `pthread_mutex_unlock` on NORMAL mutex that is + * not owned by the calling thread is undefined behavior. + * + * Our implementation for NORMAL mutexes does not check ownership at all, + * so call to `pthread_mutex_unlock` on a valid NORMAL mutex always succeeds. + */ + do { + assert(pthread_mutex_unlock(&mutex) == 0); + YieldProcessor(); + } while (IsThreadABlocked); + assert(pthread_join (thread, &result) == 0); + assert(result == &mutex); + assert(pthread_mutex_destroy(&mutex) == 0); - Sleep (1000); - - assert(lockCount == 2); - - exit(0); - - /* Never reached */ return 0; }
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6e.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6e.c index f786781..4d97a50 100644 --- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6e.c +++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6e.c
@@ -1,14 +1,10 @@ /* - * mutex6e.c - * - * - * -------------------------------------------------------------------------- - * * Pthreads-win32 - POSIX Threads Library for Win32 * Copyright(C) 1998 John E. Bossom * Copyright(C) 1999,2005 Pthreads-win32 contributors + * Copyright(C) 2026 mingw-w64 project * - * Contact Email: rpj@callisto.canberra.edu.au + * Contact Email: mingw-w64-public@lists.sourceforge.net * * The current list of contributors is contained * in the file CONTRIBUTORS included with the source @@ -30,71 +26,58 @@ * License along with this library in the file COPYING.LIB; * if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * -------------------------------------------------------------------------- - * - * Tests PTHREAD_MUTEX_ERRORCHECK mutex type. - * Thread locks mutex twice (recursive lock). - * This should fail with an EDEADLK error. - * The second unlock attempt should fail with an EPERM error. - * - * Depends on API functions: - * pthread_create() - * pthread_join() - * pthread_mutexattr_init() - * pthread_mutexattr_destroy() - * pthread_mutexattr_settype() - * pthread_mutexattr_gettype() - * pthread_mutex_init() - * pthread_mutex_destroy() - * pthread_mutex_lock() - * pthread_mutex_unlock() */ #include "test.h" -static int lockCount = 0; +/** + * Test Summary: + * + * Main thread M creates mutex L with type `PTHREAD_MUTEX_ERRORCHECK`. + * + * Thread A locks L. + * + * Thread A attempts to lock L again; the call to `pthread_mutex_lock` must + * fail with EDEADLK. + * + * Thread A unlocks L. + * + * Thread A attempts to unlock L again; the call to `pthread_mutex_unlock` must + * fail with EPERM. + * + * Thread M destroys L. + */ -static pthread_mutex_t mutex; -static pthread_mutexattr_t mxAttr; - -void *locker(void *arg) +static void *ThreadA(void *arg) { - assert(pthread_mutex_lock(&mutex) == 0); - lockCount++; - assert(pthread_mutex_lock(&mutex) == EDEADLK); - lockCount++; - assert(pthread_mutex_unlock(&mutex) == 0); - assert(pthread_mutex_unlock(&mutex) == EPERM); + pthread_mutex_t *mutex = arg; - return (void *) 555; + assert(pthread_mutex_lock(mutex) == 0); + assert(pthread_mutex_lock(mutex) == EDEADLK); + assert(pthread_mutex_unlock(mutex) == 0); + assert(pthread_mutex_unlock(mutex) == EPERM); + + return arg; } int main(void) { - pthread_t t; - intptr_t result = 0; - int mxType = -1; + pthread_mutexattr_t mutexAttr; + pthread_mutex_t mutex; + pthread_t thread; + int mutexType; + void *result; - assert(pthread_mutexattr_init(&mxAttr) == 0); - assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_ERRORCHECK) == 0); - assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0); - assert(mxType == PTHREAD_MUTEX_ERRORCHECK); - - assert(pthread_mutex_init(&mutex, &mxAttr) == 0); - - assert(pthread_create(&t, NULL, locker, NULL) == 0); - - assert(pthread_join(t, (void **) &result) == 0); - assert(result == 555); - - assert(lockCount == 2); - + assert(pthread_mutexattr_init(&mutexAttr) == 0); + assert(pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_ERRORCHECK) == 0); + assert(pthread_mutexattr_gettype(&mutexAttr, &mutexType) == 0); + assert(mutexType == PTHREAD_MUTEX_ERRORCHECK); + assert(pthread_mutex_init(&mutex, &mutexAttr) == 0); + assert(pthread_create(&thread, NULL, ThreadA, &mutex) == 0); + assert(pthread_join (thread, &result) == 0); + assert(result == &mutex); assert(pthread_mutex_destroy(&mutex) == 0); - assert(pthread_mutexattr_destroy(&mxAttr) == 0); + assert(pthread_mutexattr_destroy(&mutexAttr) == 0); - exit(0); - - /* Never reached */ return 0; }
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6es.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6es.c index 59718e6..b0c70af 100644 --- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6es.c +++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6es.c
@@ -1,14 +1,10 @@ /* - * mutex6es.c - * - * - * -------------------------------------------------------------------------- - * * Pthreads-win32 - POSIX Threads Library for Win32 * Copyright(C) 1998 John E. Bossom * Copyright(C) 1999,2005 Pthreads-win32 contributors + * Copyright(C) 2026 mingw-w64 project * - * Contact Email: rpj@callisto.canberra.edu.au + * Contact Email: mingw-w64-public@lists.sourceforge.net * * The current list of contributors is contained * in the file CONTRIBUTORS included with the source @@ -30,61 +26,51 @@ * License along with this library in the file COPYING.LIB; * if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * -------------------------------------------------------------------------- - * - * Tests PTHREAD_MUTEX_ERRORCHECK static mutex type. - * Thread locks mutex twice (recursive lock). - * This should fail with an EDEADLK error. - * The second unlock attempt should fail with an EPERM error. - * - * Depends on API functions: - * pthread_create() - * pthread_join() - * pthread_mutexattr_init() - * pthread_mutexattr_destroy() - * pthread_mutexattr_settype() - * pthread_mutexattr_gettype() - * pthread_mutex_init() - * pthread_mutex_destroy() - * pthread_mutex_lock() - * pthread_mutex_unlock() */ #include "test.h" -static int lockCount = 0; +/** + * Test Summary: + * + * Main thread M creates (statically initialized) mutex L with type + * `PTHREAD_MUTEX_ERRORCHECK`. + * + * Thread A locks L. + * + * Thread A attempts to lock L again; the call to `pthread_mutex_lock` must + * fail with EDEADLK. + * + * Thread A unlocks L. + * + * Thread A attempts to unlock L again; the call to `pthread_mutex_unlock` must + * fail with EPERM. + * + * Thread M destroys L. + */ -static pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER; - -void *locker(void *arg) +static void *ThreadA(void *arg) { - assert(pthread_mutex_lock(&mutex) == 0); - lockCount++; - assert(pthread_mutex_lock(&mutex) == EDEADLK); - lockCount++; - assert(pthread_mutex_unlock(&mutex) == 0); - assert(pthread_mutex_unlock(&mutex) == EPERM); + pthread_mutex_t *mutex = arg; - return (void *) 555; + assert(pthread_mutex_lock(mutex) == 0); + assert(pthread_mutex_lock(mutex) == EDEADLK); + assert(pthread_mutex_unlock(mutex) == 0); + assert(pthread_mutex_unlock(mutex) == EPERM); + + return arg; } int main(void) { - pthread_t t; - intptr_t result = 0; + pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER; + pthread_t thread; + void *result; - assert(mutex == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER); - - assert(pthread_create(&t, NULL, locker, NULL) == 0); - assert(pthread_join(t, (void **) &result) == 0); - assert(result == 555); - assert(lockCount == 2); - + assert(pthread_create(&thread, NULL, ThreadA, &mutex) == 0); + assert(pthread_join (thread, &result) == 0); + assert(result == &mutex); assert(pthread_mutex_destroy(&mutex) == 0); - exit(0); - - /* Never reached */ return 0; }
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6n.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6n.c index 267bcb8..52b2007 100644 --- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6n.c +++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6n.c
@@ -1,14 +1,10 @@ /* - * mutex6n.c - * - * - * -------------------------------------------------------------------------- - * * Pthreads-win32 - POSIX Threads Library for Win32 * Copyright(C) 1998 John E. Bossom * Copyright(C) 1999,2005 Pthreads-win32 contributors + * Copyright(C) 2026 mingw-w64 project * - * Contact Email: rpj@callisto.canberra.edu.au + * Contact Email: mingw-w64-public@lists.sourceforge.net * * The current list of contributors is contained * in the file CONTRIBUTORS included with the source @@ -30,73 +26,87 @@ * License along with this library in the file COPYING.LIB; * if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * -------------------------------------------------------------------------- - * - * Tests PTHREAD_MUTEX_NORMAL mutex type. - * Thread locks mutex twice (recursive lock). - * The thread should deadlock. - * - * Depends on API functions: - * pthread_create() - * pthread_mutexattr_init() - * pthread_mutexattr_settype() - * pthread_mutexattr_gettype() - * pthread_mutex_init() - * pthread_mutex_lock() - * pthread_mutex_unlock() */ #include "test.h" -static int lockCount = 0; +/** + * Test Summary: + * + * Main thread M creates mutex L with type `PTHREAD_MUTEX_NORMAL`. + * + * Thread A locks L. + * + * Thread A attempts to lock L again; this must result in a dead lock. + * + * Thread M unlocks and destroys L. + */ -static pthread_mutex_t mutex; -static pthread_mutexattr_t mxAttr; +static LONG IsThreadABlocked = FALSE; -void *locker(void *arg) +static void *ThreadA(void *arg) { - assert(pthread_mutex_lock(&mutex) == 0); - lockCount++; + pthread_mutex_t *mutex = arg; - /* Should wait here (deadlocked) */ - assert(pthread_mutex_lock(&mutex) == 0); - lockCount++; - assert(pthread_mutex_unlock(&mutex) == 0); + assert(pthread_mutex_lock(mutex) == 0); + /** + * Signal thread M that thread A locked L. + */ + InterlockedExchange(&IsThreadABlocked, TRUE); + /** + * Attempt to recursively lock NORMAL mutex must result in a dead lock. + * Wait for main thread to unlock... + */ + assert(pthread_mutex_lock(mutex) == 0); + /** + * Signal thread M that thread A was unblocked. + */ + InterlockedExchange(&IsThreadABlocked, FALSE); + assert(pthread_mutex_unlock(mutex) == 0); - return (void *) 555; + return arg; } int main(void) { - pthread_t t; - int mxType = -1; + pthread_mutexattr_t mutexAttr; + pthread_mutex_t mutex; + pthread_t thread; + int mutexType; + void *result; - assert(pthread_mutexattr_init(&mxAttr) == 0); - assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_NORMAL) == 0); - assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0); - assert(mxType == PTHREAD_MUTEX_NORMAL); - - assert(pthread_mutex_init(&mutex, &mxAttr) == 0); - - assert(pthread_create(&t, NULL, locker, NULL) == 0); - - Sleep(1000); - - assert(lockCount == 1); - - /* - * Should succeed even though we don't own the lock - * because FAST mutexes don't check ownership. + assert(pthread_mutexattr_init(&mutexAttr) == 0); + assert(pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_NORMAL) == 0); + assert(pthread_mutexattr_gettype(&mutexAttr, &mutexType) == 0); + assert(mutexType == PTHREAD_MUTEX_NORMAL); + assert(pthread_mutex_init(&mutex, &mutexAttr) == 0); + assert(pthread_create(&thread, NULL, ThreadA, &mutex) == 0); + /** + * Wait until thread A locks L. */ - assert(pthread_mutex_unlock(&mutex) == 0); + while (!IsThreadABlocked) { + YieldProcessor(); + } + Sleep(10); + /** + * Thread A must be deadlocked. + */ + assert(IsThreadABlocked); + /** + * POSIX states that calling `pthread_mutex_unlock` on NORMAL mutex that is + * not owned by the calling thread is undefined behavior. + * + * Our implementation for NORMAL mutexes does not check ownership at all, + * so call to `pthread_mutex_unlock` on a valid NORMAL mutex always succeeds. + */ + do { + assert(pthread_mutex_unlock(&mutex) == 0); + YieldProcessor(); + } while (IsThreadABlocked); + assert(pthread_join (thread, &result) == 0); + assert(result == &mutex); + assert(pthread_mutex_destroy(&mutex) == 0); + assert(pthread_mutexattr_destroy(&mutexAttr) == 0); - Sleep (1000); - - assert(lockCount == 2); - - exit(0); - - /* Never reached */ return 0; }
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6r.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6r.c index cb96016..6a5ddb3 100644 --- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6r.c +++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6r.c
@@ -1,14 +1,10 @@ /* - * mutex6r.c - * - * - * -------------------------------------------------------------------------- - * * Pthreads-win32 - POSIX Threads Library for Win32 * Copyright(C) 1998 John E. Bossom * Copyright(C) 1999,2005 Pthreads-win32 contributors + * Copyright(C) 2026 mingw-w64 project * - * Contact Email: rpj@callisto.canberra.edu.au + * Contact Email: mingw-w64-public@lists.sourceforge.net * * The current list of contributors is contained * in the file CONTRIBUTORS included with the source @@ -30,68 +26,58 @@ * License along with this library in the file COPYING.LIB; * if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * -------------------------------------------------------------------------- - * - * Tests PTHREAD_MUTEX_RECURSIVE mutex type. - * Thread locks mutex twice (recursive lock). - * Both locks and unlocks should succeed. - * - * Depends on API functions: - * pthread_create() - * pthread_join() - * pthread_mutexattr_init() - * pthread_mutexattr_destroy() - * pthread_mutexattr_settype() - * pthread_mutexattr_gettype() - * pthread_mutex_init() - * pthread_mutex_destroy() - * pthread_mutex_lock() - * pthread_mutex_unlock() */ #include "test.h" -static int lockCount = 0; +/** + * Test Summary: + * + * Main thread M creates mutex L with type `PTHREAD_MUTEX_RECURSIVE`. + * + * Thread A locks L. + * + * Thread A attempts to lock L again; the call to `pthread_mutex_lock` must + * succeed. + * + * Thread A unlocks L. + * + * Thread A attempts to unlock L again; the call to `pthread_mutex_unlock` must + * succeed. + * + * Thread M destroys L. + */ -static pthread_mutex_t mutex; -static pthread_mutexattr_t mxAttr; - -void *locker(void *arg) +static void *ThreadA(void *arg) { - assert(pthread_mutex_lock(&mutex) == 0); - lockCount++; - assert(pthread_mutex_lock(&mutex) == 0); - lockCount++; - assert(pthread_mutex_unlock(&mutex) == 0); - assert(pthread_mutex_unlock(&mutex) == 0); + pthread_mutex_t *mutex = arg; - return (void *) 555; + assert(pthread_mutex_lock(mutex) == 0); + assert(pthread_mutex_lock(mutex) == 0); + assert(pthread_mutex_unlock(mutex) == 0); + assert(pthread_mutex_unlock(mutex) == 0); + + return arg; } int main(void) { - pthread_t t; - intptr_t result = 0; - int mxType = -1; + pthread_mutexattr_t mutexAttr; + pthread_mutex_t mutex; + pthread_t thread; + int mutexType; + void *result; - assert(pthread_mutexattr_init(&mxAttr) == 0); - assert(pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE) == 0); - assert(pthread_mutexattr_gettype(&mxAttr, &mxType) == 0); - assert(mxType == PTHREAD_MUTEX_RECURSIVE); - - assert(pthread_mutex_init(&mutex, &mxAttr) == 0); - - assert(pthread_create(&t, NULL, locker, NULL) == 0); - assert(pthread_join(t, (void **) &result) == 0); - assert(result == 555); - assert(lockCount == 2); - + assert(pthread_mutexattr_init(&mutexAttr) == 0); + assert(pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_RECURSIVE) == 0); + assert(pthread_mutexattr_gettype(&mutexAttr, &mutexType) == 0); + assert(mutexType == PTHREAD_MUTEX_RECURSIVE); + assert(pthread_mutex_init(&mutex, &mutexAttr) == 0); + assert(pthread_create(&thread, NULL, ThreadA, &mutex) == 0); + assert(pthread_join (thread, &result) == 0); + assert(result == &mutex); assert(pthread_mutex_destroy(&mutex) == 0); - assert(pthread_mutexattr_destroy(&mxAttr) == 0); + assert(pthread_mutexattr_destroy(&mutexAttr) == 0); - exit(0); - - /* Never reached */ return 0; }
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6rs.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6rs.c index b8f1e82..b1eb570 100644 --- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6rs.c +++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6rs.c
@@ -1,14 +1,10 @@ /* - * mutex6rs.c - * - * - * -------------------------------------------------------------------------- - * * Pthreads-win32 - POSIX Threads Library for Win32 * Copyright(C) 1998 John E. Bossom * Copyright(C) 1999,2005 Pthreads-win32 contributors + * Copyright(C) 2026 mingw-w64 project * - * Contact Email: rpj@callisto.canberra.edu.au + * Contact Email: mingw-w64-public@lists.sourceforge.net * * The current list of contributors is contained * in the file CONTRIBUTORS included with the source @@ -30,60 +26,51 @@ * License along with this library in the file COPYING.LIB; * if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * -------------------------------------------------------------------------- - * - * Tests PTHREAD_MUTEX_RECURSIVE static mutex type. - * Thread locks mutex twice (recursive lock). - * Both locks and unlocks should succeed. - * - * Depends on API functions: - * pthread_create() - * pthread_join() - * pthread_mutexattr_init() - * pthread_mutexattr_destroy() - * pthread_mutexattr_settype() - * pthread_mutexattr_gettype() - * pthread_mutex_init() - * pthread_mutex_destroy() - * pthread_mutex_lock() - * pthread_mutex_unlock() */ #include "test.h" -static int lockCount = 0; +/** + * Test Summary: + * + * Main thread M creates (statically initialized) mutex L with type + * `PTHREAD_MUTEX_RECURSIVE`. + * + * Thread A locks L. + * + * Thread A attempts to lock L again; the call to `pthread_mutex_lock` must + * succeed. + * + * Thread A unlocks L. + * + * Thread A attempts to unlock L again; the call to `pthread_mutex_unlock` must + * succeed. + * + * Thread M destroys L. + */ -static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; - -void *locker(void *arg) +static void *ThreadA(void *arg) { - assert(pthread_mutex_lock(&mutex) == 0); - lockCount++; - assert(pthread_mutex_lock(&mutex) == 0); - lockCount++; - assert(pthread_mutex_unlock(&mutex) == 0); - assert(pthread_mutex_unlock(&mutex) == 0); + pthread_mutex_t *mutex = arg; - return (void *) 555; + assert(pthread_mutex_lock(mutex) == 0); + assert(pthread_mutex_lock(mutex) == 0); + assert(pthread_mutex_unlock(mutex) == 0); + assert(pthread_mutex_unlock(mutex) == 0); + + return arg; } int main(void) { - pthread_t t; - intptr_t result = 0; + pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; + pthread_t thread; + void *result; - assert(mutex == PTHREAD_RECURSIVE_MUTEX_INITIALIZER); - - assert(pthread_create(&t, NULL, locker, NULL) == 0); - assert(pthread_join(t, (void **) &result) == 0); - assert(result == 555); - assert(lockCount == 2); - + assert(pthread_create(&thread, NULL, ThreadA, &mutex) == 0); + assert(pthread_join (thread, &result) == 0); + assert(result == &mutex); assert(pthread_mutex_destroy(&mutex) == 0); - exit(0); - - /* Never reached */ return 0; }
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6s.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6s.c index 6165bdd..5917163 100644 --- a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6s.c +++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/mutex6s.c
@@ -1,14 +1,10 @@ /* - * mutex6s.c - * - * - * -------------------------------------------------------------------------- - * * Pthreads-win32 - POSIX Threads Library for Win32 * Copyright(C) 1998 John E. Bossom * Copyright(C) 1999,2005 Pthreads-win32 contributors + * Copyright(C) 2026 mingw-w64 project * - * Contact Email: rpj@callisto.canberra.edu.au + * Contact Email: mingw-w64-public@lists.sourceforge.net * * The current list of contributors is contained * in the file CONTRIBUTORS included with the source @@ -30,63 +26,79 @@ * License along with this library in the file COPYING.LIB; * if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * -------------------------------------------------------------------------- - * - * Test the default (type not set) static mutex type. - * Should be the same as PTHREAD_MUTEX_NORMAL. - * Thread locks mutex twice (recursive lock). - * Locking thread should deadlock on second attempt. - * - * Depends on API functions: - * pthread_mutex_lock() - * pthread_mutex_trylock() - * pthread_mutex_unlock() */ #include "test.h" -static int lockCount = 0; +/** + * Test Summary: + * + * Main thread M creates (statically initialized) default-type mutex L. + * + * Thread A locks L. + * + * Thread A attempts to lock L again; this must result in a dead lock. + * + * Thread M unlocks and destroys L. + */ -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static LONG IsThreadABlocked = FALSE; -void *locker(void *arg) +static void *ThreadA(void *arg) { - assert(pthread_mutex_lock(&mutex) == 0); - lockCount++; + pthread_mutex_t *mutex = arg; - /* Should wait here (deadlocked) */ - assert(pthread_mutex_lock(&mutex) == 0); - lockCount++; - assert(pthread_mutex_unlock(&mutex) == 0); + assert(pthread_mutex_lock(mutex) == 0); + /** + * Signal thread M that thread A locked L. + */ + InterlockedExchange(&IsThreadABlocked, TRUE); + /** + * Attempt to recursively lock NORMAL mutex must result in a dead lock. + * Wait for main thread to unlock... + */ + assert(pthread_mutex_lock(mutex) == 0); + /** + * Signal thread M that thread A was unblocked. + */ + InterlockedExchange(&IsThreadABlocked, FALSE); + assert(pthread_mutex_unlock(mutex) == 0); - return 0; + return arg; } int main(void) { - pthread_t t; + pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + pthread_t thread; + void *result; - assert(mutex == PTHREAD_MUTEX_INITIALIZER); - - assert(pthread_create(&t, NULL, locker, NULL) == 0); - - Sleep(1000); - - assert(lockCount == 1); - - /* - * Should succeed even though we don't own the lock - * because FAST mutexes don't check ownership. + assert(pthread_create(&thread, NULL, ThreadA, &mutex) == 0); + /** + * Wait until thread A locks L. */ - assert(pthread_mutex_unlock(&mutex) == 0); + while (!IsThreadABlocked) { + YieldProcessor(); + } + Sleep(10); + /** + * Thread A must be deadlocked. + */ + assert(IsThreadABlocked); + /** + * POSIX states that calling `pthread_mutex_unlock` on NORMAL mutex that is + * not owned by the calling thread is undefined behavior. + * + * Our implementation for NORMAL mutexes does not check ownership at all, + * so call to `pthread_mutex_unlock` on a valid NORMAL mutex always succeeds. + */ + do { + assert(pthread_mutex_unlock(&mutex) == 0); + YieldProcessor(); + } while (IsThreadABlocked); + assert(pthread_join (thread, &result) == 0); + assert(result == &mutex); + assert(pthread_mutex_destroy(&mutex) == 0); - Sleep (1000); - - assert(lockCount == 2); - - exit(0); - - /* Never reached */ return 0; }