winpthreads: mutex.c: update `pthread_mutexattr_*` functions
Interpret `pthread_mutexattr_t` as a union consisting of bit fields.
This change makes it easier to understand how `pthread_mutexattr_*` functions
operate on `pthread_mutexattr_t` objects and provide support for new attributes.
Remove macro `PTHREAD_PRIO_MULT` from pthread.h; this constant is not defined
by POSIX and is only used by `pthread_mutexattr_{set,get}prioceiling` functions.
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 3ab5db7..f9eba44 100644
--- a/mingw-w64-libraries/winpthreads/include/pthread.h
+++ b/mingw-w64-libraries/winpthreads/include/pthread.h
@@ -128,7 +128,6 @@
#define PTHREAD_PRIO_NONE 0
#define PTHREAD_PRIO_INHERIT 8
#define PTHREAD_PRIO_PROTECT 16
-#define PTHREAD_PRIO_MULT 32
#define PTHREAD_PROCESS_SHARED 1
#define PTHREAD_PROCESS_PRIVATE 0
diff --git a/mingw-w64-libraries/winpthreads/src/mutex.c b/mingw-w64-libraries/winpthreads/src/mutex.c
index 3b3edf2..93b854f 100644
--- a/mingw-w64-libraries/winpthreads/src/mutex.c
+++ b/mingw-w64-libraries/winpthreads/src/mutex.c
@@ -90,6 +90,11 @@
typedef union WinpthreadsMutex WinpthreadsMutex;
/**
+ * Forward declaration; see definition below.
+ */
+typedef union WinpthreadsMutexAttributes WinpthreadsMutexAttributes;
+
+/**
* Mutex type-specific "init" routine.
*/
typedef int (* FuncMutexInit) (WinpthreadsMutex **, const pthread_mutexattr_t *);
@@ -130,6 +135,71 @@
FuncMutexUnlock Unlock;
} WinpthreadsMutexVtable;
+/**
+ * Union stored in `pthread_mutexattr_t` objects.
+ */
+union WinpthreadsMutexAttributes {
+ pthread_mutexattr_t Value;
+ struct {
+ /**
+ * Can be one of the following values:
+ *
+ * - PTHREAD_MUTEX_NORMAL
+ * - PTHREAD_MUTEX_ERRORCHECK
+ * - PTHREAD_MUTEX_RECURSIVE
+ */
+ int Type : 4;
+ /**
+ * Zero for `PTHREAD_PROCESS_PRIVATE` and non-zero for
+ * `PTHREAD_PROCESS_SHARED`.
+ *
+ * Currently, winpthreads only supports `PTHREAD_PROCESS_PRIVATE`.
+ */
+ int Shared : 1;
+ int Reserved : 3;
+ /**
+ * Can be one of the following values:
+ *
+ * - PTHREAD_PRIO_NONE
+ * - PTHREAD_PRIO_INHERIT
+ * - PTHREAD_PRIO_PROTECT
+ *
+ * Currently, winpthreads does not implement POSIX realtime extensions.
+ * As such, the only supported value is `PTHREAD_PRIO_NONE`.
+ */
+ int Protocol : 8;
+ /**
+ * Can be any valid `THREAD_PRIORITY_*` value.
+ *
+ * Only has effect when `Protocol` is `PTHREAD_PRIO_INHERIT` or
+ * `PTHREAD_PRIO_PROTECT`, which are not currently supported.
+ */
+ int PriorityCeiling : 8;
+#define WINPTHREADS_MUTEX_ATTRIBUTES_MAGIC 0x67
+ /**
+ * Must be `WINPTHREADS_MUTEX_ATTRIBUTES_MAGIC`.
+ *
+ * If needed, these bits may be used for future extensions.
+ */
+ int Magic : 8;
+ } Attributes;
+};
+
+WINPTHREADS_STATIC_ASSERT (sizeof ((WinpthreadsMutexAttributes) {}.Attributes) == sizeof (pthread_mutexattr_t), "");
+
+/**
+ * Expands into an expression of type `WinpthreadsMutexAttributes`
+ * corresponding to the default mutex attributes.
+ */
+#define WINPTHREADS_MUTEX_ATTRIBUTES_DEFAULT ((WinpthreadsMutexAttributes) { \
+ .Attributes.Type = PTHREAD_MUTEX_NORMAL, \
+ .Attributes.Shared = PTHREAD_PROCESS_PRIVATE, \
+ .Attributes.Reserved = 0, \
+ .Attributes.Protocol = PTHREAD_PRIO_NONE, \
+ .Attributes.PriorityCeiling = THREAD_PRIORITY_NORMAL, \
+ .Attributes.Magic = WINPTHREADS_MUTEX_ATTRIBUTES_MAGIC \
+ })
+
#define THREAD_ID_NO_OWNER ((DWORD) -1)
/**
@@ -1038,102 +1108,197 @@
int pthread_mutexattr_init(pthread_mutexattr_t *a)
{
- *a = PTHREAD_MUTEX_NORMAL | (PTHREAD_PROCESS_PRIVATE << 3);
+ *a = WINPTHREADS_MUTEX_ATTRIBUTES_DEFAULT.Value;
return 0;
}
int pthread_mutexattr_destroy(pthread_mutexattr_t *a)
{
- if (!a)
+ if (a == NULL) {
return EINVAL;
-
- return 0;
-}
-
-int pthread_mutexattr_gettype(const pthread_mutexattr_t *a, int *type)
-{
- if (!a || !type)
- return EINVAL;
-
- *type = *a & 3;
-
- return 0;
-}
-
-int pthread_mutexattr_settype(pthread_mutexattr_t *a, int type)
-{
- if (!a)
- return EINVAL;
-
- if (type != PTHREAD_MUTEX_NORMAL && type != PTHREAD_MUTEX_RECURSIVE && type != PTHREAD_MUTEX_ERRORCHECK)
- return EINVAL;
-
- *a &= ~3;
- *a |= type;
-
- return 0;
-}
-
-int pthread_mutexattr_getpshared(const pthread_mutexattr_t *a, int *type)
-{
- if (!a || !type)
- return EINVAL;
-
- *type = (*a & 4 ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE);
-
- return 0;
-}
-
-int pthread_mutexattr_setpshared(pthread_mutexattr_t *a, int type)
-{
- int r = 0;
-
- if (!a)
- return EINVAL;
-
- if (type != PTHREAD_PROCESS_SHARED && type != PTHREAD_PROCESS_PRIVATE)
- return EINVAL;
-
- if (type == PTHREAD_PROCESS_SHARED) {
- type = PTHREAD_PROCESS_PRIVATE;
- r = ENOSYS;
}
- type = (type == PTHREAD_PROCESS_SHARED ? 4 : 0);
-
- *a &= ~4;
- *a |= type;
-
- return r;
-}
-
-int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *a, int *type)
-{
- *type = *a & (8 + 16);
+ memset (a, 0, sizeof (pthread_mutexattr_t));
return 0;
}
-int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int type)
+int pthread_mutexattr_gettype(const pthread_mutexattr_t *a, int *value)
{
- if ((type & (8 + 16)) != 8 + 16)
+ if (a == NULL || value == NULL) {
return EINVAL;
+ }
- *a &= ~(8 + 16);
- *a |= type;
+ const WinpthreadsMutexAttributes *wMutexAttr = (const WinpthreadsMutexAttributes *) a;
+ if (wMutexAttr->Attributes.Magic != WINPTHREADS_MUTEX_ATTRIBUTES_MAGIC) {
+ return EINVAL;
+ }
+
+ switch (wMutexAttr->Attributes.Type) {
+ case PTHREAD_MUTEX_NORMAL:
+ case PTHREAD_MUTEX_ERRORCHECK:
+ case PTHREAD_MUTEX_RECURSIVE:
+ *value = wMutexAttr->Attributes.Type;
+ return 0;
+ }
+
+ return EINVAL;
+}
+
+int pthread_mutexattr_settype(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_NORMAL:
+ case PTHREAD_MUTEX_ERRORCHECK:
+ case PTHREAD_MUTEX_RECURSIVE:
+ wMutexAttr->Attributes.Type = value;
+ return 0;
+ }
+
+ return EINVAL;
+}
+
+int pthread_mutexattr_getpshared(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.Shared;
return 0;
}
-int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *a, int *prio)
+int pthread_mutexattr_setpshared(pthread_mutexattr_t *a, int value)
{
- *prio = *a / PTHREAD_PRIO_MULT;
- return 0;
+ if (a == NULL) {
+ return EINVAL;
+ }
+
+ WinpthreadsMutexAttributes *wMutexAttr = (WinpthreadsMutexAttributes *) a;
+
+ if (wMutexAttr->Attributes.Magic != WINPTHREADS_MUTEX_ATTRIBUTES_MAGIC) {
+ return EINVAL;
+ }
+
+ switch (value) {
+ case PTHREAD_PROCESS_PRIVATE:
+ case PTHREAD_PROCESS_SHARED:
+ wMutexAttr->Attributes.Shared = value;
+ return 0;
+ }
+
+ return EINVAL;
}
-int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a, int prio)
+int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *a, int *value)
{
- *a &= (PTHREAD_PRIO_MULT - 1);
- *a += prio * PTHREAD_PRIO_MULT;
+ if (a == NULL || value == NULL) {
+ return EINVAL;
+ }
- return 0;
+ const WinpthreadsMutexAttributes *wMutexAttr = (const WinpthreadsMutexAttributes *) a;
+
+ if (wMutexAttr->Attributes.Magic != WINPTHREADS_MUTEX_ATTRIBUTES_MAGIC) {
+ return EINVAL;
+ }
+
+ switch (wMutexAttr->Attributes.Protocol) {
+ case PTHREAD_PRIO_NONE:
+ case PTHREAD_PRIO_INHERIT:
+ case PTHREAD_PRIO_PROTECT:
+ *value = wMutexAttr->Attributes.Protocol;
+ return 0;
+ }
+
+ return EINVAL;
+}
+
+int pthread_mutexattr_setprotocol(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_PRIO_NONE:
+ wMutexAttr->Attributes.Protocol = value;
+ return 0;
+ /**
+ * POSIX realtime extensions are not implemented.
+ *
+ * The pthread_mutexattr_setprotocol() function shall fail if:
+ *
+ * [ENOTSUP]
+ * The value specified by protocol is an unsupported value.
+ */
+ case PTHREAD_PRIO_INHERIT:
+ case PTHREAD_PRIO_PROTECT:
+ return ENOTSUP;
+ }
+
+ return EINVAL;
+}
+
+int pthread_mutexattr_getprioceiling(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;
+ }
+
+ int priorityCeiling = wMutexAttr->Attributes.PriorityCeiling;
+
+ if (priorityCeiling >= THREAD_PRIORITY_IDLE && priorityCeiling <= THREAD_PRIORITY_TIME_CRITICAL) {
+ *value = priorityCeiling;
+ return 0;
+ }
+
+ return EINVAL;
+}
+
+int pthread_mutexattr_setprioceiling(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;
+ }
+
+ if (value >= THREAD_PRIORITY_IDLE && value <= THREAD_PRIORITY_TIME_CRITICAL) {
+ wMutexAttr->Attributes.PriorityCeiling = value;
+ return 0;
+ }
+
+ return EINVAL;
}