Support futexes on FreeBSD

This commit is contained in:
Justine Tunney 2022-10-02 11:56:27 -07:00
parent 795d295590
commit 7549a5755e
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
10 changed files with 81 additions and 31 deletions

View file

@ -112,7 +112,7 @@ WinThreadEntry(int rdi, // rcx
// since we didn't indirect this function through NT2SYSV() it's not
// safe to simply return, and as such, we just call ExitThread().
__imp_ExitThread(rc);
unreachable;
notpossible;
}
static textwindows int CloneWindows(int (*func)(void *, int), char *stk,
@ -192,7 +192,7 @@ XnuThreadMain(void *pthread, // rdi
: "=m"(*wt->ztid)
: "a"(0x2000000 | 361), "D"(0), "S"(0), "d"(0)
: "rcx", "r10", "r11", "memory");
unreachable;
notpossible;
}
static int CloneXnu(int (*fn)(void *), char *stk, size_t stksz, int flags,
@ -239,12 +239,15 @@ static wontreturn void FreebsdThreadMain(void *p) {
wt->func(wt->arg, wt->tid);
// we no longer use the stack after this point
// void thr_exit(%rdi = long *state);
asm volatile("movl\t$0,%0\n\t" // *wt->ztid = 0
"syscall" // thr_exit()
asm volatile("movl\t$0,%0\n\t" // *wt->ztid = 0
"syscall\n\t" // _umtx_op()
"movl\t$431,%%eax\n\t" // thr_exit()
"xor\t%%edi,%%edi\n\t"
"syscall"
: "=m"(*wt->ztid)
: "a"(431), "D"(0)
: "rcx", "r11", "memory");
unreachable;
: "a"(454), "D"(wt->ztid), "S"(UMTX_OP_WAKE)
: "rcx", "r8", "r9", "r10", "r11", "memory");
notpossible;
}
static int CloneFreebsd(int (*func)(void *, int), char *stk, size_t stksz,
@ -318,7 +321,7 @@ noasan static wontreturn void OpenbsdThreadMain(void *p) {
: "a"(83), "m"(oldrsp), "D"(wt->ztid), "S"(FUTEX_WAKE),
"d"(INT_MAX)
: "rcx", "r11", "memory");
unreachable;
notpossible;
}
static int CloneOpenbsd(int (*func)(void *, int), char *stk, size_t stksz,
@ -372,7 +375,7 @@ static wontreturn void NetbsdThreadMain(void *arg, // rdi
: "=a"(ax), "=d"(dx), "=m"(*ztid)
: "0"(310)
: "rcx", "r11", "memory");
unreachable;
notpossible;
}
static int CloneNetbsd(int (*func)(void *, int), char *stk, size_t stksz,

View file

@ -0,0 +1,2 @@
.include "o/libc/sysv/macros.internal.inc"
.scall sys_umtx_op,0xffffff1c6fffffff,globl

View file

@ -1316,9 +1316,9 @@ syscon rusage RUSAGE_BOTH -2 99 99 99 99 99 # woop
#
# group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary
syscon futex FUTEX_WAIT 0 0 0 1 0 0
syscon futex FUTEX_WAKE 1 0 0 2 0 1
syscon futex FUTEX_WAKE 1 0 1 2 0 1
syscon futex FUTEX_REQUEUE 3 0 0 3 0 0
syscon futex FUTEX_PRIVATE_FLAG 128 0 0 128 0 0
syscon futex FUTEX_PRIVATE_FLAG 128 0 128 128 0 0
# lio_listio() magnums
#

View file

@ -1,2 +1,2 @@
.include "o/libc/sysv/consts/syscon.internal.inc"
.syscon futex,FUTEX_PRIVATE_FLAG,128,0,0,128,0,0
.syscon futex,FUTEX_PRIVATE_FLAG,128,0,128,128,0,0

View file

@ -1,2 +1,2 @@
.include "o/libc/sysv/consts/syscon.internal.inc"
.syscon futex,FUTEX_WAKE,1,0,0,2,0,1
.syscon futex,FUTEX_WAKE,1,0,1,2,0,1

View file

@ -18,6 +18,7 @@
╚────────────────────────────────────────────────────────────────'>/dev/null #*/
dir=libc/sysv/calls
. libc/sysv/gen.sh
#include "libc/calls/syscall-sysv.internal.h"
# The Fifth Bell System Interface, Community Edition ┌─────────────────────────┐
# » so many numbers │ legend │
@ -641,7 +642,7 @@ scall sys_bsdthread_register 0xfffffffff216efff globl hidden
#scall write_nocancel 0xfffffffff218dfff globl
#scall writev_nocancel 0xfffffffff219cfff globl
#──────────────────────────FREEBSD───────────────────────────
#scall _umtx_op 0xffffff1c6fffffff globl
scall sys_umtx_op 0xffffff1c6fffffff globl
#scall abort2 0xffffff1cffffffff globl
#scall afs3_syscall 0xffffff179fffffff globl
#scall bindat 0xffffff21afffffff globl

View file

@ -1,8 +1,8 @@
#ifndef COSMOPOLITAN_LIBC_THREAD_FREEBSD_INTERNAL_H_
#define COSMOPOLITAN_LIBC_THREAD_FREEBSD_INTERNAL_H_
#include "libc/intrin/asmflag.h"
#include "libc/calls/struct/timespec.h"
#include "libc/errno.h"
#include "libc/intrin/asmflag.h"
/**
* @fileoverview FreeBSD Threading
@ -11,9 +11,12 @@
* maximum legal range is PID_MAX + 2 (100001) through INT_MAX
*/
#define UMTX_OP_MUTEX_WAIT 17
#define UMTX_OP_MUTEX_WAKE 18
#define UMTX_ABSTIME 1
#define UMTX_OP_WAIT 2
#define UMTX_OP_WAIT_UINT 11
#define UMTX_OP_WAIT_UINT_PRIVATE 15
#define UMTX_OP_WAKE 3
#define UMTX_OP_WAKE_PRIVATE 16
#define UMTX_ABSTIME 1
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@ -42,7 +45,7 @@ struct _umtx_time {
uint32_t _clockid;
};
int _umtx_op(void *, int, unsigned long, void *, void *);
int sys_umtx_op(void *, int, unsigned long, void *, void *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -27,14 +27,14 @@
* Waits for condition with optional time limit, e.g.
*
* struct timespec ts; // one second timeout
* ts = _timespec_add(_timespec_mono(), _timespec_frommillis(1000));
* ts = _timespec_add(_timespec_real(), _timespec_frommillis(1000));
* if (pthread_cond_timedwait(cond, mutex, &ts) == ETIMEDOUT) {
* // handle timeout...
* }
*
* @param mutex needs to be held by thread when calling this function
* @param abstime may be null to wait indefinitely and should contain
* some arbitrary interval added to a `CLOCK_MONOTONIC` timestamp
* some arbitrary interval added to a `CLOCK_REALTIME` timestamp
* @return 0 on success, or errno on error
* @raise ETIMEDOUT if `abstime` was specified and the current time
* exceeded its value

View file

@ -29,6 +29,7 @@
#include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h"
#include "libc/sysv/consts/futex.h"
#include "libc/thread/freebsd.internal.h"
#include "libc/thread/wait0.internal.h"
int _futex(atomic_int *, int, int, const struct timespec *);
@ -64,6 +65,8 @@ static void _wait0_futex(const atomic_int *a, int e) {
} else {
rc = -GetLastError();
}
} else if (IsFreebsd()) {
rc = sys_umtx_op(a, UMTX_OP_WAIT_UINT, 0, 0, 0);
} else {
rc = _futex(a, op, e, 0);
if (IsOpenbsd() && rc > 0) {