diff options
Diffstat (limited to 'src/thread')
-rw-r--r-- | src/thread/pthread_attr_get.c | 2 | ||||
-rw-r--r-- | src/thread/pthread_cond_timedwait.c | 2 | ||||
-rw-r--r-- | src/thread/pthread_create.c | 25 | ||||
-rw-r--r-- | src/thread/pthread_mutex_destroy.c | 6 | ||||
-rw-r--r-- | src/thread/s390x/clone.s | 6 | ||||
-rw-r--r-- | src/thread/s390x/syscall_cp.s | 2 | ||||
-rw-r--r-- | src/thread/sem_open.c | 7 | ||||
-rw-r--r-- | src/thread/vmlock.c | 2 |
8 files changed, 40 insertions, 12 deletions
diff --git a/src/thread/pthread_attr_get.c b/src/thread/pthread_attr_get.c index 4aa5afdb..f12ff442 100644 --- a/src/thread/pthread_attr_get.c +++ b/src/thread/pthread_attr_get.c @@ -70,7 +70,7 @@ int pthread_condattr_getpshared(const pthread_condattr_t *restrict a, int *restr int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *restrict a, int *restrict protocol) { - *protocol = PTHREAD_PRIO_NONE; + *protocol = a->__attr / 8U % 2; return 0; } int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict a, int *restrict pshared) diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c index a0cd4904..6b761455 100644 --- a/src/thread/pthread_cond_timedwait.c +++ b/src/thread/pthread_cond_timedwait.c @@ -155,7 +155,7 @@ relock: int val = m->_m_lock; if (val>0) a_cas(&m->_m_lock, val, val|0x80000000); unlock_requeue(&node.prev->barrier, &m->_m_lock, m->_m_type & (8|128)); - } else if (!!(m->_m_type & 8)) { + } else if (!(m->_m_type & 8)) { a_dec(&m->_m_waiters); } diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index 55744155..6f187ee8 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -69,12 +69,25 @@ _Noreturn void __pthread_exit(void *result) __pthread_tsd_run_dtors(); + __block_app_sigs(&set); + + /* This atomic potentially competes with a concurrent pthread_detach + * call; the loser is responsible for freeing thread resources. */ + int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING); + + if (state==DT_DETACHED && self->map_base) { + /* Since __unmapself bypasses the normal munmap code path, + * explicitly wait for vmlock holders first. This must be + * done before any locks are taken, to avoid lock ordering + * issues that could lead to deadlock. */ + __vm_wait(); + } + /* Access to target the exiting thread with syscalls that use * its kernel tid is controlled by killlock. For detached threads, * any use past this point would have undefined behavior, but for * joinable threads it's a valid usage that must be handled. * Signals must be blocked since pthread_kill must be AS-safe. */ - __block_app_sigs(&set); LOCK(self->killlock); /* The thread list lock must be AS-safe, and thus depends on @@ -87,6 +100,7 @@ _Noreturn void __pthread_exit(void *result) if (self->next == self) { __tl_unlock(); UNLOCK(self->killlock); + self->detach_state = state; __restore_sigs(&set); exit(0); } @@ -125,10 +139,6 @@ _Noreturn void __pthread_exit(void *result) self->prev->next = self->next; self->prev = self->next = self; - /* This atomic potentially competes with a concurrent pthread_detach - * call; the loser is responsible for freeing thread resources. */ - int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING); - if (state==DT_DETACHED && self->map_base) { /* Detached threads must block even implementation-internal * signals, since they will not have a stack in their last @@ -140,16 +150,13 @@ _Noreturn void __pthread_exit(void *result) if (self->robust_list.off) __syscall(SYS_set_robust_list, 0, 3*sizeof(long)); - /* Since __unmapself bypasses the normal munmap code path, - * explicitly wait for vmlock holders first. */ - __vm_wait(); - /* The following call unmaps the thread's stack mapping * and then exits without touching the stack. */ __unmapself(self->map_base, self->map_size); } /* Wake any joiner. */ + a_store(&self->detach_state, DT_EXITED); __wake(&self->detach_state, 1, 1); /* After the kernel thread exits, its tid may be reused. Clear it diff --git a/src/thread/pthread_mutex_destroy.c b/src/thread/pthread_mutex_destroy.c index 6d49e689..8d1bf77b 100644 --- a/src/thread/pthread_mutex_destroy.c +++ b/src/thread/pthread_mutex_destroy.c @@ -1,6 +1,10 @@ -#include <pthread.h> +#include "pthread_impl.h" int pthread_mutex_destroy(pthread_mutex_t *mutex) { + /* If the mutex being destroyed is process-shared and has nontrivial + * type (tracking ownership), it might be in the pending slot of a + * robust_list; wait for quiescence. */ + if (mutex->_m_type > 128) __vm_wait(); return 0; } diff --git a/src/thread/s390x/clone.s b/src/thread/s390x/clone.s index 577748ea..2125f20b 100644 --- a/src/thread/s390x/clone.s +++ b/src/thread/s390x/clone.s @@ -17,6 +17,9 @@ __clone: # if (!tid) syscall(SYS_exit, a(d)); # return tid; + # preserve call-saved register used as syscall arg + stg %r6, 48(%r15) + # create initial stack frame for new thread nill %r3, 0xfff8 aghi %r3, -160 @@ -35,6 +38,9 @@ __clone: lg %r6, 160(%r15) svc 120 + # restore call-saved register + lg %r6, 48(%r15) + # if error or if we're the parent, return ltgr %r2, %r2 bnzr %r14 diff --git a/src/thread/s390x/syscall_cp.s b/src/thread/s390x/syscall_cp.s index c1da40de..d094cbf5 100644 --- a/src/thread/s390x/syscall_cp.s +++ b/src/thread/s390x/syscall_cp.s @@ -14,6 +14,7 @@ __cp_begin: icm %r2, 15, 0(%r2) jne __cp_cancel + stg %r6, 48(%r15) stg %r7, 56(%r15) lgr %r1, %r3 lgr %r2, %r4 @@ -26,6 +27,7 @@ __cp_begin: __cp_end: lg %r7, 56(%r15) + lg %r6, 48(%r15) br %r14 __cp_cancel: diff --git a/src/thread/sem_open.c b/src/thread/sem_open.c index 6fb0c5b2..0ad29de9 100644 --- a/src/thread/sem_open.c +++ b/src/thread/sem_open.c @@ -12,6 +12,12 @@ #include <stdlib.h> #include <pthread.h> #include "lock.h" +#include "fork_impl.h" + +#define malloc __libc_malloc +#define calloc __libc_calloc +#define realloc undef +#define free undef static struct { ino_t ino; @@ -19,6 +25,7 @@ static struct { int refcnt; } *semtab; static volatile int lock[1]; +volatile int *const __sem_open_lockptr = lock; #define FLAGS (O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NONBLOCK) diff --git a/src/thread/vmlock.c b/src/thread/vmlock.c index 75f3cb76..fa0a8e3c 100644 --- a/src/thread/vmlock.c +++ b/src/thread/vmlock.c @@ -1,6 +1,8 @@ #include "pthread_impl.h" +#include "fork_impl.h" static volatile int vmlock[2]; +volatile int *const __vmlock_lockptr = vmlock; void __vm_wait() { |