diff options
Diffstat (limited to 'main/musl/0002-d86af2a0-to-4992ace9.patch')
-rw-r--r-- | main/musl/0002-d86af2a0-to-4992ace9.patch | 1083 |
1 files changed, 0 insertions, 1083 deletions
diff --git a/main/musl/0002-d86af2a0-to-4992ace9.patch b/main/musl/0002-d86af2a0-to-4992ace9.patch deleted file mode 100644 index ed0eb65226..0000000000 --- a/main/musl/0002-d86af2a0-to-4992ace9.patch +++ /dev/null @@ -1,1083 +0,0 @@ -diff --git a/arch/arm/bits/alltypes.h.in b/arch/arm/bits/alltypes.h.in -index bd23a6a..0d750cc 100644 ---- a/arch/arm/bits/alltypes.h.in -+++ b/arch/arm/bits/alltypes.h.in -@@ -17,7 +17,7 @@ TYPEDEF long time_t; - TYPEDEF long suseconds_t; - - TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; --TYPEDEF struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t; -+TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; - TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; - TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; - TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; -diff --git a/arch/i386/bits/alltypes.h.in b/arch/i386/bits/alltypes.h.in -index efd2c07..502c882 100644 ---- a/arch/i386/bits/alltypes.h.in -+++ b/arch/i386/bits/alltypes.h.in -@@ -31,7 +31,7 @@ TYPEDEF long time_t; - TYPEDEF long suseconds_t; - - TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; --TYPEDEF struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t; -+TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; - TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; - TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; - TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; -diff --git a/arch/microblaze/bits/alltypes.h.in b/arch/microblaze/bits/alltypes.h.in -index 6bd7942..4657d14 100644 ---- a/arch/microblaze/bits/alltypes.h.in -+++ b/arch/microblaze/bits/alltypes.h.in -@@ -17,7 +17,7 @@ TYPEDEF long time_t; - TYPEDEF long suseconds_t; - - TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; --TYPEDEF struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t; -+TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; - TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; - TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; - TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; -diff --git a/arch/mips/bits/alltypes.h.in b/arch/mips/bits/alltypes.h.in -index 6bd7942..4657d14 100644 ---- a/arch/mips/bits/alltypes.h.in -+++ b/arch/mips/bits/alltypes.h.in -@@ -17,7 +17,7 @@ TYPEDEF long time_t; - TYPEDEF long suseconds_t; - - TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; --TYPEDEF struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t; -+TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; - TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; - TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; - TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; -diff --git a/arch/or1k/bits/alltypes.h.in b/arch/or1k/bits/alltypes.h.in -index bd23a6a..0d750cc 100644 ---- a/arch/or1k/bits/alltypes.h.in -+++ b/arch/or1k/bits/alltypes.h.in -@@ -17,7 +17,7 @@ TYPEDEF long time_t; - TYPEDEF long suseconds_t; - - TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; --TYPEDEF struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t; -+TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; - TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; - TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; - TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; -diff --git a/arch/powerpc/bits/alltypes.h.in b/arch/powerpc/bits/alltypes.h.in -index e9d8dd8..378124c 100644 ---- a/arch/powerpc/bits/alltypes.h.in -+++ b/arch/powerpc/bits/alltypes.h.in -@@ -17,7 +17,7 @@ TYPEDEF long time_t; - TYPEDEF long suseconds_t; - - TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; --TYPEDEF struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t; -+TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; - TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; - TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; - TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; -diff --git a/arch/sh/bits/alltypes.h.in b/arch/sh/bits/alltypes.h.in -index e9d8dd8..378124c 100644 ---- a/arch/sh/bits/alltypes.h.in -+++ b/arch/sh/bits/alltypes.h.in -@@ -17,7 +17,7 @@ TYPEDEF long time_t; - TYPEDEF long suseconds_t; - - TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; --TYPEDEF struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t; -+TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; - TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; - TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; - TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; -diff --git a/arch/x32/bits/alltypes.h.in b/arch/x32/bits/alltypes.h.in -index b077fc9..8930efa 100644 ---- a/arch/x32/bits/alltypes.h.in -+++ b/arch/x32/bits/alltypes.h.in -@@ -22,7 +22,7 @@ TYPEDEF long long time_t; - TYPEDEF long long suseconds_t; - - TYPEDEF struct { union { int __i[14]; unsigned long __s[7]; } __u; } pthread_attr_t; --TYPEDEF struct { union { int __i[10]; void *__p[5]; } __u; } pthread_mutex_t; -+TYPEDEF struct { union { int __i[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t; - TYPEDEF struct { union { int __i[12]; void *__p[6]; } __u; } pthread_cond_t; - TYPEDEF struct { union { int __i[14]; void *__p[7]; } __u; } pthread_rwlock_t; - TYPEDEF struct { union { int __i[8]; void *__p[4]; } __u; } pthread_barrier_t; -diff --git a/arch/x86_64/bits/alltypes.h.in b/arch/x86_64/bits/alltypes.h.in -index 277e944..34b7d6a 100644 ---- a/arch/x86_64/bits/alltypes.h.in -+++ b/arch/x86_64/bits/alltypes.h.in -@@ -22,7 +22,7 @@ TYPEDEF long time_t; - TYPEDEF long suseconds_t; - - TYPEDEF struct { union { int __i[14]; unsigned long __s[7]; } __u; } pthread_attr_t; --TYPEDEF struct { union { int __i[10]; void *__p[5]; } __u; } pthread_mutex_t; -+TYPEDEF struct { union { int __i[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t; - TYPEDEF struct { union { int __i[12]; void *__p[6]; } __u; } pthread_cond_t; - TYPEDEF struct { union { int __i[14]; void *__p[7]; } __u; } pthread_rwlock_t; - TYPEDEF struct { union { int __i[8]; void *__p[4]; } __u; } pthread_barrier_t; -diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h -index 650e811..2d090f8 100644 ---- a/src/internal/pthread_impl.h -+++ b/src/internal/pthread_impl.h -@@ -33,9 +33,9 @@ struct pthread { - pthread_attr_t attr; - volatile int dead; - struct { -- void **head; -+ volatile void *volatile head; - long off; -- void *pending; -+ volatile void *volatile pending; - } robust_list; - int unblock_cancel; - int timer_id; -@@ -66,16 +66,16 @@ struct __timer { - #define _m_prev __u.__p[3] - #define _m_next __u.__p[4] - #define _m_count __u.__i[5] --#define _c_mutex __u.__p[0] -+#define _c_shared __u.__p[0] - #define _c_seq __u.__i[2] - #define _c_waiters __u.__i[3] - #define _c_clock __u.__i[4] --#define _c_lock __u.__i[5] --#define _c_lockwait __u.__i[6] --#define _c_waiters2 __u.__i[7] --#define _c_destroy __u.__i[8] -+#define _c_lock __u.__i[8] -+#define _c_head __u.__p[1] -+#define _c_tail __u.__p[5] - #define _rw_lock __u.__i[0] - #define _rw_waiters __u.__i[1] -+#define _rw_shared __u.__i[2] - #define _b_lock __u.__i[0] - #define _b_waiters __u.__i[1] - #define _b_limit __u.__i[2] -@@ -108,8 +108,13 @@ void __unmapself(void *, size_t); - - int __timedwait(volatile int *, int, clockid_t, const struct timespec *, void (*)(void *), void *, int); - void __wait(volatile int *, volatile int *, int, int); --#define __wake(addr, cnt, priv) \ -- __syscall(SYS_futex, addr, FUTEX_WAKE, (cnt)<0?INT_MAX:(cnt)) -+static inline void __wake(volatile void *addr, int cnt, int priv) -+{ -+ if (priv) priv = 128; -+ if (cnt<0) cnt = INT_MAX; -+ __syscall(SYS_futex, addr, FUTEX_WAKE|priv, cnt) != -EINVAL || -+ __syscall(SYS_futex, addr, FUTEX_WAKE, cnt); -+} - - void __acquire_ptc(); - void __release_ptc(); -diff --git a/src/mman/mmap.c b/src/mman/mmap.c -index 1917a54..56e39a7 100644 ---- a/src/mman/mmap.c -+++ b/src/mman/mmap.c -@@ -16,8 +16,6 @@ weak_alias(dummy0, __vm_unlock); - - void *__mmap(void *start, size_t len, int prot, int flags, int fd, off_t off) - { -- void *ret; -- - if (off & OFF_MASK) { - errno = EINVAL; - return MAP_FAILED; -@@ -26,14 +24,15 @@ void *__mmap(void *start, size_t len, int prot, int flags, int fd, off_t off) - errno = ENOMEM; - return MAP_FAILED; - } -- if (flags & MAP_FIXED) __vm_lock(-1); -+ if (flags & MAP_FIXED) { -+ __vm_lock(-1); -+ __vm_unlock(); -+ } - #ifdef SYS_mmap2 -- ret = (void *)syscall(SYS_mmap2, start, len, prot, flags, fd, off/UNIT); -+ return (void *)syscall(SYS_mmap2, start, len, prot, flags, fd, off/UNIT); - #else -- ret = (void *)syscall(SYS_mmap, start, len, prot, flags, fd, off); -+ return (void *)syscall(SYS_mmap, start, len, prot, flags, fd, off); - #endif -- if (flags & MAP_FIXED) __vm_unlock(); -- return ret; - } - - weak_alias(__mmap, mmap); -diff --git a/src/mman/munmap.c b/src/mman/munmap.c -index 8488d75..359c691 100644 ---- a/src/mman/munmap.c -+++ b/src/mman/munmap.c -@@ -11,8 +11,8 @@ int __munmap(void *start, size_t len) - { - int ret; - __vm_lock(-1); -- ret = syscall(SYS_munmap, start, len); - __vm_unlock(); -+ ret = syscall(SYS_munmap, start, len); - return ret; - } - -diff --git a/src/thread/__timedwait.c b/src/thread/__timedwait.c -index 302273a..39eb996 100644 ---- a/src/thread/__timedwait.c -+++ b/src/thread/__timedwait.c -@@ -4,12 +4,15 @@ - #include "futex.h" - #include "syscall.h" - --static int do_wait(volatile int *addr, int val, -- clockid_t clk, const struct timespec *at, int priv) -+int __timedwait(volatile int *addr, int val, -+ clockid_t clk, const struct timespec *at, -+ void (*cleanup)(void *), void *arg, int priv) - { -- int r; -+ int r, cs; - struct timespec to, *top=0; - -+ if (priv) priv = 128; -+ - if (at) { - if (at->tv_nsec >= 1000000000UL) return EINVAL; - if (clock_gettime(clk, &to)) return EINVAL; -@@ -22,21 +25,12 @@ static int do_wait(volatile int *addr, int val, - top = &to; - } - -- r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT, val, top); -- if (r == EINTR || r == EINVAL || r == ETIMEDOUT) return r; -- return 0; --} -- --int __timedwait(volatile int *addr, int val, -- clockid_t clk, const struct timespec *at, -- void (*cleanup)(void *), void *arg, int priv) --{ -- int r, cs; -- - if (!cleanup) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); - pthread_cleanup_push(cleanup, arg); - -- r = do_wait(addr, val, clk, at, priv); -+ r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT|priv, val, top); -+ if (r == EINVAL) r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT, val, top); -+ if (r != EINTR && r != ETIMEDOUT) r = 0; - - pthread_cleanup_pop(0); - if (!cleanup) pthread_setcancelstate(cs, 0); -diff --git a/src/thread/__wait.c b/src/thread/__wait.c -index a1e4780..ec1e820 100644 ---- a/src/thread/__wait.c -+++ b/src/thread/__wait.c -@@ -3,13 +3,15 @@ - void __wait(volatile int *addr, volatile int *waiters, int val, int priv) - { - int spins=10000; -- if (priv) priv = 128; priv=0; -+ if (priv) priv = 128; - while (spins--) { - if (*addr==val) a_spin(); - else return; - } - if (waiters) a_inc(waiters); -- while (*addr==val) -- __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0); -+ while (*addr==val) { -+ __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -EINVAL -+ || __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0); -+ } - if (waiters) a_dec(waiters); - } -diff --git a/src/thread/pthread_attr_get.c b/src/thread/pthread_attr_get.c -index 03fc91e..3d296bf 100644 ---- a/src/thread/pthread_attr_get.c -+++ b/src/thread/pthread_attr_get.c -@@ -75,7 +75,7 @@ int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *restrict a, int *re - } - int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict a, int *restrict pshared) - { -- *pshared = a->__attr>>31; -+ *pshared = a->__attr / 128U % 2; - return 0; - } - -diff --git a/src/thread/pthread_barrier_wait.c b/src/thread/pthread_barrier_wait.c -index 5e60338..6b329c9 100644 ---- a/src/thread/pthread_barrier_wait.c -+++ b/src/thread/pthread_barrier_wait.c -@@ -87,7 +87,8 @@ int pthread_barrier_wait(pthread_barrier_t *b) - a_spin(); - a_inc(&inst->finished); - while (inst->finished == 1) -- __syscall(SYS_futex, &inst->finished, FUTEX_WAIT,1,0); -+ __syscall(SYS_futex,&inst->finished,FUTEX_WAIT|128,1,0) != -EINTR -+ || __syscall(SYS_futex,&inst->finished,FUTEX_WAIT,1,0); - return PTHREAD_BARRIER_SERIAL_THREAD; - } - -diff --git a/src/thread/pthread_cond_broadcast.c b/src/thread/pthread_cond_broadcast.c -index 0901daf..69f840f 100644 ---- a/src/thread/pthread_cond_broadcast.c -+++ b/src/thread/pthread_cond_broadcast.c -@@ -1,39 +1,12 @@ - #include "pthread_impl.h" - -+int __private_cond_signal(pthread_cond_t *, int); -+ - int pthread_cond_broadcast(pthread_cond_t *c) - { -- pthread_mutex_t *m; -- -+ if (!c->_c_shared) return __private_cond_signal(c, -1); - if (!c->_c_waiters) return 0; -- - a_inc(&c->_c_seq); -- -- /* If cond var is process-shared, simply wake all waiters. */ -- if (c->_c_mutex == (void *)-1) { -- __wake(&c->_c_seq, -1, 0); -- return 0; -- } -- -- /* Block waiters from returning so we can use the mutex. */ -- while (a_swap(&c->_c_lock, 1)) -- __wait(&c->_c_lock, &c->_c_lockwait, 1, 1); -- if (!c->_c_waiters) -- goto out; -- m = c->_c_mutex; -- -- /* Move waiter count to the mutex */ -- a_fetch_add(&m->_m_waiters, c->_c_waiters2); -- c->_c_waiters2 = 0; -- -- /* Perform the futex requeue, waking one waiter unless we know -- * that the calling thread holds the mutex. */ -- __syscall(SYS_futex, &c->_c_seq, FUTEX_REQUEUE, -- !m->_m_type || (m->_m_lock&INT_MAX)!=__pthread_self()->tid, -- INT_MAX, &m->_m_lock); -- --out: -- a_store(&c->_c_lock, 0); -- if (c->_c_lockwait) __wake(&c->_c_lock, 1, 0); -- -+ __wake(&c->_c_seq, -1, 0); - return 0; - } -diff --git a/src/thread/pthread_cond_destroy.c b/src/thread/pthread_cond_destroy.c -index a096c55..8c55516 100644 ---- a/src/thread/pthread_cond_destroy.c -+++ b/src/thread/pthread_cond_destroy.c -@@ -2,12 +2,13 @@ - - int pthread_cond_destroy(pthread_cond_t *c) - { -- int priv = c->_c_mutex != (void *)-1; -- int cnt; -- c->_c_destroy = 1; -- if (c->_c_waiters) -- __wake(&c->_c_seq, -1, priv); -- while ((cnt = c->_c_waiters)) -- __wait(&c->_c_waiters, 0, cnt, priv); -+ if (c->_c_shared && c->_c_waiters) { -+ int cnt; -+ a_or(&c->_c_waiters, 0x80000000); -+ a_inc(&c->_c_seq); -+ __wake(&c->_c_seq, -1, 0); -+ while ((cnt = c->_c_waiters) & 0x7fffffff) -+ __wait(&c->_c_waiters, 0, cnt, 0); -+ } - return 0; - } -diff --git a/src/thread/pthread_cond_init.c b/src/thread/pthread_cond_init.c -index 357ecd5..8c484dd 100644 ---- a/src/thread/pthread_cond_init.c -+++ b/src/thread/pthread_cond_init.c -@@ -5,7 +5,7 @@ int pthread_cond_init(pthread_cond_t *restrict c, const pthread_condattr_t *rest - *c = (pthread_cond_t){0}; - if (a) { - c->_c_clock = a->__attr & 0x7fffffff; -- if (a->__attr>>31) c->_c_mutex = (void *)-1; -+ if (a->__attr>>31) c->_c_shared = (void *)-1; - } - return 0; - } -diff --git a/src/thread/pthread_cond_signal.c b/src/thread/pthread_cond_signal.c -index 71bcdcd..119c00a 100644 ---- a/src/thread/pthread_cond_signal.c -+++ b/src/thread/pthread_cond_signal.c -@@ -1,9 +1,12 @@ - #include "pthread_impl.h" - -+int __private_cond_signal(pthread_cond_t *, int); -+ - int pthread_cond_signal(pthread_cond_t *c) - { -+ if (!c->_c_shared) return __private_cond_signal(c, 1); - if (!c->_c_waiters) return 0; - a_inc(&c->_c_seq); -- if (c->_c_waiters) __wake(&c->_c_seq, 1, 0); -+ __wake(&c->_c_seq, 1, 0); - return 0; - } -diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c -index 99d62cc..c5cf66c 100644 ---- a/src/thread/pthread_cond_timedwait.c -+++ b/src/thread/pthread_cond_timedwait.c -@@ -1,47 +1,130 @@ - #include "pthread_impl.h" - --struct cm { -- pthread_cond_t *c; -- pthread_mutex_t *m; -+/* -+ * struct waiter -+ * -+ * Waiter objects have automatic storage on the waiting thread, and -+ * are used in building a linked list representing waiters currently -+ * waiting on the condition variable or a group of waiters woken -+ * together by a broadcast or signal; in the case of signal, this is a -+ * degenerate list of one member. -+ * -+ * Waiter lists attached to the condition variable itself are -+ * protected by the lock on the cv. Detached waiter lists are never -+ * modified again, but can only be traversed in reverse order, and are -+ * protected by the "barrier" locks in each node, which are unlocked -+ * in turn to control wake order. -+ * -+ * Since process-shared cond var semantics do not necessarily allow -+ * one thread to see another's automatic storage (they may be in -+ * different processes), the waiter list is not used for the -+ * process-shared case, but the structure is still used to store data -+ * needed by the cancellation cleanup handler. -+ */ -+ -+struct waiter { -+ struct waiter *prev, *next; -+ int state, barrier, mutex_ret; -+ int *notify; -+ pthread_mutex_t *mutex; -+ pthread_cond_t *cond; -+ int shared; - }; - --static void unwait(pthread_cond_t *c, pthread_mutex_t *m) -+/* Self-synchronized-destruction-safe lock functions */ -+ -+static inline void lock(volatile int *l) - { -- /* Removing a waiter is non-trivial if we could be using requeue -- * based broadcast signals, due to mutex access issues, etc. */ -+ if (a_cas(l, 0, 1)) { -+ a_cas(l, 1, 2); -+ do __wait(l, 0, 2, 1); -+ while (a_cas(l, 0, 2)); -+ } -+} - -- if (c->_c_mutex == (void *)-1) { -- a_dec(&c->_c_waiters); -- if (c->_c_destroy) __wake(&c->_c_waiters, 1, 0); -+static inline void unlock(volatile int *l) -+{ -+ if (a_swap(l, 0)==2) -+ __wake(l, 1, 1); -+} -+ -+static inline void unlock_requeue(volatile int *l, volatile int *r, int w) -+{ -+ a_store(l, 0); -+ if (w) __wake(l, 1, 1); -+ else __syscall(SYS_futex, l, FUTEX_REQUEUE|128, 0, 1, r) != -EINVAL -+ || __syscall(SYS_futex, l, FUTEX_REQUEUE, 0, 1, r); -+} -+ -+enum { -+ WAITING, -+ SIGNALED, -+ LEAVING, -+}; -+ -+static void unwait(void *arg) -+{ -+ struct waiter *node = arg; -+ -+ if (node->shared) { -+ pthread_cond_t *c = node->cond; -+ pthread_mutex_t *m = node->mutex; -+ if (a_fetch_add(&c->_c_waiters, -1) == -0x7fffffff) -+ __wake(&c->_c_waiters, 1, 0); -+ node->mutex_ret = pthread_mutex_lock(m); - return; - } - -- while (a_swap(&c->_c_lock, 1)) -- __wait(&c->_c_lock, &c->_c_lockwait, 1, 1); -+ int oldstate = a_cas(&node->state, WAITING, LEAVING); -+ -+ if (oldstate == WAITING) { -+ /* Access to cv object is valid because this waiter was not -+ * yet signaled and a new signal/broadcast cannot return -+ * after seeing a LEAVING waiter without getting notified -+ * via the futex notify below. */ -+ -+ pthread_cond_t *c = node->cond; -+ lock(&c->_c_lock); -+ -+ if (c->_c_head == node) c->_c_head = node->next; -+ else if (node->prev) node->prev->next = node->next; -+ if (c->_c_tail == node) c->_c_tail = node->prev; -+ else if (node->next) node->next->prev = node->prev; -+ -+ unlock(&c->_c_lock); -+ -+ if (node->notify) { -+ if (a_fetch_add(node->notify, -1)==1) -+ __wake(node->notify, 1, 1); -+ } -+ } else { -+ /* Lock barrier first to control wake order. */ -+ lock(&node->barrier); -+ } - -- if (c->_c_waiters2) c->_c_waiters2--; -- else a_dec(&m->_m_waiters); -+ node->mutex_ret = pthread_mutex_lock(node->mutex); - -- a_store(&c->_c_lock, 0); -- if (c->_c_lockwait) __wake(&c->_c_lock, 1, 1); -+ if (oldstate == WAITING) return; - -- a_dec(&c->_c_waiters); -- if (c->_c_destroy) __wake(&c->_c_waiters, 1, 1); --} -+ if (!node->next) a_inc(&node->mutex->_m_waiters); - --static void cleanup(void *p) --{ -- struct cm *cm = p; -- unwait(cm->c, cm->m); -- pthread_mutex_lock(cm->m); -+ /* Unlock the barrier that's holding back the next waiter, and -+ * either wake it or requeue it to the mutex. */ -+ if (node->prev) { -+ unlock_requeue(&node->prev->barrier, -+ &node->mutex->_m_lock, -+ node->mutex->_m_type & 128); -+ } else { -+ a_dec(&node->mutex->_m_waiters); -+ } - } - - int pthread_cond_timedwait(pthread_cond_t *restrict c, pthread_mutex_t *restrict m, const struct timespec *restrict ts) - { -- struct cm cm = { .c=c, .m=m }; -- int r, e=0, seq; -+ struct waiter node = { .cond = c, .mutex = m }; -+ int e, seq, *fut, clock = c->_c_clock; - -- if (m->_m_type && (m->_m_lock&INT_MAX) != __pthread_self()->tid) -+ if ((m->_m_type&15) && (m->_m_lock&INT_MAX) != __pthread_self()->tid) - return EPERM; - - if (ts && ts->tv_nsec >= 1000000000UL) -@@ -49,28 +132,68 @@ int pthread_cond_timedwait(pthread_cond_t *restrict c, pthread_mutex_t *restrict - - pthread_testcancel(); - -- a_inc(&c->_c_waiters); -- -- if (c->_c_mutex != (void *)-1) { -- c->_c_mutex = m; -- while (a_swap(&c->_c_lock, 1)) -- __wait(&c->_c_lock, &c->_c_lockwait, 1, 1); -- c->_c_waiters2++; -- a_store(&c->_c_lock, 0); -- if (c->_c_lockwait) __wake(&c->_c_lock, 1, 1); -+ if (c->_c_shared) { -+ node.shared = 1; -+ fut = &c->_c_seq; -+ seq = c->_c_seq; -+ a_inc(&c->_c_waiters); -+ } else { -+ lock(&c->_c_lock); -+ -+ seq = node.barrier = 2; -+ fut = &node.barrier; -+ node.state = WAITING; -+ node.next = c->_c_head; -+ c->_c_head = &node; -+ if (!c->_c_tail) c->_c_tail = &node; -+ else node.next->prev = &node; -+ -+ unlock(&c->_c_lock); - } - -- seq = c->_c_seq; -- - pthread_mutex_unlock(m); - -- do e = __timedwait(&c->_c_seq, seq, c->_c_clock, ts, cleanup, &cm, 0); -- while (c->_c_seq == seq && (!e || e==EINTR)); -+ do e = __timedwait(fut, seq, clock, ts, unwait, &node, !node.shared); -+ while (*fut==seq && (!e || e==EINTR)); - if (e == EINTR) e = 0; - -- unwait(c, m); -+ unwait(&node); -+ -+ return node.mutex_ret ? node.mutex_ret : e; -+} -+ -+int __private_cond_signal(pthread_cond_t *c, int n) -+{ -+ struct waiter *p, *first=0; -+ int ref = 0, cur; -+ -+ lock(&c->_c_lock); -+ for (p=c->_c_tail; n && p; p=p->prev) { -+ if (a_cas(&p->state, WAITING, SIGNALED) != WAITING) { -+ ref++; -+ p->notify = &ref; -+ } else { -+ n--; -+ if (!first) first=p; -+ } -+ } -+ /* Split the list, leaving any remainder on the cv. */ -+ if (p) { -+ if (p->next) p->next->prev = 0; -+ p->next = 0; -+ } else { -+ c->_c_head = 0; -+ } -+ c->_c_tail = p; -+ unlock(&c->_c_lock); -+ -+ /* Wait for any waiters in the LEAVING state to remove -+ * themselves from the list before returning or allowing -+ * signaled threads to proceed. */ -+ while ((cur = ref)) __wait(&ref, 0, cur, 1); - -- if ((r=pthread_mutex_lock(m))) return r; -+ /* Allow first signaled waiter, if any, to proceed. */ -+ if (first) unlock(&first->barrier); - -- return e; -+ return 0; - } -diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c -index e77e54a..c8c117b 100644 ---- a/src/thread/pthread_create.c -+++ b/src/thread/pthread_create.c -@@ -10,6 +10,7 @@ static void dummy_0() - weak_alias(dummy_0, __acquire_ptc); - weak_alias(dummy_0, __release_ptc); - weak_alias(dummy_0, __pthread_tsd_run_dtors); -+weak_alias(dummy_0, __do_private_robust_list); - - _Noreturn void pthread_exit(void *result) - { -@@ -63,6 +64,8 @@ _Noreturn void pthread_exit(void *result) - a_dec(&libc.bytelocale_cnt_minus_1); - } - -+ __do_private_robust_list(); -+ - if (self->detached && self->map_base) { - /* Detached threads must avoid the kernel clear_child_tid - * feature, since the virtual address will have been -diff --git a/src/thread/pthread_mutex_consistent.c b/src/thread/pthread_mutex_consistent.c -index 65da29f..96b83b5 100644 ---- a/src/thread/pthread_mutex_consistent.c -+++ b/src/thread/pthread_mutex_consistent.c -@@ -2,9 +2,9 @@ - - int pthread_mutex_consistent(pthread_mutex_t *m) - { -- if (m->_m_type < 8) return EINVAL; -- if ((m->_m_lock & 0x3fffffff) != __pthread_self()->tid) -+ if (!(m->_m_type & 8)) return EINVAL; -+ if ((m->_m_lock & 0x7fffffff) != __pthread_self()->tid) - return EPERM; -- m->_m_type -= 8; -+ m->_m_type &= ~8U; - return 0; - } -diff --git a/src/thread/pthread_mutex_init.c b/src/thread/pthread_mutex_init.c -index 9d85a35..acf45a7 100644 ---- a/src/thread/pthread_mutex_init.c -+++ b/src/thread/pthread_mutex_init.c -@@ -3,6 +3,6 @@ - int pthread_mutex_init(pthread_mutex_t *restrict m, const pthread_mutexattr_t *restrict a) - { - *m = (pthread_mutex_t){0}; -- if (a) m->_m_type = a->__attr & 7; -+ if (a) m->_m_type = a->__attr; - return 0; - } -diff --git a/src/thread/pthread_mutex_lock.c b/src/thread/pthread_mutex_lock.c -index 42b5af6..2a9a3aa 100644 ---- a/src/thread/pthread_mutex_lock.c -+++ b/src/thread/pthread_mutex_lock.c -@@ -2,7 +2,8 @@ - - int pthread_mutex_lock(pthread_mutex_t *m) - { -- if (m->_m_type == PTHREAD_MUTEX_NORMAL && !a_cas(&m->_m_lock, 0, EBUSY)) -+ if ((m->_m_type&15) == PTHREAD_MUTEX_NORMAL -+ && !a_cas(&m->_m_lock, 0, EBUSY)) - return 0; - - return pthread_mutex_timedlock(m, 0); -diff --git a/src/thread/pthread_mutex_timedlock.c b/src/thread/pthread_mutex_timedlock.c -index 7b1afc0..2a959d2 100644 ---- a/src/thread/pthread_mutex_timedlock.c -+++ b/src/thread/pthread_mutex_timedlock.c -@@ -2,21 +2,23 @@ - - int pthread_mutex_timedlock(pthread_mutex_t *restrict m, const struct timespec *restrict at) - { -- int r, t; -- -- if (m->_m_type == PTHREAD_MUTEX_NORMAL && !a_cas(&m->_m_lock, 0, EBUSY)) -+ if ((m->_m_type&15) == PTHREAD_MUTEX_NORMAL -+ && !a_cas(&m->_m_lock, 0, EBUSY)) - return 0; - -+ int r, t, priv = (m->_m_type & 128) ^ 128; -+ - while ((r=pthread_mutex_trylock(m)) == EBUSY) { -- if (!(r=m->_m_lock) || (r&0x40000000)) continue; -+ if (!(r=m->_m_lock) || ((r&0x40000000) && (m->_m_type&4))) -+ continue; - if ((m->_m_type&3) == PTHREAD_MUTEX_ERRORCHECK -- && (r&0x1fffffff) == __pthread_self()->tid) -+ && (r&0x7fffffff) == __pthread_self()->tid) - return EDEADLK; - - a_inc(&m->_m_waiters); - t = r | 0x80000000; - a_cas(&m->_m_lock, r, t); -- r = __timedwait(&m->_m_lock, t, CLOCK_REALTIME, at, 0, 0, 0); -+ r = __timedwait(&m->_m_lock, t, CLOCK_REALTIME, at, 0, 0, priv); - a_dec(&m->_m_waiters); - if (r && r != EINTR) break; - } -diff --git a/src/thread/pthread_mutex_trylock.c b/src/thread/pthread_mutex_trylock.c -index 00ad65d..e851517 100644 ---- a/src/thread/pthread_mutex_trylock.c -+++ b/src/thread/pthread_mutex_trylock.c -@@ -1,52 +1,58 @@ - #include "pthread_impl.h" - --int pthread_mutex_trylock(pthread_mutex_t *m) -+int __pthread_mutex_trylock_owner(pthread_mutex_t *m) - { -- int tid, old, own; -- pthread_t self; -- -- if (m->_m_type == PTHREAD_MUTEX_NORMAL) -- return a_cas(&m->_m_lock, 0, EBUSY) & EBUSY; -- -- self = __pthread_self(); -- tid = self->tid; -- -- if (m->_m_type >= 4) { -- if (!self->robust_list.off) -- __syscall(SYS_set_robust_list, -- &self->robust_list, 3*sizeof(long)); -+ int old, own; -+ int type = m->_m_type & 15; -+ pthread_t self = __pthread_self(); -+ int tid = self->tid; -+ -+ if (!self->robust_list.off) { -+ __syscall(SYS_set_robust_list, &self->robust_list, 3*sizeof(long)); -+ self->robust_list.head = &self->robust_list.head; - self->robust_list.off = (char*)&m->_m_lock-(char *)&m->_m_next; -- self->robust_list.pending = &m->_m_next; - } - - old = m->_m_lock; - own = old & 0x7fffffff; -- if (own == tid && (m->_m_type&3) == PTHREAD_MUTEX_RECURSIVE) { -+ if (own == tid && (type&3) == PTHREAD_MUTEX_RECURSIVE) { - if ((unsigned)m->_m_count >= INT_MAX) return EAGAIN; - m->_m_count++; - return 0; - } -+ if (own == 0x40000000) return ENOTRECOVERABLE; - -- if ((own && !(own & 0x40000000)) || a_cas(&m->_m_lock, old, tid)!=old) -- return EBUSY; -- -- if (m->_m_type < 4) return 0; -+ if (m->_m_type & 128) { -+ if (m->_m_waiters) tid |= 0x80000000; -+ self->robust_list.pending = &m->_m_next; -+ } - -- if (m->_m_type >= 8) { -- m->_m_lock = 0; -- return ENOTRECOVERABLE; -+ if ((own && (!(own & 0x40000000) || !(type & 4))) -+ || a_cas(&m->_m_lock, old, tid) != old) { -+ self->robust_list.pending = 0; -+ return EBUSY; - } -- m->_m_next = self->robust_list.head; -+ -+ volatile void *next = self->robust_list.head; -+ m->_m_next = next; - m->_m_prev = &self->robust_list.head; -- if (self->robust_list.head) -- self->robust_list.head[-1] = &m->_m_next; -+ if (next != &self->robust_list.head) *(volatile void *volatile *) -+ ((char *)next - sizeof(void *)) = &m->_m_next; - self->robust_list.head = &m->_m_next; - self->robust_list.pending = 0; -+ - if (own) { - m->_m_count = 0; -- m->_m_type += 8; -+ m->_m_type |= 8; - return EOWNERDEAD; - } - - return 0; - } -+ -+int pthread_mutex_trylock(pthread_mutex_t *m) -+{ -+ if ((m->_m_type&15) == PTHREAD_MUTEX_NORMAL) -+ return a_cas(&m->_m_lock, 0, EBUSY) & EBUSY; -+ return __pthread_mutex_trylock_owner(m); -+} -diff --git a/src/thread/pthread_mutex_unlock.c b/src/thread/pthread_mutex_unlock.c -index b4bd74b..46761d9 100644 ---- a/src/thread/pthread_mutex_unlock.c -+++ b/src/thread/pthread_mutex_unlock.c -@@ -8,30 +8,31 @@ int pthread_mutex_unlock(pthread_mutex_t *m) - pthread_t self; - int waiters = m->_m_waiters; - int cont; -- int robust = 0; -+ int type = m->_m_type & 15; -+ int priv = (m->_m_type & 128) ^ 128; - -- if (m->_m_type != PTHREAD_MUTEX_NORMAL) { -- if (!m->_m_lock) -- return EPERM; -+ if (type != PTHREAD_MUTEX_NORMAL) { - self = __pthread_self(); -- if ((m->_m_lock&0x1fffffff) != self->tid) -+ if ((m->_m_lock&0x7fffffff) != self->tid) - return EPERM; -- if ((m->_m_type&3) == PTHREAD_MUTEX_RECURSIVE && m->_m_count) -+ if ((type&3) == PTHREAD_MUTEX_RECURSIVE && m->_m_count) - return m->_m_count--, 0; -- if (m->_m_type >= 4) { -- robust = 1; -+ if (!priv) { - self->robust_list.pending = &m->_m_next; -- *(void **)m->_m_prev = m->_m_next; -- if (m->_m_next) ((void **)m->_m_next)[-1] = m->_m_prev; - __vm_lock_impl(+1); - } -+ volatile void *prev = m->_m_prev; -+ volatile void *next = m->_m_next; -+ *(volatile void *volatile *)prev = next; -+ if (next != &self->robust_list.head) *(volatile void *volatile *) -+ ((char *)next - sizeof(void *)) = prev; - } -- cont = a_swap(&m->_m_lock, 0); -- if (robust) { -+ cont = a_swap(&m->_m_lock, (type & 8) ? 0x40000000 : 0); -+ if (type != PTHREAD_MUTEX_NORMAL && !priv) { - self->robust_list.pending = 0; - __vm_unlock_impl(); - } - if (waiters || cont<0) -- __wake(&m->_m_lock, 1, 0); -+ __wake(&m->_m_lock, 1, priv); - return 0; - } -diff --git a/src/thread/pthread_mutexattr_setpshared.c b/src/thread/pthread_mutexattr_setpshared.c -index 8c7a1e2..100f6ff 100644 ---- a/src/thread/pthread_mutexattr_setpshared.c -+++ b/src/thread/pthread_mutexattr_setpshared.c -@@ -3,7 +3,7 @@ - int pthread_mutexattr_setpshared(pthread_mutexattr_t *a, int pshared) - { - if (pshared > 1U) return EINVAL; -- a->__attr &= 0x7fffffff; -- a->__attr |= pshared<<31; -+ a->__attr &= ~128U; -+ a->__attr |= pshared<<7; - return 0; - } -diff --git a/src/thread/pthread_mutexattr_setrobust.c b/src/thread/pthread_mutexattr_setrobust.c -index dcfa4cf..d062788 100644 ---- a/src/thread/pthread_mutexattr_setrobust.c -+++ b/src/thread/pthread_mutexattr_setrobust.c -@@ -1,4 +1,28 @@ - #include "pthread_impl.h" -+#include <stddef.h> -+ -+void __do_private_robust_list() -+{ -+ pthread_t self = __pthread_self(); -+ volatile void *volatile *p; -+ volatile void *volatile *prev; -+ volatile void *volatile *next; -+ pthread_mutex_t *m; -+ -+ prev = &self->robust_list.head; -+ for (p=self->robust_list.head; p&&p!=&self->robust_list.head; p=next) { -+ next = *p; -+ m = (void *)((char *)p - offsetof(pthread_mutex_t, _m_next)); -+ if (!(m->_m_type & 128)) { -+ int waiters = m->_m_waiters; -+ *prev = next; -+ int cont = a_swap(&m->_m_lock, self->tid|0x40000000); -+ if (cont < 0 || waiters) __wake(&m->_m_lock, 1, 1); -+ } else { -+ prev = p; -+ } -+ } -+} - - int pthread_mutexattr_setrobust(pthread_mutexattr_t *a, int robust) - { -diff --git a/src/thread/pthread_once.c b/src/thread/pthread_once.c -index e01f6d4..2eb0f93 100644 ---- a/src/thread/pthread_once.c -+++ b/src/thread/pthread_once.c -@@ -3,7 +3,7 @@ - static void undo(void *control) - { - a_store(control, 0); -- __wake(control, 1, 0); -+ __wake(control, 1, 1); - } - - int pthread_once(pthread_once_t *control, void (*init)(void)) -@@ -25,10 +25,10 @@ int pthread_once(pthread_once_t *control, void (*init)(void)) - pthread_cleanup_pop(0); - - a_store(control, 2); -- if (waiters) __wake(control, -1, 0); -+ if (waiters) __wake(control, -1, 1); - return 0; - case 1: -- __wait(control, &waiters, 1, 0); -+ __wait(control, &waiters, 1, 1); - continue; - case 2: - return 0; -diff --git a/src/thread/pthread_rwlock_init.c b/src/thread/pthread_rwlock_init.c -index 82df52e..a2c0b47 100644 ---- a/src/thread/pthread_rwlock_init.c -+++ b/src/thread/pthread_rwlock_init.c -@@ -3,7 +3,6 @@ - int pthread_rwlock_init(pthread_rwlock_t *restrict rw, const pthread_rwlockattr_t *restrict a) - { - *rw = (pthread_rwlock_t){0}; -- if (a) { -- } -+ if (a) rw->_rw_shared = a->__attr[0]*128; - return 0; - } -diff --git a/src/thread/pthread_rwlock_timedrdlock.c b/src/thread/pthread_rwlock_timedrdlock.c -index c0c94c9..a2b4d44 100644 ---- a/src/thread/pthread_rwlock_timedrdlock.c -+++ b/src/thread/pthread_rwlock_timedrdlock.c -@@ -8,7 +8,7 @@ int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rw, const struct times - t = r | 0x80000000; - a_inc(&rw->_rw_waiters); - a_cas(&rw->_rw_lock, r, t); -- r = __timedwait(&rw->_rw_lock, t, CLOCK_REALTIME, at, 0, 0, 0); -+ r = __timedwait(&rw->_rw_lock, t, CLOCK_REALTIME, at, 0, 0, rw->_rw_shared^128); - a_dec(&rw->_rw_waiters); - if (r && r != EINTR) return r; - } -diff --git a/src/thread/pthread_rwlock_timedwrlock.c b/src/thread/pthread_rwlock_timedwrlock.c -index 339a167..63a32ec 100644 ---- a/src/thread/pthread_rwlock_timedwrlock.c -+++ b/src/thread/pthread_rwlock_timedwrlock.c -@@ -8,7 +8,7 @@ int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rw, const struct times - t = r | 0x80000000; - a_inc(&rw->_rw_waiters); - a_cas(&rw->_rw_lock, r, t); -- r = __timedwait(&rw->_rw_lock, t, CLOCK_REALTIME, at, 0, 0, 0); -+ r = __timedwait(&rw->_rw_lock, t, CLOCK_REALTIME, at, 0, 0, rw->_rw_shared^128); - a_dec(&rw->_rw_waiters); - if (r && r != EINTR) return r; - } -diff --git a/src/thread/pthread_rwlock_unlock.c b/src/thread/pthread_rwlock_unlock.c -index a6d2085..7b5eec8 100644 ---- a/src/thread/pthread_rwlock_unlock.c -+++ b/src/thread/pthread_rwlock_unlock.c -@@ -2,7 +2,7 @@ - - int pthread_rwlock_unlock(pthread_rwlock_t *rw) - { -- int val, cnt, waiters, new; -+ int val, cnt, waiters, new, priv = rw->_rw_shared^128; - - do { - val = rw->_rw_lock; -@@ -12,7 +12,7 @@ int pthread_rwlock_unlock(pthread_rwlock_t *rw) - } while (a_cas(&rw->_rw_lock, val, new) != val); - - if (!new && (waiters || val<0)) -- __wake(&rw->_rw_lock, cnt, 0); -+ __wake(&rw->_rw_lock, cnt, priv); - - return 0; - } -diff --git a/src/thread/sem_init.c b/src/thread/sem_init.c -index e8e419c..5509243 100644 ---- a/src/thread/sem_init.c -+++ b/src/thread/sem_init.c -@@ -10,5 +10,6 @@ int sem_init(sem_t *sem, int pshared, unsigned value) - } - sem->__val[0] = value; - sem->__val[1] = 0; -+ sem->__val[2] = pshared ? 0 : 128; - return 0; - } -diff --git a/src/thread/sem_post.c b/src/thread/sem_post.c -index 14a2dfe..31e3293 100644 ---- a/src/thread/sem_post.c -+++ b/src/thread/sem_post.c -@@ -3,7 +3,7 @@ - - int sem_post(sem_t *sem) - { -- int val, waiters; -+ int val, waiters, priv = sem->__val[2]; - do { - val = sem->__val[0]; - waiters = sem->__val[1]; -@@ -12,6 +12,6 @@ int sem_post(sem_t *sem) - return -1; - } - } while (a_cas(sem->__val, val, val+1+(val<0)) != val); -- if (val<0 || waiters) __wake(sem->__val, 1, 0); -+ if (val<0 || waiters) __wake(sem->__val, 1, priv); - return 0; - } -diff --git a/src/thread/sem_timedwait.c b/src/thread/sem_timedwait.c -index 6d0d011..bfcb6dc 100644 ---- a/src/thread/sem_timedwait.c -+++ b/src/thread/sem_timedwait.c -@@ -12,7 +12,7 @@ int sem_timedwait(sem_t *restrict sem, const struct timespec *restrict at) - int r; - a_inc(sem->__val+1); - a_cas(sem->__val, 0, -1); -- r = __timedwait(sem->__val, -1, CLOCK_REALTIME, at, cleanup, sem->__val+1, 0); -+ r = __timedwait(sem->__val, -1, CLOCK_REALTIME, at, cleanup, sem->__val+1, sem->__val[2]); - a_dec(sem->__val+1); - if (r) { - errno = r; |