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

@ -30,10 +30,11 @@
#include <sys/uio.h>
#include <time.h>
#include <unistd.h>
#include <semaphore.h>
#define pagesz 16384
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
#define SYSLIB_VERSION 4
#define SYSLIB_VERSION 5
struct Syslib {
int magic;
@ -79,6 +80,15 @@ struct Syslib {
long (*pselect)(int, fd_set *, fd_set *, fd_set *, const struct timespec *,
const sigset_t *);
long (*mprotect)(void *, size_t, int);
/* v5 (2023-10-09) */
long (*sigaltstack)(const stack_t *, stack_t *);
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 *);
};
#define ELFCLASS32 1
@ -350,6 +360,7 @@ static char AccessCommand(struct PathSearcher *ps, unsigned long pathlen) {
if (pathlen + 1 + ps->namelen + 1 > sizeof(ps->path)) return 0;
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
MemMove(ps->path + pathlen, ps->name, ps->namelen);
ps->path[pathlen + ps->namelen] = 0;
return !access(ps->path, X_OK);
}
@ -795,6 +806,38 @@ static long sys_mprotect(void *data, size_t size, int prot) {
return sysret(mprotect(data, size, prot));
}
static long sys_sigaltstack(const stack_t *ss, stack_t *oss) {
return sysret(sigaltstack(ss, oss));
}
static long sys_getentropy(void *buf, size_t buflen) {
return sysret(getentropy(buf, buflen));
}
static long sys_sem_open(const char *name, int oflags, mode_t mode, unsigned value) {
return sysret((long)sem_open(name, oflags, mode, value));
}
static long sys_sem_unlink(const char *name) {
return sysret(sem_unlink(name));
}
static long sys_sem_close(sem_t *sem) {
return sysret(sem_close(sem));
}
static long sys_sem_post(sem_t *sem) {
return sysret(sem_post(sem));
}
static long sys_sem_wait(sem_t *sem) {
return sysret(sem_wait(sem));
}
static long sys_sem_trywait(sem_t *sem) {
return sysret(sem_trywait(sem));
}
static long sys_write(int fd, const void *data, size_t size) {
return sysret(write(fd, data, size));
}
@ -879,6 +922,14 @@ int main(int argc, char **argv, char **envp) {
M->lib.sigaction = sys_sigaction;
M->lib.pselect = sys_pselect;
M->lib.mprotect = sys_mprotect;
M->lib.sigaltstack = sys_sigaltstack;
M->lib.getentropy = sys_getentropy;
M->lib.sem_open = sys_sem_open;
M->lib.sem_unlink = sys_sem_unlink;
M->lib.sem_close = sys_sem_close;
M->lib.sem_post = sys_sem_post;
M->lib.sem_wait = sys_sem_wait;
M->lib.sem_trywait = sys_sem_trywait;
/* getenv("_") is close enough to at_execfn */
execfn = argc > 0 ? argv[0] : 0;

View file

@ -538,6 +538,7 @@ static char AccessCommand(struct PathSearcher *ps, unsigned long pathlen) {
if (pathlen + 1 + ps->namelen + 1 > sizeof(ps->path)) return 0;
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
MemMove(ps->path + pathlen, ps->name, ps->namelen);
ps->path[pathlen + ps->namelen] = 0;
return !Access(ps->path, X_OK, ps->os);
}

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];
};

View file

@ -18,6 +18,7 @@
*/
#include "libc/atomic.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
@ -26,6 +27,7 @@
#include "libc/nexgen32e/nexgen32e.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/sig.h"
#include "libc/testlib/testlib.h"
#include "libc/thread/thread.h"
#include "libc/thread/thread2.h"
@ -283,3 +285,28 @@ TEST(pthread_cancel, self_asynchronous_takesImmediateEffect) {
ASSERT_SYS(0, 0, close(pfds[1]));
ASSERT_SYS(0, 0, close(pfds[0]));
}
atomic_bool was_completed;
void WaitUntilReady(void) {
while (!ready) pthread_yield();
ASSERT_EQ(0, errno);
ASSERT_SYS(0, 0, usleep(1000));
}
void *SleepWorker(void *arg) {
pthread_setcancelstate(PTHREAD_CANCEL_MASKED, 0);
ready = true;
ASSERT_SYS(ECANCELED, -1, usleep(30 * 1e6));
was_completed = true;
return 0;
}
TEST(pthread_cancel, canInterruptSleepOperation) {
pthread_t th;
ASSERT_EQ(0, pthread_create(&th, 0, SleepWorker, 0));
WaitUntilReady();
ASSERT_EQ(0, pthread_cancel(th));
ASSERT_EQ(0, pthread_join(th, 0));
ASSERT_TRUE(was_completed);
}

