Add futexes for OpenBSD

This commit is contained in:
Justine Tunney 2022-06-21 05:11:51 -07:00
parent 1216b6e7c7
commit b8e9f71d33
4 changed files with 46 additions and 8 deletions

View file

@ -121,7 +121,7 @@ int pthread_rwlock_unlock(pthread_rwlock_t *);
#define pthread_mutex_unlock(mutex) \ #define pthread_mutex_unlock(mutex) \
((mutex)->attr == PTHREAD_MUTEX_NORMAL \ ((mutex)->attr == PTHREAD_MUTEX_NORMAL \
? (atomic_store_explicit(&(mutex)->lock, 0, memory_order_relaxed), \ ? (atomic_store_explicit(&(mutex)->lock, 0, memory_order_relaxed), \
(IsLinux() && \ ((IsLinux() || IsOpenbsd()) && \
atomic_load_explicit(&(mutex)->waits, memory_order_relaxed) && \ atomic_load_explicit(&(mutex)->waits, memory_order_relaxed) && \
_pthread_mutex_wake(mutex)), \ _pthread_mutex_wake(mutex)), \
0) \ 0) \

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/asmflag.h"
#include "libc/bits/atomic.h" #include "libc/bits/atomic.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/dce.h" #include "libc/dce.h"
@ -24,16 +25,41 @@
#include "libc/intrin/spinlock.h" #include "libc/intrin/spinlock.h"
#include "libc/linux/futex.h" #include "libc/linux/futex.h"
#include "libc/nexgen32e/threaded.h" #include "libc/nexgen32e/threaded.h"
#include "libc/sysv/consts/futex.h"
#include "libc/sysv/consts/nr.h"
static inline int FutexWait(void *addr, int expect, struct timespec *timeout) {
int ax;
bool cf;
asm volatile(CFLAG_ASM("mov\t%6,%%r10\n\t"
"clc\n\t"
"syscall")
: CFLAG_CONSTRAINT(cf), "=a"(ax)
: "1"(__NR_futex), "D"(addr), "S"(FUTEX_WAIT), "d"(expect),
"g"(timeout)
: "rcx", "r10", "r11", "memory");
if (cf) ax = -ax;
return ax;
}
static int pthread_mutex_lock_spin(pthread_mutex_t *mutex, int tries) { static int pthread_mutex_lock_spin(pthread_mutex_t *mutex, int tries) {
volatile int i; volatile int i;
struct timespec ts;
if (tries < 7) { if (tries < 7) {
for (i = 0; i != 1 << tries; i++) { for (i = 0; i != 1 << tries; i++) {
} }
tries++; tries++;
} else if (IsLinux()) { } else if (IsLinux() || IsOpenbsd()) {
atomic_fetch_add(&mutex->waits, 1); atomic_fetch_add(&mutex->waits, 1);
LinuxFutexWait(&mutex->lock, 1, 0); if (tries < 28) {
ts.tv_sec = 0;
ts.tv_nsec = 4 << tries;
tries++;
} else {
ts.tv_sec = 1;
ts.tv_nsec = 0;
}
FutexWait(&mutex->lock, 1, &ts);
atomic_fetch_sub(&mutex->waits, 1); atomic_fetch_sub(&mutex->waits, 1);
} else { } else {
sched_yield(); sched_yield();

View file

@ -40,7 +40,7 @@ int(pthread_mutex_unlock)(pthread_mutex_t *mutex) {
// fallthrough // fallthrough
case PTHREAD_MUTEX_NORMAL: case PTHREAD_MUTEX_NORMAL:
atomic_store_explicit(&mutex->lock, 0, memory_order_relaxed); atomic_store_explicit(&mutex->lock, 0, memory_order_relaxed);
if (IsLinux() && if ((IsLinux() || IsOpenbsd()) &&
atomic_load_explicit(&mutex->waits, memory_order_relaxed)) { atomic_load_explicit(&mutex->waits, memory_order_relaxed)) {
_pthread_mutex_wake(mutex); _pthread_mutex_wake(mutex);
} }

View file

@ -16,11 +16,23 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/atomic.h" #include "libc/bits/asmflag.h"
#include "libc/dce.h"
#include "libc/intrin/pthread.h" #include "libc/intrin/pthread.h"
#include "libc/linux/futex.h" #include "libc/sysv/consts/futex.h"
#include "libc/sysv/consts/nr.h"
static inline int FutexWake(void *addr, int count) {
int ax;
bool cf;
asm volatile(CFLAG_ASM("clc\n\t"
"syscall")
: CFLAG_CONSTRAINT(cf), "=a"(ax)
: "1"(__NR_futex), "D"(addr), "S"(FUTEX_WAKE), "d"(count)
: "rcx", "r11", "memory");
if (cf) ax = -ax;
return ax;
}
int _pthread_mutex_wake(pthread_mutex_t *mutex) { int _pthread_mutex_wake(pthread_mutex_t *mutex) {
return LinuxFutexWake(&mutex->lock, 1); return FutexWake(&mutex->lock, 1);
} }