summaryrefslogtreecommitdiff
path: root/src/thread
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2018-09-15 13:45:41 -0400
committerRich Felker <dalias@aerifal.cx>2018-09-15 14:22:06 -0400
commit5994de4e02a05c19a6bddadcfb687ab2e7511bd6 (patch)
tree5d0ffa57b7a59fdc6323afd105fcdf748f636776 /src/thread
parentdbcfb16e43af28ba919f651c51d7a2f15af656a1 (diff)
downloadmusl-5994de4e02a05c19a6bddadcfb687ab2e7511bd6.tar.gz
check for kernel support before allowing robust mutex creation
on some archs, linux support for futex operations (including robust_list processing) that depend on kernelspace CAS is conditional on a runtime check. as of linux 4.18, this check fails unconditionally on nommu archs that perform it, and spurious failure on powerpc64 was observed but not explained. it's also possible that futex support is omitted entirely, or that the kernel is older than 2.6.17. for most futex ops, ENOSYS does not yield hard breakage; userspace will just spin at 100% cpu load. but for robust mutexes, correct behavior depends on the kernel functionality. use the get_robust_list syscall to probe for support at the first call to pthread_mutexattr_setrobust, and block creation of robust mutexes with a reportable error if they can't be supported.
Diffstat (limited to 'src/thread')
-rw-r--r--src/thread/pthread_mutexattr_setrobust.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/src/thread/pthread_mutexattr_setrobust.c b/src/thread/pthread_mutexattr_setrobust.c
index dcfa4cf1..04db92a6 100644
--- a/src/thread/pthread_mutexattr_setrobust.c
+++ b/src/thread/pthread_mutexattr_setrobust.c
@@ -1,9 +1,25 @@
#include "pthread_impl.h"
+#include "syscall.h"
+
+static pthread_once_t check_robust_once;
+static int check_robust_result;
+
+static void check_robust()
+{
+ void *p;
+ size_t l;
+ check_robust_result = -__syscall(SYS_get_robust_list, 0, &p, &l);
+}
int pthread_mutexattr_setrobust(pthread_mutexattr_t *a, int robust)
{
if (robust > 1U) return EINVAL;
+ if (robust) {
+ pthread_once(&check_robust_once, check_robust);
+ if (check_robust_result) return check_robust_result;
+ a->__attr |= 4;
+ return 0;
+ }
a->__attr &= ~4;
- a->__attr |= robust*4;
return 0;
}