Make futexes cancellable by pthreads

This commit is contained in:
Justine Tunney 2022-11-04 18:19:05 -07:00
parent 2278327eba
commit 022536cab6
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
101 changed files with 627 additions and 391 deletions

View file

@ -32,36 +32,29 @@
* @returnserrno
* @threadsafe
*/
int pthread_detach(pthread_t thread) {
errno_t pthread_detach(pthread_t thread) {
struct PosixThread *pt;
enum PosixThreadStatus status;
if (!(pt = (struct PosixThread *)thread)) {
return EINVAL;
}
enum PosixThreadStatus status, transition;
if (!(pt = (struct PosixThread *)thread)) return EINVAL;
for (;;) {
status = atomic_load_explicit(&pt->status, memory_order_acquire);
if (status == kPosixThreadDetached || status == kPosixThreadZombie) {
// these two states indicate the thread was already detached, in
// which case it's already listed under _pthread_zombies.
return EINVAL;
} else if (status == kPosixThreadTerminated) {
// thread was joinable and finished running. since pthread_join
// won't be called, it's safe to free the thread resources now.
// POSIX says this could be reported as ESRCH but then our test
// code would be less elegant in order for it to avoid flaking.
_pthread_wait(pt);
_pthread_free(pt);
break;
} else if (status == kPosixThreadJoinable) {
if (atomic_compare_exchange_weak_explicit(
&pt->status, &status, kPosixThreadDetached, memory_order_release,
memory_order_relaxed)) {
_pthread_zombies_add(pt);
break;
}
transition = kPosixThreadDetached;
} else if (status == kPosixThreadTerminated) {
transition = kPosixThreadZombie;
} else {
notpossible;
}
if (atomic_compare_exchange_weak_explicit(&pt->status, &status, transition,
memory_order_release,
memory_order_relaxed)) {
_pthread_zombies_add(pt);
break;
}
}
return 0;
}