View file

@ -21,7 +21,6 @@
#include "libc/calls/struct/sigaction.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/sock/struct/sockaddr.h"
@ -85,7 +84,6 @@ TEST(pthread_kill, canInterruptSleepOperation) {
signal(SIGUSR1, old);
}
#if 0
void *ReadWorker(void *arg) {
char buf[8] = {0};
ready = true;
@ -324,4 +322,3 @@ TEST(pthread_kill, canInterruptSigsuspend) {
ASSERT_SYS(0, 0, sigprocmask(SIG_SETMASK, &oldss, 0));
signal(SIGUSR1, oldsig);
}
#endif

View file

@ -207,7 +207,7 @@ semlock_release(SemLockObject *self, PyObject *args)
#endif
#ifndef HAVE_SEM_TIMEDWAIT
# define sem_timedwait(sem,deadline) sem_timedwait_save(sem,deadline,_save)
# define sem_timedwait_(sem,deadline) sem_timedwait_save(sem,deadline,_save)
static int
sem_timedwait_save(sem_t *sem, struct timespec *deadline, PyThreadState *_save)

View file

@ -25,7 +25,6 @@
#include "libc/calls/struct/timespec.h"
#include "libc/dns/dns.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/libgen.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/kprintf.h"
@ -33,9 +32,7 @@
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/mem/gc.h"
#include "libc/mem/gc.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/ipclassify.internal.h"
@ -51,12 +48,8 @@
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/sock.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
#include "libc/x/xasprintf.h"
#include "libc/x/xsigaction.h"
#include "net/https/https.h"
#include "third_party/mbedtls/debug.h"
#include "third_party/mbedtls/net_sockets.h"
#include "third_party/mbedtls/ssl.h"
#include "third_party/zlib/zlib.h"

View file

@ -26,11 +26,6 @@
#define MAXIMUM 1e9
#define ITERATIONS 10
void WarmUp(void) {
struct timespec wf = {0, 1};
npassert(!clock_nanosleep(CLOCK_REALTIME, 0, &wf, 0));
}
void TestSleepRealRelative(void) {
printf("\n");
printf("testing: clock_nanosleep(CLOCK_REALTIME) with relative "
@ -68,7 +63,6 @@ void TestSleepMonoRelative(void) {
}
int main(int argc, char *argv[]) {
WarmUp();
TestSleepRealRelative();
TestSleepMonoRelative();
}

View file

@ -0,0 +1,61 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/itimerval.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timeval.h"
#include "libc/fmt/itoa.h"
#include "libc/sysv/consts/itimer.h"
#include "libc/sysv/consts/sig.h"
#define HZ 120
struct timeval start;
struct timeval expect;
struct timeval interval = {0, 1e6 / HZ};
void OnTick(int sig) {
char ibuf[27];
struct timeval now = timeval_real();
switch (timeval_cmp(now, expect)) {
case 0:
tinyprint(1, "100% precise\n", NULL);
break;
case -1:
FormatInt64Thousands(ibuf, timeval_tomicros(timeval_sub(expect, now)));
tinyprint(1, ibuf, " µs early\n", NULL);
break;
case +1:
FormatInt64Thousands(ibuf, timeval_tomicros(timeval_sub(now, expect)));
tinyprint(1, ibuf, " µs late\n", NULL);
break;
default:
__builtin_unreachable();
}
expect = timeval_add(expect, interval);
}
int main(int argc, char *argv[]) {
start = timeval_real();
expect = timeval_add(start, interval);
signal(SIGALRM, OnTick);
setitimer(ITIMER_REAL, &(struct itimerval){interval, interval}, 0);
for (;;) pause();
}