Rewrite recursive mutex code

This commit is contained in:
Justine Tunney 2022-09-10 09:14:40 -07:00
parent bae7367774
commit cfcf5918bc
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
27 changed files with 164 additions and 257 deletions

View file

@ -18,7 +18,6 @@
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/futex.internal.h"
@ -31,35 +30,34 @@
* @raises EPERM if in error check mode and not owned by caller
*/
int pthread_mutex_unlock(pthread_mutex_t *mutex) {
int c, me, owner;
switch (mutex->type) {
case PTHREAD_MUTEX_NORMAL:
// From Futexes Are Tricky Version 1.1 § Mutex, Take 3;
// Ulrich Drepper, Red Hat Incorporated, June 27, 2004.
if ((c = atomic_fetch_sub_explicit(&mutex->lock, 1,
memory_order_release)) != 1) {
atomic_store_explicit(&mutex->lock, 0, memory_order_release);
_futex_wake(&mutex->lock, 1, mutex->pshared);
}
return 0;
case PTHREAD_MUTEX_ERRORCHECK:
me = gettid();
owner = atomic_load_explicit(&mutex->lock, memory_order_relaxed);
if (owner != me) {
assert(!"permlock");
return EPERM;
}
// fallthrough
case PTHREAD_MUTEX_RECURSIVE:
if (--mutex->reent) return 0;
atomic_store_explicit(&mutex->lock, 0, memory_order_relaxed);
if ((IsLinux() || IsOpenbsd()) &&
atomic_load_explicit(&mutex->waits, memory_order_relaxed) > 0) {
return _futex_wake(&mutex->lock, 1, mutex->pshared);
}
return 0;
default:
assert(!"badlock");
return EINVAL;
int c, t;
if (mutex->type == PTHREAD_MUTEX_NORMAL) {
// From Futexes Are Tricky Version 1.1 § Mutex, Take 3;
// Ulrich Drepper, Red Hat Incorporated, June 27, 2004.
if ((c = atomic_fetch_sub(&mutex->lock, 1)) != 1) {
atomic_store_explicit(&mutex->lock, 0, memory_order_release);
_futex_wake(&mutex->lock, 1, mutex->pshared);
}
return 0;
}
t = gettid();
if (mutex->type == PTHREAD_MUTEX_ERRORCHECK) {
c = atomic_load_explicit(&mutex->lock, memory_order_relaxed);
if ((c & 0x000fffff) != t) {
assert(!"permlock");
return EPERM;
}
}
c = atomic_fetch_sub(&mutex->lock, 0x00100000);
if ((c & 0x0ff00000) == 0x00100000) {
atomic_store_explicit(&mutex->lock, 0, memory_order_release);
if ((c & 0xf0000000) == 0x20000000) {
_futex_wake(&mutex->lock, 1, mutex->pshared);
}
}
return 0;
}