Fix some issues

This commit is contained in:
Justine Tunney 2023-10-09 20:18:48 -07:00
parent 211d5d902e
commit 9d372f48dd
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
29 changed files with 373 additions and 63 deletions

View file

@ -29,7 +29,7 @@
void __assert_fail(const char *expr, const char *file, int line) {
char ibuf[12];
FormatInt32(ibuf, line);
tinyprint(2, "\n", file, ":", ibuf, ": assert(", expr, ") failed (",
tinyprint(2, file, ":", ibuf, ": assert(", expr, ") failed (",
program_invocation_short_name, " ",
DescribeBacktrace(__builtin_frame_address(0)), ")\n", NULL);
abort();

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timespec.internal.h"
#include "libc/calls/struct/timeval.h"
@ -27,6 +28,7 @@
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/timer.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/posixthread.internal.h"
#include "libc/thread/thread.h"
int sys_clock_nanosleep_xnu(int clock, int flags, const struct timespec *req,
@ -74,7 +76,7 @@ int sys_clock_nanosleep_xnu(int clock, int flags, const struct timespec *req,
}
if (res == -EINTR && //
(_weaken(pthread_testcancel_np) && //
_weaken(pthread_testcancel_np))) {
_weaken(pthread_testcancel_np)())) {
return ecanceled();
}
return _sysret(res);

View file

@ -23,11 +23,14 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/clktck.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/timer.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/thread.h"
static int sys_clock_nanosleep(int clock, int flags, //
const struct timespec *req,
@ -45,6 +48,16 @@ static int sys_clock_nanosleep(int clock, int flags, //
} else {
rc = enosys();
}
if (rc > 0) {
errno = rc;
rc = -1;
}
// system call support might not detect cancelation on bsds
if (rc == -1 && errno == EINTR && //
_weaken(pthread_testcancel_np) && //
_weaken(pthread_testcancel_np)()) {
rc = ecanceled();
}
END_CANCELATION_POINT;
STRACE("sys_clock_nanosleep(%s, %s, %s, [%s]) → %d% m",
DescribeClockName(clock), DescribeSleepFlags(flags),
@ -62,11 +75,11 @@ static int cosmo_clock_nanosleep(int clock, int flags,
if (clock == CLOCK_REALTIME || //
clock == CLOCK_REALTIME_PRECISE) {
time_clock = clock;
sleep_clock = CLOCK_REALTIME_PRECISE;
sleep_clock = CLOCK_REALTIME;
} else if (clock == CLOCK_MONOTONIC || //
clock == CLOCK_MONOTONIC_PRECISE) {
time_clock = clock;
sleep_clock = CLOCK_MONOTONIC_PRECISE;
sleep_clock = CLOCK_MONOTONIC;
} else if (clock == CLOCK_REALTIME_COARSE || //
clock == CLOCK_REALTIME_FAST) {
return sys_clock_nanosleep(CLOCK_REALTIME, flags, req, rem);

View file

@ -41,6 +41,7 @@
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/limits.h"
#include "libc/sysv/consts/sa.h"
@ -70,6 +71,10 @@ static void sigaction_cosmo2native(union metasigaction *sa) {
sa->linux.sa_restorer = restorer;
sa->linux.sa_mask[0] = masklo;
sa->linux.sa_mask[1] = maskhi;
} else if (IsXnuSilicon()) {
sa->silicon.sa_flags = flags;
sa->silicon.sa_handler = handler;
sa->silicon.sa_mask[0] = masklo;
} else if (IsXnu()) {
sa->xnu_in.sa_flags = flags;
sa->xnu_in.sa_handler = handler;
@ -109,6 +114,10 @@ static void sigaction_native2cosmo(union metasigaction *sa) {
restorer = sa->linux.sa_restorer;
masklo = sa->linux.sa_mask[0];
maskhi = sa->linux.sa_mask[1];
} else if (IsXnu()) {
flags = sa->silicon.sa_flags;
handler = sa->silicon.sa_handler;
masklo = sa->silicon.sa_mask[0];
} else if (IsXnu()) {
flags = sa->xnu_out.sa_flags;
handler = sa->xnu_out.sa_handler;
@ -142,6 +151,7 @@ static int __sigaction(int sig, const struct sigaction *act,
(sizeof(struct sigaction) >= sizeof(struct sigaction_linux) &&
sizeof(struct sigaction) >= sizeof(struct sigaction_xnu_in) &&
sizeof(struct sigaction) >= sizeof(struct sigaction_xnu_out) &&
sizeof(struct sigaction) >= sizeof(struct sigaction_silicon) &&
sizeof(struct sigaction) >= sizeof(struct sigaction_freebsd) &&
sizeof(struct sigaction) >= sizeof(struct sigaction_openbsd) &&
sizeof(struct sigaction) >= sizeof(struct sigaction_netbsd)),
@ -193,6 +203,9 @@ static int __sigaction(int sig, const struct sigaction *act,
// mitigate Rosetta signal handling strangeness
// https://github.com/jart/cosmopolitan/issues/455
ap->sa_flags |= SA_SIGINFO;
} else if (IsXnu()) {
sigenter = __sigenter_xnu;
ap->sa_flags |= SA_SIGINFO; // couldn't hurt
} else if (IsNetbsd()) {
sigenter = __sigenter_netbsd;
} else if (IsFreebsd()) {
@ -231,7 +244,12 @@ static int __sigaction(int sig, const struct sigaction *act,
arg4 = 8; /* or linux whines */
arg5 = 0;
}
if ((rc = sys_sigaction(sig, ap, oldact, arg4, arg5)) != -1) {
if (!IsXnuSilicon()) {
rc = sys_sigaction(sig, ap, oldact, arg4, arg5);
} else {
rc = _sysret(__syslib->__sigaction(sig, ap, oldact));
}
if (rc != -1) {
sigaction_native2cosmo((union metasigaction *)oldact);
}
} else {

View file

@ -25,6 +25,7 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sysv/consts/ss.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/tls.h"
@ -82,9 +83,17 @@ static textwindows int sigaltstack_cosmo(const struct sigaltstack *neu,
static int sigaltstack_bsd(const struct sigaltstack *neu,
struct sigaltstack *old) {
int rc;
struct sigaltstack_bsd oldbsd, neubsd, *neup = 0;
if (neu) sigaltstack2bsd(&neubsd, neu), neup = &neubsd;
if (sys_sigaltstack(neup, &oldbsd) == -1) return -1;
if (IsXnuSilicon()) {
rc = _sysret(__syslib->__sigaltstack(neup, &oldbsd));
} else {
rc = sys_sigaltstack(neup, &oldbsd);
}
if (rc == -1) {
return -1;
}
if (old) sigaltstack2linux(old, &oldbsd);
return 0;
}

View file

@ -486,9 +486,14 @@ static privileged void linuxssefpustate2xnu(
#endif /* __x86_64__ */
#ifdef __x86_64__
privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
struct siginfo_xnu *xnuinfo,
struct __darwin_ucontext *xnuctx) {
#else
privileged void __sigenter_xnu(int sig, struct siginfo_xnu *xnuinfo,
struct __darwin_ucontext *xnuctx) {
#endif
#pragma GCC push_options
#pragma GCC diagnostic ignored "-Wframe-larger-than="
struct Goodies {
@ -579,15 +584,6 @@ privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
: "=a"(ax)
: "0"(0x20000b8 /* sigreturn */), "D"(xnuctx), "S"(infostyle)
: "rcx", "r11", "memory", "cc");
#else
register long r0 asm("x0") = (long)xnuctx;
register long r1 asm("x1") = (long)infostyle;
asm volatile("mov\tx16,%0\n\t"
"svc\t0"
: /* no outputs */
: "i"(0x0b8 /* sigreturn */), "r"(r0), "r"(r1)
: "x16", "memory");
#endif /* __x86_64__ */
notpossible;
#endif /* __x86_64__ */
}

View file

@ -17,32 +17,45 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/blockcancel.internal.h"
#include "libc/calls/struct/timespec.h"
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/sysv/consts/clock.h"
#include "libc/thread/posixthread.internal.h"
#include "libc/thread/thread.h"
#include "libc/time/time.h"
/**
* Sleeps for particular number of seconds.
*
* This function may be canceled except when using masked mode in which
* case cancelation is temporarily disabled, because there is no way to
* report the ECANCELED state.
*
* @return 0 if the full time elapsed, otherwise we assume an interrupt
* was delivered, in which case the errno condition is ignored, and
* this function shall return the number of unslept seconds rounded
* using the ceiling function, and finally `-1u` may be returned if
* thread was cancelled with `PTHREAD_CANCEL_MASKED` in play
* using the ceiling function
* @see clock_nanosleep()
* @cancelationpoint
* @asyncsignalsafe
* @norestart
*/
unsigned sleep(unsigned seconds) {
errno_t rc;
int cs = -1;
errno_t err;
unsigned unslept;
struct timespec tv = {seconds};
if (!(rc = clock_nanosleep(CLOCK_REALTIME, 0, &tv, &tv))) return 0;
if (rc == ECANCELED) return -1u;
npassert(rc == EINTR);
if (_pthread_self()->pt_flags & PT_MASKED) {
cs = _pthread_block_cancelation();
}
err = clock_nanosleep(CLOCK_REALTIME, 0, &tv, &tv);
if (cs != -1) {
_pthread_allow_cancelation(cs);
}
if (!err) return 0;
unassert(err == EINTR);
unslept = tv.tv_sec;
if (tv.tv_nsec && unslept < UINT_MAX) {
++unslept;

View file

@ -31,6 +31,12 @@ struct sigaction_netbsd {
uint32_t sa_flags;
};
struct sigaction_silicon {
void *sa_handler;
uint32_t sa_mask[1];
uint32_t sa_flags;
};
struct sigaction_xnu_in {
void *sa_handler;
void *sa_restorer;
@ -50,6 +56,7 @@ union metasigaction {
struct sigaction_freebsd freebsd;
struct sigaction_openbsd openbsd;
struct sigaction_netbsd netbsd;
struct sigaction_silicon silicon;
struct sigaction_xnu_in xnu_in;
struct sigaction_xnu_out xnu_out;
};

View file

@ -22,20 +22,31 @@
#include "libc/errno.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/clock.h"
#include "libc/thread/posixthread.internal.h"
/**
* Sleeps for specified delay.
*
* This function may be canceled except when using masked mode in which
* case cancelation is temporarily disabled, because there is no way to
* report the ECANCELED state.
*
* @return unslept time which may be non-zero if the call was interrupted
* @cancelationpoint
*/
struct timespec timespec_sleep(struct timespec delay) {
errno_t rc;
int cs = -1;
errno_t err;
struct timespec remain;
BLOCK_CANCELATION;
bzero(&remain, sizeof(remain));
if ((rc = clock_nanosleep(CLOCK_REALTIME, 0, &delay, &remain))) {
npassert(rc == EINTR);
remain = timespec_zero;
if (_pthread_self()->pt_flags & PT_MASKED) {
cs = _pthread_block_cancelation();
}
if ((err = clock_nanosleep(CLOCK_REALTIME, 0, &delay, &remain))) {
unassert(err == EINTR);
}
if (cs != -1) {
_pthread_allow_cancelation(cs);
}
ALLOW_CANCELATION;
return remain;
}

View file

@ -33,6 +33,6 @@
errno_t timespec_sleep_until(struct timespec abs_deadline) {
errno_t rc;
rc = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &abs_deadline, 0);
npassert(!rc || rc == EINTR || rc == ECANCELED);
unassert(!rc || rc == EINTR || rc == ECANCELED);
return rc;
}

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/struct/timespec.h"
#include "libc/errno.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/errfuns.h"
#include "libc/time/time.h"
@ -32,7 +33,9 @@
* @norestart
*/
int usleep(uint32_t micros) {
errno_t err;
struct timespec ts = timespec_frommicros(micros);
if (clock_nanosleep(CLOCK_REALTIME, 0, &ts, 0)) return eintr();
err = clock_nanosleep(CLOCK_REALTIME, 0, &ts, 0);
if (err) return errno = err, -1;
return 0;
}

View file

@ -130,6 +130,9 @@ void AppendResourceReport(char **b, struct rusage *ru, const char *nl) {
if (ru->ru_nsignals) {
appends(b, "delivered ");
AppendUnit(st, ru->ru_nsignals, "signal");
if ((ru->ru_nsignals) > 1) {
appendw(b, READ16LE("s"));
}
AppendNl(st);
}
if (ru->ru_nswap) {

View file

@ -92,7 +92,6 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
if (rc == -1) {
free(fdspec);
CloseHandle(hParentProcess);
__undescribe_fds(hParentProcess, lpExplicitHandles, dwExplicitHandleCount);
_pthread_unlock();
__sig_unblock(m);
if (GetLastError() == kNtErrorSharingViolation) {
@ -104,8 +103,8 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
// give child to libc/proc/proc.c worker thread in parent
int64_t handle;
unassert(!DuplicateHandle(GetCurrentProcess(), pi.hProcess, hParentProcess,
&handle, 0, false, kNtDuplicateSameAccess));
unassert(DuplicateHandle(GetCurrentProcess(), pi.hProcess, hParentProcess,
&handle, 0, false, kNtDuplicateSameAccess));
unassert(!(handle & 0xFFFFFFFFFF000000));
TerminateThisProcess(0x23000000u | handle);
}

View file

@ -59,6 +59,15 @@ struct Syslib {
long (*__sigaction)(int, const void *, void *);
long (*__pselect)(int, void *, void *, void *, const void *, const void *);
long (*__mprotect)(void *, size_t, int);
/* v5 (2023-10-09) */
long (*__sigaltstack)(const void *, void *);
long (*__getentropy)(void *, size_t);
long (*__sem_open)(const char *, int, uint16_t, unsigned);
long (*__sem_unlink)(const char *);
long (*__sem_close)(int *);
long (*__sem_post)(int *);
long (*__sem_wait)(int *);
long (*__sem_trywait)(int *);
};
extern struct Syslib *__syslib;

View file

@ -45,6 +45,7 @@
#include "libc/nt/struct/ldrdatatableentry.h"
#include "libc/nt/struct/startupinfo.h"
#include "libc/nt/struct/teb.h"
#include "libc/runtime/clktck.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
@ -457,6 +458,7 @@ textstartup void __printargs(const char *prologue) {
PRINT(" ☼ %s = %d", "geteuid()", geteuid());
PRINT(" ☼ %s = %d", "getgid()", getgid());
PRINT(" ☼ %s = %d", "getegid()", getegid());
PRINT(" ☼ %s = %d", "CLK_TCK", CLK_TCK);
PRINT(" ☼ %s = %#s", "__get_tmpdir()", __get_tmpdir());
#ifdef __x86_64__
PRINT(" ☼ %s = %#s", "kNtSystemDirectory", kNtSystemDirectory);

View file

@ -46,7 +46,9 @@ extern const char systemfive_cancellable[];
extern const char systemfive_cancellable_end[];
long _pthread_cancel_ack(void) {
struct PosixThread *pt = _pthread_self();
struct PosixThread *pt;
STRACE("_pthread_cancel_ack()");
pt = _pthread_self();
if (!(pt->pt_flags & (PT_NOCANCEL | PT_MASKED)) ||
(pt->pt_flags & PT_ASYNC)) {
pthread_exit(PTHREAD_CANCELED);
@ -58,6 +60,7 @@ long _pthread_cancel_ack(void) {
return ecanceled();
}
// the purpose of this routine is to force a blocking system call to end
static void _pthread_cancel_sig(int sig, siginfo_t *si, void *arg) {
ucontext_t *ctx = arg;
@ -231,6 +234,7 @@ static errno_t _pthread_cancel_everyone(void) {
* - `nsync_cv_wait`
* - `opendir`
* - `openatemp`, 'mkstemp', etc.
* - `sleep`, `usleep`, `nanosleep`, `timespec_sleep`, etc.
* - `pclose`
* - `popen`
* - `fwrite`, `printf`, `fprintf`, `putc`, etc.
@ -344,15 +348,12 @@ static errno_t _pthread_cancel_everyone(void) {
* @raise ESRCH if system thread wasn't alive or we lost a race
*/
errno_t pthread_cancel(pthread_t thread) {
errno_t err;
struct PosixThread *arg;
if ((arg = (struct PosixThread *)thread)) {
err = _pthread_cancel_single(arg);
return _pthread_cancel_single(arg);
} else {
err = _pthread_cancel_everyone();
return _pthread_cancel_everyone();
}
STRACE("pthread_cancel(%d) → %s", _pthread_tid(arg), DescribeErrno(err));
return err;
}
/**

View file

@ -20,6 +20,7 @@
#include "libc/calls/blockcancel.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
@ -27,6 +28,7 @@
#include "libc/limits.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/map.h"
@ -173,15 +175,32 @@ sem_t *sem_open(const char *name, int oflag, ...) {
struct Semaphore *s;
char pathbuf[PATH_MAX];
unsigned mode = 0, value = 0;
va_start(va, oflag);
mode = va_arg(va, unsigned);
value = va_arg(va, unsigned);
va_end(va);
#if 0
if (IsXnuSilicon()) {
long kernel;
if (!(sem = calloc(1, sizeof(sem_t)))) return SEM_FAILED;
sem->sem_magic = SEM_MAGIC_KERNEL;
kernel = _sysret(__syslib->__sem_open(name, oflag, mode, value));
if (kernel == -1) {
free(sem);
return SEM_FAILED;
}
sem->sem_magic = SEM_MAGIC_KERNEL;
sem->sem_kernel = (int *)kernel;
}
#endif
if (oflag & ~(O_CREAT | O_EXCL)) {
einval();
return SEM_FAILED;
}
if (oflag & O_CREAT) {
va_start(va, oflag);
mode = va_arg(va, unsigned);
value = va_arg(va, unsigned);
va_end(va);
if (value > SEM_VALUE_MAX) {
einval();
return SEM_FAILED;
@ -250,6 +269,14 @@ int sem_close(sem_t *sem) {
int prefs;
bool unmap, delete;
struct Semaphore *s, **p;
#if 0
if (IsXnuSilicon()) {
npassert(sem->sem_magic == SEM_MAGIC_KERNEL);
return _sysret(__syslib->__sem_close(sem->sem_kernel));
}
#endif
npassert(sem->sem_magic == SEM_MAGIC_NAMED);
sem_open_init();
sem_open_lock();
@ -298,6 +325,13 @@ int sem_unlink(const char *name) {
int rc, e = errno;
struct Semaphore *s;
char pathbuf[PATH_MAX];
#if 0
if (IsXnuSilicon()) {
return _sysret(__syslib->__sem_unlink(name));
}
#endif
if (!(path = sem_path_np(name, pathbuf, sizeof(pathbuf)))) return -1;
if ((rc = unlink(path)) == -1 && IsWindows() && errno == EACCES) {
sem_open_init();

View file

@ -18,9 +18,12 @@
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/limits.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/semaphore.h"
#include "third_party/nsync/futex.internal.h"
@ -33,6 +36,13 @@
*/
int sem_post(sem_t *sem) {
int rc, old, wakeups;
#if 0
if (IsXnuSilicon() && sem->sem_magic == SEM_MAGIC_KERNEL) {
return _sysret(__syslib->__sem_post(sem->sem_kernel));
}
#endif
old = atomic_fetch_add_explicit(&sem->sem_value, 1, memory_order_acq_rel);
unassert(old > INT_MIN);
if (old >= 0) {

View file

@ -17,12 +17,17 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/cp.internal.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timespec.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/weaken.h"
#include "libc/limits.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/semaphore.h"
#include "libc/thread/thread.h"
@ -52,9 +57,48 @@ static void sem_timedwait_cleanup(void *arg) {
* @cancelationpoint
*/
int sem_timedwait(sem_t *sem, const struct timespec *abstime) {
int e, i, v, rc;
int i, v, rc, e = errno;
#if 0
if (IsXnuSilicon() && sem->sem_magic == SEM_MAGIC_KERNEL) {
if (!abstime) {
if (_weaken(pthread_testcancel_np) && //
_weaken(pthread_testcancel_np)()) {
return ecanceled();
}
rc = _sysret(__syslib->__sem_wait(sem->sem_kernel));
if (rc == -1 && errno == EINTR && //
_weaken(pthread_testcancel_np) && //
_weaken(pthread_testcancel_np)()) {
return ecanceled();
}
return rc;
}
for (;;) {
if (_weaken(pthread_testcancel_np) && //
_weaken(pthread_testcancel_np)()) {
return ecanceled();
}
rc = _sysret(__syslib->__sem_trywait(sem->sem_kernel));
if (!rc) return 0;
if (errno == EINTR && //
_weaken(pthread_testcancel_np) && //
_weaken(pthread_testcancel_np)()) {
return ecanceled();
}
if (errno != EAGAIN) return -1;
errno = e;
struct timespec now = timespec_real();
if (timespec_cmp(*abstime, now) >= 0) {
return etimedout();
}
if (usleep(10 * 1000) == -1) {
return -1;
}
}
}
#endif
e = errno;
for (i = 0; i < 7; ++i) {
rc = sem_trywait(sem);
if (!rc) {

View file

@ -18,9 +18,12 @@
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/limits.h"
#include "libc/runtime/syslib.internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/semaphore.h"
@ -34,6 +37,13 @@
*/
int sem_trywait(sem_t *sem) {
int v;
#if 0
if (IsXnuSilicon() && sem->sem_magic == SEM_MAGIC_KERNEL) {
return _sysret(__syslib->__sem_trywait(sem->sem_kernel));
}
#endif
v = atomic_load_explicit(&sem->sem_value, memory_order_relaxed);
do {
unassert(v > INT_MIN);

View file

@ -8,6 +8,7 @@ COSMOPOLITAN_C_START_
#define SEM_FAILED ((sem_t *)0)
#define SEM_MAGIC_NAMED 0xDEADBEEFu
#define SEM_MAGIC_UNNAMED 0xFEEDABEEu
#define SEM_MAGIC_KERNEL 0xCAFEBABEu
typedef struct {
union {
@ -21,6 +22,7 @@ typedef struct {
int sem_pid; /* unnamed only */
bool sem_lazydelete; /* named only */
bool sem_pshared;
int *sem_kernel;
};
void *sem_space[32];
};