winpthreads: mutex.c: implement `pthread_mutexattr_{set,get}robust` functions
This change is a preparation step for implementing robust mutexes.
Add new test `pthread_mutex/attr-robust.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/include/pthread.h b/mingw-w64-libraries/winpthreads/include/pthread.h
index f415a06..a61753c 100644
--- a/mingw-w64-libraries/winpthreads/include/pthread.h
+++ b/mingw-w64-libraries/winpthreads/include/pthread.h
@@ -231,6 +231,9 @@
#define PTHREAD_MUTEX_PRIVATE 0
#define PTHREAD_MUTEX_SHARED 1
+#define PTHREAD_MUTEX_STALLED 0
+#define PTHREAD_MUTEX_ROBUST 1
+
typedef unsigned pthread_mutexattr_t;
WINPTHREAD_API int pthread_mutexattr_init(pthread_mutexattr_t *);
@@ -243,6 +246,8 @@
WINPTHREAD_API int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *, int *);
WINPTHREAD_API int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int);
WINPTHREAD_API int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *, int *);
+WINPTHREAD_API int pthread_mutexattr_setrobust(pthread_mutexattr_t *, int);
+WINPTHREAD_API int pthread_mutexattr_getrobust(const pthread_mutexattr_t *, int *);
typedef intptr_t pthread_mutex_t;
diff --git a/mingw-w64-libraries/winpthreads/src/mutex.c b/mingw-w64-libraries/winpthreads/src/mutex.c
index 555804c..152c561 100644
--- a/mingw-w64-libraries/winpthreads/src/mutex.c
+++ b/mingw-w64-libraries/winpthreads/src/mutex.c
@@ -79,8 +79,6 @@
* - pthread_mutex_clocklock()
* - pthread_mutex_getprioceiling()
* - pthread_mutex_setprioceiling()
- * - pthread_mutexattr_getrobust()
- * - pthread_mutexattr_setrobust()
*/
/**
@@ -161,7 +159,12 @@
* Currently, winpthreads only supports `PTHREAD_PROCESS_PRIVATE`.
*/
int Shared : 1;
- int Reserved : 3;
+ /**
+ * Zero for `PTHREAD_MUTEX_STALLED` and non-zero for
+ * `PTHREAD_MUTEX_ROBUST`.
+ */
+ int Robust : 1;
+ int Reserved : 2;
/**
* Can be one of the following values:
*
@@ -199,6 +202,7 @@
#define WINPTHREADS_MUTEX_ATTRIBUTES_DEFAULT ((WinpthreadsMutexAttributes) { \
.Attributes.Type = PTHREAD_MUTEX_NORMAL, \
.Attributes.Shared = PTHREAD_PROCESS_PRIVATE, \
+ .Attributes.Robust = PTHREAD_MUTEX_STALLED, \
.Attributes.Reserved = 0, \
.Attributes.Protocol = PTHREAD_PRIO_NONE, \
.Attributes.PriorityCeiling = THREAD_PRIORITY_NORMAL, \
@@ -434,7 +438,8 @@
}
/*******************************************************************************
- * Normal Mutex (PTHREAD_MUTEX_NORMAL) implementation.
+ * Normal (PTHREAD_MUTEX_NORMAL) Stalled (PTHREAD_MUTEX_STALLED) Mutex
+ * implementation.
*
* Normal Mutexes have the following properties:
*
@@ -545,7 +550,8 @@
};
/*******************************************************************************
- * Error Checking Mutex (PTHREAD_MUTEX_ERRORCHECK) implementation.
+ * Error Checking (PTHREAD_MUTEX_ERRORCHECK) Stalled (PTHREAD_MUTEX_STALLED)
+ * Mutex implementation.
*
* Error Checking Mutexes have the following properties:
*
@@ -676,7 +682,8 @@
};
/*******************************************************************************
- * Recursive Mutex (PTHREAD_MUTEX_RECURSIVE) implementation.
+ * Recursive (PTHREAD_MUTEX_RECURSIVE) Stalled (PTHREAD_MUTEX_STALLED) Mutex
+ * implementation.
*
* Recursive Mutexes have the following properties:
*
@@ -1043,6 +1050,44 @@
return EINVAL;
}
+int pthread_mutexattr_setrobust(pthread_mutexattr_t *a, int value)
+{
+ if (a == NULL) {
+ return EINVAL;
+ }
+
+ WinpthreadsMutexAttributes *wMutexAttr = (WinpthreadsMutexAttributes *) a;
+
+ if (wMutexAttr->Attributes.Magic != WINPTHREADS_MUTEX_ATTRIBUTES_MAGIC) {
+ return EINVAL;
+ }
+
+ switch (value) {
+ case PTHREAD_MUTEX_STALLED:
+ case PTHREAD_MUTEX_ROBUST:
+ wMutexAttr->Attributes.Robust = value;
+ return 0;
+ }
+
+ return EINVAL;
+}
+
+int pthread_mutexattr_getrobust(const pthread_mutexattr_t *a, int *value)
+{
+ if (a == NULL || value == NULL) {
+ return EINVAL;
+ }
+
+ const WinpthreadsMutexAttributes *wMutexAttr = (const WinpthreadsMutexAttributes *) a;
+
+ if (wMutexAttr->Attributes.Magic != WINPTHREADS_MUTEX_ATTRIBUTES_MAGIC) {
+ return EINVAL;
+ }
+
+ *value = !!wMutexAttr->Attributes.Robust;
+ return 0;
+}
+
/*******************************************************************************
* Implementation for public `pthread_mutex_*` functions.
*/
@@ -1148,6 +1193,10 @@
return EINVAL;
}
+ if (pthread_mutexattr_getrobust (&wMutexAttr.Value, &value) != 0) {
+ return EINVAL;
+ }
+
if (pthread_mutexattr_getprotocol (&wMutexAttr.Value, &value) != 0) {
return EINVAL;
}
@@ -1165,13 +1214,25 @@
switch (wMutexAttr.Attributes.Type) {
case PTHREAD_MUTEX_NORMAL:
- wMutexVtable = &WinpthreadsNormalMutexVtable;
+ if (wMutexAttr.Attributes.Robust) {
+ return ENOSYS;
+ } else {
+ wMutexVtable = &WinpthreadsNormalMutexVtable;
+ }
break;
case PTHREAD_MUTEX_ERRORCHECK:
- wMutexVtable = &WinpthreadsErrorCheckMutexVtable;
+ if (wMutexAttr.Attributes.Robust) {
+ return ENOSYS;
+ } else {
+ wMutexVtable = &WinpthreadsErrorCheckMutexVtable;
+ }
break;
case PTHREAD_MUTEX_RECURSIVE:
- wMutexVtable = &WinpthreadsRecursiveMutexVtable;
+ if (wMutexAttr.Attributes.Robust) {
+ return ENOSYS;
+ } else {
+ wMutexVtable = &WinpthreadsRecursiveMutexVtable;
+ }
break;
default:
UNREACHABLE ();
diff --git a/mingw-w64-libraries/winpthreads/tests/Makefile.am b/mingw-w64-libraries/winpthreads/tests/Makefile.am
index 8087899..57a647d 100644
--- a/mingw-w64-libraries/winpthreads/tests/Makefile.am
+++ b/mingw-w64-libraries/winpthreads/tests/Makefile.am
@@ -113,6 +113,7 @@
pthread_mutex/attr-prioceiling \
pthread_mutex/attr-protocol \
pthread_mutex/attr-pshared \
+ pthread_mutex/attr-robust \
pthread_mutex/attr-type \
pthread_mutex/default-basic \
pthread_mutex/default-lock-recursive \
diff --git a/mingw-w64-libraries/winpthreads/tests/pthread_mutex/attr-robust.c b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/attr-robust.c
new file mode 100644
index 0000000..39974c4
--- /dev/null
+++ b/mingw-w64-libraries/winpthreads/tests/pthread_mutex/attr-robust.c
@@ -0,0 +1,57 @@
+/*
+ Copyright (c) 2026 mingw-w64 project
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+*/
+
+#include "test.h"
+
+/**
+ * Test Summary:
+ *
+ * Test functions `pthread_mutexattr_setrobust` and
+ * `pthread_mutexattr_getrobust`.
+ */
+
+static void DoTest (int value, int expectedValue, int expectedReturn1, int expectedReturn2) {
+ pthread_mutexattr_t mutexAttr;
+ pthread_mutex_t mutex;
+
+ assert (pthread_mutexattr_init (&mutexAttr) == 0);
+ assert (pthread_mutexattr_setrobust (&mutexAttr, value) == expectedReturn1);
+ assert (pthread_mutexattr_getrobust (&mutexAttr, &value) == 0);
+ assert (value == expectedValue);
+ assert (pthread_mutex_init (&mutex, &mutexAttr) == expectedReturn2);
+ if (expectedReturn2 == 0) {
+ assert (pthread_mutex_destroy (&mutex) == 0);
+ }
+ assert (pthread_mutexattr_destroy (&mutexAttr) == 0);
+}
+
+int main (void) {
+ DoTest (PTHREAD_MUTEX_STALLED, PTHREAD_MUTEX_STALLED, 0, 0);
+ DoTest (PTHREAD_MUTEX_ROBUST, PTHREAD_MUTEX_ROBUST, 0, ENOSYS);
+
+ /**
+ * Try setting an invalid value; default attribute value must be used.
+ */
+ DoTest (0xFF, PTHREAD_MUTEX_STALLED, EINVAL, 0);
+
+ return 0;
+}