mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-22 21:32:31 +00:00
Fix some issues
This commit is contained in:
parent
211d5d902e
commit
9d372f48dd
29 changed files with 373 additions and 63 deletions
53
ape/ape-m1.c
53
ape/ape-m1.c
|
@ -30,10 +30,11 @@
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
|
||||||
#define pagesz 16384
|
#define pagesz 16384
|
||||||
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
|
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
|
||||||
#define SYSLIB_VERSION 4
|
#define SYSLIB_VERSION 5
|
||||||
|
|
||||||
struct Syslib {
|
struct Syslib {
|
||||||
int magic;
|
int magic;
|
||||||
|
@ -79,6 +80,15 @@ struct Syslib {
|
||||||
long (*pselect)(int, fd_set *, fd_set *, fd_set *, const struct timespec *,
|
long (*pselect)(int, fd_set *, fd_set *, fd_set *, const struct timespec *,
|
||||||
const sigset_t *);
|
const sigset_t *);
|
||||||
long (*mprotect)(void *, size_t, int);
|
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
|
#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 + 1 + ps->namelen + 1 > sizeof(ps->path)) return 0;
|
||||||
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
|
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
|
||||||
MemMove(ps->path + pathlen, ps->name, ps->namelen);
|
MemMove(ps->path + pathlen, ps->name, ps->namelen);
|
||||||
|
ps->path[pathlen + ps->namelen] = 0;
|
||||||
return !access(ps->path, X_OK);
|
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));
|
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) {
|
static long sys_write(int fd, const void *data, size_t size) {
|
||||||
return sysret(write(fd, data, 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.sigaction = sys_sigaction;
|
||||||
M->lib.pselect = sys_pselect;
|
M->lib.pselect = sys_pselect;
|
||||||
M->lib.mprotect = sys_mprotect;
|
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 */
|
/* getenv("_") is close enough to at_execfn */
|
||||||
execfn = argc > 0 ? argv[0] : 0;
|
execfn = argc > 0 ? argv[0] : 0;
|
||||||
|
|
|
@ -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 + 1 + ps->namelen + 1 > sizeof(ps->path)) return 0;
|
||||||
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
|
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
|
||||||
MemMove(ps->path + pathlen, ps->name, ps->namelen);
|
MemMove(ps->path + pathlen, ps->name, ps->namelen);
|
||||||
|
ps->path[pathlen + ps->namelen] = 0;
|
||||||
return !Access(ps->path, X_OK, ps->os);
|
return !Access(ps->path, X_OK, ps->os);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
void __assert_fail(const char *expr, const char *file, int line) {
|
void __assert_fail(const char *expr, const char *file, int line) {
|
||||||
char ibuf[12];
|
char ibuf[12];
|
||||||
FormatInt32(ibuf, line);
|
FormatInt32(ibuf, line);
|
||||||
tinyprint(2, "\n", file, ":", ibuf, ": assert(", expr, ") failed (",
|
tinyprint(2, file, ":", ibuf, ": assert(", expr, ") failed (",
|
||||||
program_invocation_short_name, " ",
|
program_invocation_short_name, " ",
|
||||||
DescribeBacktrace(__builtin_frame_address(0)), ")\n", NULL);
|
DescribeBacktrace(__builtin_frame_address(0)), ")\n", NULL);
|
||||||
abort();
|
abort();
|
||||||
|
|
|
@ -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/assert.h"
|
||||||
#include "libc/calls/struct/timespec.h"
|
#include "libc/calls/struct/timespec.h"
|
||||||
#include "libc/calls/struct/timespec.internal.h"
|
#include "libc/calls/struct/timespec.internal.h"
|
||||||
#include "libc/calls/struct/timeval.h"
|
#include "libc/calls/struct/timeval.h"
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
#include "libc/sysv/consts/clock.h"
|
#include "libc/sysv/consts/clock.h"
|
||||||
#include "libc/sysv/consts/timer.h"
|
#include "libc/sysv/consts/timer.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
#include "libc/thread/posixthread.internal.h"
|
||||||
#include "libc/thread/thread.h"
|
#include "libc/thread/thread.h"
|
||||||
|
|
||||||
int sys_clock_nanosleep_xnu(int clock, int flags, const struct timespec *req,
|
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 && //
|
if (res == -EINTR && //
|
||||||
(_weaken(pthread_testcancel_np) && //
|
(_weaken(pthread_testcancel_np) && //
|
||||||
_weaken(pthread_testcancel_np))) {
|
_weaken(pthread_testcancel_np)())) {
|
||||||
return ecanceled();
|
return ecanceled();
|
||||||
}
|
}
|
||||||
return _sysret(res);
|
return _sysret(res);
|
||||||
|
|
|
@ -23,11 +23,14 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/describeflags.internal.h"
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
|
#include "libc/intrin/weaken.h"
|
||||||
#include "libc/runtime/clktck.h"
|
#include "libc/runtime/clktck.h"
|
||||||
#include "libc/sysv/consts/clock.h"
|
#include "libc/sysv/consts/clock.h"
|
||||||
#include "libc/sysv/consts/timer.h"
|
#include "libc/sysv/consts/timer.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
#include "libc/thread/thread.h"
|
||||||
|
|
||||||
static int sys_clock_nanosleep(int clock, int flags, //
|
static int sys_clock_nanosleep(int clock, int flags, //
|
||||||
const struct timespec *req,
|
const struct timespec *req,
|
||||||
|
@ -45,6 +48,16 @@ static int sys_clock_nanosleep(int clock, int flags, //
|
||||||
} else {
|
} else {
|
||||||
rc = enosys();
|
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;
|
END_CANCELATION_POINT;
|
||||||
STRACE("sys_clock_nanosleep(%s, %s, %s, [%s]) → %d% m",
|
STRACE("sys_clock_nanosleep(%s, %s, %s, [%s]) → %d% m",
|
||||||
DescribeClockName(clock), DescribeSleepFlags(flags),
|
DescribeClockName(clock), DescribeSleepFlags(flags),
|
||||||
|
@ -62,11 +75,11 @@ static int cosmo_clock_nanosleep(int clock, int flags,
|
||||||
if (clock == CLOCK_REALTIME || //
|
if (clock == CLOCK_REALTIME || //
|
||||||
clock == CLOCK_REALTIME_PRECISE) {
|
clock == CLOCK_REALTIME_PRECISE) {
|
||||||
time_clock = clock;
|
time_clock = clock;
|
||||||
sleep_clock = CLOCK_REALTIME_PRECISE;
|
sleep_clock = CLOCK_REALTIME;
|
||||||
} else if (clock == CLOCK_MONOTONIC || //
|
} else if (clock == CLOCK_MONOTONIC || //
|
||||||
clock == CLOCK_MONOTONIC_PRECISE) {
|
clock == CLOCK_MONOTONIC_PRECISE) {
|
||||||
time_clock = clock;
|
time_clock = clock;
|
||||||
sleep_clock = CLOCK_MONOTONIC_PRECISE;
|
sleep_clock = CLOCK_MONOTONIC;
|
||||||
} else if (clock == CLOCK_REALTIME_COARSE || //
|
} else if (clock == CLOCK_REALTIME_COARSE || //
|
||||||
clock == CLOCK_REALTIME_FAST) {
|
clock == CLOCK_REALTIME_FAST) {
|
||||||
return sys_clock_nanosleep(CLOCK_REALTIME, flags, req, rem);
|
return sys_clock_nanosleep(CLOCK_REALTIME, flags, req, rem);
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/runtime/syslib.internal.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/limits.h"
|
#include "libc/sysv/consts/limits.h"
|
||||||
#include "libc/sysv/consts/sa.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_restorer = restorer;
|
||||||
sa->linux.sa_mask[0] = masklo;
|
sa->linux.sa_mask[0] = masklo;
|
||||||
sa->linux.sa_mask[1] = maskhi;
|
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()) {
|
} else if (IsXnu()) {
|
||||||
sa->xnu_in.sa_flags = flags;
|
sa->xnu_in.sa_flags = flags;
|
||||||
sa->xnu_in.sa_handler = handler;
|
sa->xnu_in.sa_handler = handler;
|
||||||
|
@ -109,6 +114,10 @@ static void sigaction_native2cosmo(union metasigaction *sa) {
|
||||||
restorer = sa->linux.sa_restorer;
|
restorer = sa->linux.sa_restorer;
|
||||||
masklo = sa->linux.sa_mask[0];
|
masklo = sa->linux.sa_mask[0];
|
||||||
maskhi = sa->linux.sa_mask[1];
|
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()) {
|
} else if (IsXnu()) {
|
||||||
flags = sa->xnu_out.sa_flags;
|
flags = sa->xnu_out.sa_flags;
|
||||||
handler = sa->xnu_out.sa_handler;
|
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_linux) &&
|
||||||
sizeof(struct sigaction) >= sizeof(struct sigaction_xnu_in) &&
|
sizeof(struct sigaction) >= sizeof(struct sigaction_xnu_in) &&
|
||||||
sizeof(struct sigaction) >= sizeof(struct sigaction_xnu_out) &&
|
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_freebsd) &&
|
||||||
sizeof(struct sigaction) >= sizeof(struct sigaction_openbsd) &&
|
sizeof(struct sigaction) >= sizeof(struct sigaction_openbsd) &&
|
||||||
sizeof(struct sigaction) >= sizeof(struct sigaction_netbsd)),
|
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
|
// mitigate Rosetta signal handling strangeness
|
||||||
// https://github.com/jart/cosmopolitan/issues/455
|
// https://github.com/jart/cosmopolitan/issues/455
|
||||||
ap->sa_flags |= SA_SIGINFO;
|
ap->sa_flags |= SA_SIGINFO;
|
||||||
|
} else if (IsXnu()) {
|
||||||
|
sigenter = __sigenter_xnu;
|
||||||
|
ap->sa_flags |= SA_SIGINFO; // couldn't hurt
|
||||||
} else if (IsNetbsd()) {
|
} else if (IsNetbsd()) {
|
||||||
sigenter = __sigenter_netbsd;
|
sigenter = __sigenter_netbsd;
|
||||||
} else if (IsFreebsd()) {
|
} else if (IsFreebsd()) {
|
||||||
|
@ -231,7 +244,12 @@ static int __sigaction(int sig, const struct sigaction *act,
|
||||||
arg4 = 8; /* or linux whines */
|
arg4 = 8; /* or linux whines */
|
||||||
arg5 = 0;
|
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);
|
sigaction_native2cosmo((union metasigaction *)oldact);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "libc/intrin/describeflags.internal.h"
|
#include "libc/intrin/describeflags.internal.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/runtime/syslib.internal.h"
|
||||||
#include "libc/sysv/consts/ss.h"
|
#include "libc/sysv/consts/ss.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/thread/tls.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,
|
static int sigaltstack_bsd(const struct sigaltstack *neu,
|
||||||
struct sigaltstack *old) {
|
struct sigaltstack *old) {
|
||||||
|
int rc;
|
||||||
struct sigaltstack_bsd oldbsd, neubsd, *neup = 0;
|
struct sigaltstack_bsd oldbsd, neubsd, *neup = 0;
|
||||||
if (neu) sigaltstack2bsd(&neubsd, neu), neup = &neubsd;
|
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);
|
if (old) sigaltstack2linux(old, &oldbsd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -486,9 +486,14 @@ static privileged void linuxssefpustate2xnu(
|
||||||
|
|
||||||
#endif /* __x86_64__ */
|
#endif /* __x86_64__ */
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
|
privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
|
||||||
struct siginfo_xnu *xnuinfo,
|
struct siginfo_xnu *xnuinfo,
|
||||||
struct __darwin_ucontext *xnuctx) {
|
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 push_options
|
||||||
#pragma GCC diagnostic ignored "-Wframe-larger-than="
|
#pragma GCC diagnostic ignored "-Wframe-larger-than="
|
||||||
struct Goodies {
|
struct Goodies {
|
||||||
|
@ -579,15 +584,6 @@ privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
|
||||||
: "=a"(ax)
|
: "=a"(ax)
|
||||||
: "0"(0x20000b8 /* sigreturn */), "D"(xnuctx), "S"(infostyle)
|
: "0"(0x20000b8 /* sigreturn */), "D"(xnuctx), "S"(infostyle)
|
||||||
: "rcx", "r11", "memory", "cc");
|
: "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;
|
notpossible;
|
||||||
|
#endif /* __x86_64__ */
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,32 +17,45 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
|
#include "libc/calls/blockcancel.internal.h"
|
||||||
#include "libc/calls/struct/timespec.h"
|
#include "libc/calls/struct/timespec.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
#include "libc/sysv/consts/clock.h"
|
#include "libc/sysv/consts/clock.h"
|
||||||
|
#include "libc/thread/posixthread.internal.h"
|
||||||
|
#include "libc/thread/thread.h"
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sleeps for particular number of seconds.
|
* 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
|
* @return 0 if the full time elapsed, otherwise we assume an interrupt
|
||||||
* was delivered, in which case the errno condition is ignored, and
|
* was delivered, in which case the errno condition is ignored, and
|
||||||
* this function shall return the number of unslept seconds rounded
|
* this function shall return the number of unslept seconds rounded
|
||||||
* using the ceiling function, and finally `-1u` may be returned if
|
* using the ceiling function
|
||||||
* thread was cancelled with `PTHREAD_CANCEL_MASKED` in play
|
|
||||||
* @see clock_nanosleep()
|
* @see clock_nanosleep()
|
||||||
* @cancelationpoint
|
* @cancelationpoint
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
* @norestart
|
* @norestart
|
||||||
*/
|
*/
|
||||||
unsigned sleep(unsigned seconds) {
|
unsigned sleep(unsigned seconds) {
|
||||||
errno_t rc;
|
int cs = -1;
|
||||||
|
errno_t err;
|
||||||
unsigned unslept;
|
unsigned unslept;
|
||||||
struct timespec tv = {seconds};
|
struct timespec tv = {seconds};
|
||||||
if (!(rc = clock_nanosleep(CLOCK_REALTIME, 0, &tv, &tv))) return 0;
|
if (_pthread_self()->pt_flags & PT_MASKED) {
|
||||||
if (rc == ECANCELED) return -1u;
|
cs = _pthread_block_cancelation();
|
||||||
npassert(rc == EINTR);
|
}
|
||||||
|
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;
|
unslept = tv.tv_sec;
|
||||||
if (tv.tv_nsec && unslept < UINT_MAX) {
|
if (tv.tv_nsec && unslept < UINT_MAX) {
|
||||||
++unslept;
|
++unslept;
|
||||||
|
|
|
@ -31,6 +31,12 @@ struct sigaction_netbsd {
|
||||||
uint32_t sa_flags;
|
uint32_t sa_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sigaction_silicon {
|
||||||
|
void *sa_handler;
|
||||||
|
uint32_t sa_mask[1];
|
||||||
|
uint32_t sa_flags;
|
||||||
|
};
|
||||||
|
|
||||||
struct sigaction_xnu_in {
|
struct sigaction_xnu_in {
|
||||||
void *sa_handler;
|
void *sa_handler;
|
||||||
void *sa_restorer;
|
void *sa_restorer;
|
||||||
|
@ -50,6 +56,7 @@ union metasigaction {
|
||||||
struct sigaction_freebsd freebsd;
|
struct sigaction_freebsd freebsd;
|
||||||
struct sigaction_openbsd openbsd;
|
struct sigaction_openbsd openbsd;
|
||||||
struct sigaction_netbsd netbsd;
|
struct sigaction_netbsd netbsd;
|
||||||
|
struct sigaction_silicon silicon;
|
||||||
struct sigaction_xnu_in xnu_in;
|
struct sigaction_xnu_in xnu_in;
|
||||||
struct sigaction_xnu_out xnu_out;
|
struct sigaction_xnu_out xnu_out;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,20 +22,31 @@
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/clock.h"
|
#include "libc/sysv/consts/clock.h"
|
||||||
|
#include "libc/thread/posixthread.internal.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sleeps for specified delay.
|
* 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
|
* @return unslept time which may be non-zero if the call was interrupted
|
||||||
|
* @cancelationpoint
|
||||||
*/
|
*/
|
||||||
struct timespec timespec_sleep(struct timespec delay) {
|
struct timespec timespec_sleep(struct timespec delay) {
|
||||||
errno_t rc;
|
int cs = -1;
|
||||||
|
errno_t err;
|
||||||
struct timespec remain;
|
struct timespec remain;
|
||||||
BLOCK_CANCELATION;
|
remain = timespec_zero;
|
||||||
bzero(&remain, sizeof(remain));
|
if (_pthread_self()->pt_flags & PT_MASKED) {
|
||||||
if ((rc = clock_nanosleep(CLOCK_REALTIME, 0, &delay, &remain))) {
|
cs = _pthread_block_cancelation();
|
||||||
npassert(rc == EINTR);
|
}
|
||||||
|
if ((err = clock_nanosleep(CLOCK_REALTIME, 0, &delay, &remain))) {
|
||||||
|
unassert(err == EINTR);
|
||||||
|
}
|
||||||
|
if (cs != -1) {
|
||||||
|
_pthread_allow_cancelation(cs);
|
||||||
}
|
}
|
||||||
ALLOW_CANCELATION;
|
|
||||||
return remain;
|
return remain;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,6 @@
|
||||||
errno_t timespec_sleep_until(struct timespec abs_deadline) {
|
errno_t timespec_sleep_until(struct timespec abs_deadline) {
|
||||||
errno_t rc;
|
errno_t rc;
|
||||||
rc = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &abs_deadline, 0);
|
rc = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &abs_deadline, 0);
|
||||||
npassert(!rc || rc == EINTR || rc == ECANCELED);
|
unassert(!rc || rc == EINTR || rc == ECANCELED);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/struct/timespec.h"
|
#include "libc/calls/struct/timespec.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
#include "libc/sysv/consts/clock.h"
|
#include "libc/sysv/consts/clock.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/time/time.h"
|
#include "libc/time/time.h"
|
||||||
|
@ -32,7 +33,9 @@
|
||||||
* @norestart
|
* @norestart
|
||||||
*/
|
*/
|
||||||
int usleep(uint32_t micros) {
|
int usleep(uint32_t micros) {
|
||||||
|
errno_t err;
|
||||||
struct timespec ts = timespec_frommicros(micros);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,6 +130,9 @@ void AppendResourceReport(char **b, struct rusage *ru, const char *nl) {
|
||||||
if (ru->ru_nsignals) {
|
if (ru->ru_nsignals) {
|
||||||
appends(b, "delivered ");
|
appends(b, "delivered ");
|
||||||
AppendUnit(st, ru->ru_nsignals, "signal");
|
AppendUnit(st, ru->ru_nsignals, "signal");
|
||||||
|
if ((ru->ru_nsignals) > 1) {
|
||||||
|
appendw(b, READ16LE("s"));
|
||||||
|
}
|
||||||
AppendNl(st);
|
AppendNl(st);
|
||||||
}
|
}
|
||||||
if (ru->ru_nswap) {
|
if (ru->ru_nswap) {
|
||||||
|
|
|
@ -92,7 +92,6 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
free(fdspec);
|
free(fdspec);
|
||||||
CloseHandle(hParentProcess);
|
CloseHandle(hParentProcess);
|
||||||
__undescribe_fds(hParentProcess, lpExplicitHandles, dwExplicitHandleCount);
|
|
||||||
_pthread_unlock();
|
_pthread_unlock();
|
||||||
__sig_unblock(m);
|
__sig_unblock(m);
|
||||||
if (GetLastError() == kNtErrorSharingViolation) {
|
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
|
// give child to libc/proc/proc.c worker thread in parent
|
||||||
int64_t handle;
|
int64_t handle;
|
||||||
unassert(!DuplicateHandle(GetCurrentProcess(), pi.hProcess, hParentProcess,
|
unassert(DuplicateHandle(GetCurrentProcess(), pi.hProcess, hParentProcess,
|
||||||
&handle, 0, false, kNtDuplicateSameAccess));
|
&handle, 0, false, kNtDuplicateSameAccess));
|
||||||
unassert(!(handle & 0xFFFFFFFFFF000000));
|
unassert(!(handle & 0xFFFFFFFFFF000000));
|
||||||
TerminateThisProcess(0x23000000u | handle);
|
TerminateThisProcess(0x23000000u | handle);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,15 @@ struct Syslib {
|
||||||
long (*__sigaction)(int, const void *, void *);
|
long (*__sigaction)(int, const void *, void *);
|
||||||
long (*__pselect)(int, void *, void *, void *, const void *, const void *);
|
long (*__pselect)(int, void *, void *, void *, const void *, const void *);
|
||||||
long (*__mprotect)(void *, size_t, int);
|
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;
|
extern struct Syslib *__syslib;
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include "libc/nt/struct/ldrdatatableentry.h"
|
#include "libc/nt/struct/ldrdatatableentry.h"
|
||||||
#include "libc/nt/struct/startupinfo.h"
|
#include "libc/nt/struct/startupinfo.h"
|
||||||
#include "libc/nt/struct/teb.h"
|
#include "libc/nt/struct/teb.h"
|
||||||
|
#include "libc/runtime/clktck.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
#include "libc/runtime/memtrack.internal.h"
|
#include "libc/runtime/memtrack.internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
@ -457,6 +458,7 @@ textstartup void __printargs(const char *prologue) {
|
||||||
PRINT(" ☼ %s = %d", "geteuid()", geteuid());
|
PRINT(" ☼ %s = %d", "geteuid()", geteuid());
|
||||||
PRINT(" ☼ %s = %d", "getgid()", getgid());
|
PRINT(" ☼ %s = %d", "getgid()", getgid());
|
||||||
PRINT(" ☼ %s = %d", "getegid()", getegid());
|
PRINT(" ☼ %s = %d", "getegid()", getegid());
|
||||||
|
PRINT(" ☼ %s = %d", "CLK_TCK", CLK_TCK);
|
||||||
PRINT(" ☼ %s = %#s", "__get_tmpdir()", __get_tmpdir());
|
PRINT(" ☼ %s = %#s", "__get_tmpdir()", __get_tmpdir());
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
PRINT(" ☼ %s = %#s", "kNtSystemDirectory", kNtSystemDirectory);
|
PRINT(" ☼ %s = %#s", "kNtSystemDirectory", kNtSystemDirectory);
|
||||||
|
|
|
@ -46,7 +46,9 @@ extern const char systemfive_cancellable[];
|
||||||
extern const char systemfive_cancellable_end[];
|
extern const char systemfive_cancellable_end[];
|
||||||
|
|
||||||
long _pthread_cancel_ack(void) {
|
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)) ||
|
if (!(pt->pt_flags & (PT_NOCANCEL | PT_MASKED)) ||
|
||||||
(pt->pt_flags & PT_ASYNC)) {
|
(pt->pt_flags & PT_ASYNC)) {
|
||||||
pthread_exit(PTHREAD_CANCELED);
|
pthread_exit(PTHREAD_CANCELED);
|
||||||
|
@ -58,6 +60,7 @@ long _pthread_cancel_ack(void) {
|
||||||
return ecanceled();
|
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) {
|
static void _pthread_cancel_sig(int sig, siginfo_t *si, void *arg) {
|
||||||
ucontext_t *ctx = arg;
|
ucontext_t *ctx = arg;
|
||||||
|
|
||||||
|
@ -231,6 +234,7 @@ static errno_t _pthread_cancel_everyone(void) {
|
||||||
* - `nsync_cv_wait`
|
* - `nsync_cv_wait`
|
||||||
* - `opendir`
|
* - `opendir`
|
||||||
* - `openatemp`, 'mkstemp', etc.
|
* - `openatemp`, 'mkstemp', etc.
|
||||||
|
* - `sleep`, `usleep`, `nanosleep`, `timespec_sleep`, etc.
|
||||||
* - `pclose`
|
* - `pclose`
|
||||||
* - `popen`
|
* - `popen`
|
||||||
* - `fwrite`, `printf`, `fprintf`, `putc`, etc.
|
* - `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
|
* @raise ESRCH if system thread wasn't alive or we lost a race
|
||||||
*/
|
*/
|
||||||
errno_t pthread_cancel(pthread_t thread) {
|
errno_t pthread_cancel(pthread_t thread) {
|
||||||
errno_t err;
|
|
||||||
struct PosixThread *arg;
|
struct PosixThread *arg;
|
||||||
if ((arg = (struct PosixThread *)thread)) {
|
if ((arg = (struct PosixThread *)thread)) {
|
||||||
err = _pthread_cancel_single(arg);
|
return _pthread_cancel_single(arg);
|
||||||
} else {
|
} else {
|
||||||
err = _pthread_cancel_everyone();
|
return _pthread_cancel_everyone();
|
||||||
}
|
}
|
||||||
STRACE("pthread_cancel(%d) → %s", _pthread_tid(arg), DescribeErrno(err));
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "libc/calls/blockcancel.internal.h"
|
#include "libc/calls/blockcancel.internal.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/struct/stat.h"
|
#include "libc/calls/struct/stat.h"
|
||||||
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/atomic.h"
|
#include "libc/intrin/atomic.h"
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/runtime/syslib.internal.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/at.h"
|
#include "libc/sysv/consts/at.h"
|
||||||
#include "libc/sysv/consts/map.h"
|
#include "libc/sysv/consts/map.h"
|
||||||
|
@ -173,15 +175,32 @@ sem_t *sem_open(const char *name, int oflag, ...) {
|
||||||
struct Semaphore *s;
|
struct Semaphore *s;
|
||||||
char pathbuf[PATH_MAX];
|
char pathbuf[PATH_MAX];
|
||||||
unsigned mode = 0, value = 0;
|
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)) {
|
if (oflag & ~(O_CREAT | O_EXCL)) {
|
||||||
einval();
|
einval();
|
||||||
return SEM_FAILED;
|
return SEM_FAILED;
|
||||||
}
|
}
|
||||||
if (oflag & O_CREAT) {
|
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) {
|
if (value > SEM_VALUE_MAX) {
|
||||||
einval();
|
einval();
|
||||||
return SEM_FAILED;
|
return SEM_FAILED;
|
||||||
|
@ -250,6 +269,14 @@ int sem_close(sem_t *sem) {
|
||||||
int prefs;
|
int prefs;
|
||||||
bool unmap, delete;
|
bool unmap, delete;
|
||||||
struct Semaphore *s, **p;
|
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);
|
npassert(sem->sem_magic == SEM_MAGIC_NAMED);
|
||||||
sem_open_init();
|
sem_open_init();
|
||||||
sem_open_lock();
|
sem_open_lock();
|
||||||
|
@ -298,6 +325,13 @@ int sem_unlink(const char *name) {
|
||||||
int rc, e = errno;
|
int rc, e = errno;
|
||||||
struct Semaphore *s;
|
struct Semaphore *s;
|
||||||
char pathbuf[PATH_MAX];
|
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 (!(path = sem_path_np(name, pathbuf, sizeof(pathbuf)))) return -1;
|
||||||
if ((rc = unlink(path)) == -1 && IsWindows() && errno == EACCES) {
|
if ((rc = unlink(path)) == -1 && IsWindows() && errno == EACCES) {
|
||||||
sem_open_init();
|
sem_open_init();
|
||||||
|
|
|
@ -18,9 +18,12 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/atomic.h"
|
#include "libc/intrin/atomic.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
|
#include "libc/runtime/syslib.internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/thread/semaphore.h"
|
#include "libc/thread/semaphore.h"
|
||||||
#include "third_party/nsync/futex.internal.h"
|
#include "third_party/nsync/futex.internal.h"
|
||||||
|
@ -33,6 +36,13 @@
|
||||||
*/
|
*/
|
||||||
int sem_post(sem_t *sem) {
|
int sem_post(sem_t *sem) {
|
||||||
int rc, old, wakeups;
|
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);
|
old = atomic_fetch_add_explicit(&sem->sem_value, 1, memory_order_acq_rel);
|
||||||
unassert(old > INT_MIN);
|
unassert(old > INT_MIN);
|
||||||
if (old >= 0) {
|
if (old >= 0) {
|
||||||
|
|
|
@ -17,12 +17,17 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/cp.internal.h"
|
#include "libc/calls/cp.internal.h"
|
||||||
#include "libc/calls/struct/timespec.h"
|
#include "libc/calls/struct/timespec.h"
|
||||||
#include "libc/calls/struct/timespec.internal.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/errno.h"
|
||||||
#include "libc/intrin/atomic.h"
|
#include "libc/intrin/atomic.h"
|
||||||
|
#include "libc/intrin/weaken.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
|
#include "libc/runtime/syslib.internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/thread/semaphore.h"
|
#include "libc/thread/semaphore.h"
|
||||||
#include "libc/thread/thread.h"
|
#include "libc/thread/thread.h"
|
||||||
|
@ -52,9 +57,48 @@ static void sem_timedwait_cleanup(void *arg) {
|
||||||
* @cancelationpoint
|
* @cancelationpoint
|
||||||
*/
|
*/
|
||||||
int sem_timedwait(sem_t *sem, const struct timespec *abstime) {
|
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) {
|
for (i = 0; i < 7; ++i) {
|
||||||
rc = sem_trywait(sem);
|
rc = sem_trywait(sem);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
|
|
|
@ -18,9 +18,12 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/atomic.h"
|
#include "libc/intrin/atomic.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
|
#include "libc/runtime/syslib.internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
#include "libc/thread/semaphore.h"
|
#include "libc/thread/semaphore.h"
|
||||||
|
|
||||||
|
@ -34,6 +37,13 @@
|
||||||
*/
|
*/
|
||||||
int sem_trywait(sem_t *sem) {
|
int sem_trywait(sem_t *sem) {
|
||||||
int v;
|
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);
|
v = atomic_load_explicit(&sem->sem_value, memory_order_relaxed);
|
||||||
do {
|
do {
|
||||||
unassert(v > INT_MIN);
|
unassert(v > INT_MIN);
|
||||||
|
|
|
@ -8,6 +8,7 @@ COSMOPOLITAN_C_START_
|
||||||
#define SEM_FAILED ((sem_t *)0)
|
#define SEM_FAILED ((sem_t *)0)
|
||||||
#define SEM_MAGIC_NAMED 0xDEADBEEFu
|
#define SEM_MAGIC_NAMED 0xDEADBEEFu
|
||||||
#define SEM_MAGIC_UNNAMED 0xFEEDABEEu
|
#define SEM_MAGIC_UNNAMED 0xFEEDABEEu
|
||||||
|
#define SEM_MAGIC_KERNEL 0xCAFEBABEu
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
union {
|
union {
|
||||||
|
@ -21,6 +22,7 @@ typedef struct {
|
||||||
int sem_pid; /* unnamed only */
|
int sem_pid; /* unnamed only */
|
||||||
bool sem_lazydelete; /* named only */
|
bool sem_lazydelete; /* named only */
|
||||||
bool sem_pshared;
|
bool sem_pshared;
|
||||||
|
int *sem_kernel;
|
||||||
};
|
};
|
||||||
void *sem_space[32];
|
void *sem_space[32];
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/atomic.h"
|
#include "libc/atomic.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/struct/sigaction.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
|
@ -26,6 +27,7 @@
|
||||||
#include "libc/nexgen32e/nexgen32e.h"
|
#include "libc/nexgen32e/nexgen32e.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/sysv/consts/sig.h"
|
||||||
#include "libc/testlib/testlib.h"
|
#include "libc/testlib/testlib.h"
|
||||||
#include "libc/thread/thread.h"
|
#include "libc/thread/thread.h"
|
||||||
#include "libc/thread/thread2.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[1]));
|
||||||
ASSERT_SYS(0, 0, close(pfds[0]));
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "libc/calls/struct/sigaction.h"
|
#include "libc/calls/struct/sigaction.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
#include "libc/sock/struct/sockaddr.h"
|
#include "libc/sock/struct/sockaddr.h"
|
||||||
|
@ -85,7 +84,6 @@ TEST(pthread_kill, canInterruptSleepOperation) {
|
||||||
signal(SIGUSR1, old);
|
signal(SIGUSR1, old);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void *ReadWorker(void *arg) {
|
void *ReadWorker(void *arg) {
|
||||||
char buf[8] = {0};
|
char buf[8] = {0};
|
||||||
ready = true;
|
ready = true;
|
||||||
|
@ -324,4 +322,3 @@ TEST(pthread_kill, canInterruptSigsuspend) {
|
||||||
ASSERT_SYS(0, 0, sigprocmask(SIG_SETMASK, &oldss, 0));
|
ASSERT_SYS(0, 0, sigprocmask(SIG_SETMASK, &oldss, 0));
|
||||||
signal(SIGUSR1, oldsig);
|
signal(SIGUSR1, oldsig);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -207,7 +207,7 @@ semlock_release(SemLockObject *self, PyObject *args)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_SEM_TIMEDWAIT
|
#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
|
static int
|
||||||
sem_timedwait_save(sem_t *sem, struct timespec *deadline, PyThreadState *_save)
|
sem_timedwait_save(sem_t *sem, struct timespec *deadline, PyThreadState *_save)
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include "libc/calls/struct/timespec.h"
|
#include "libc/calls/struct/timespec.h"
|
||||||
#include "libc/dns/dns.h"
|
#include "libc/dns/dns.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/fmt/conv.h"
|
|
||||||
#include "libc/fmt/libgen.h"
|
#include "libc/fmt/libgen.h"
|
||||||
#include "libc/intrin/bits.h"
|
#include "libc/intrin/bits.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
#include "libc/intrin/kprintf.h"
|
||||||
|
@ -33,9 +32,7 @@
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
#include "libc/log/check.h"
|
#include "libc/log/check.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/macros.internal.h"
|
|
||||||
#include "libc/mem/gc.h"
|
#include "libc/mem/gc.h"
|
||||||
#include "libc/mem/gc.internal.h"
|
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/sock/ipclassify.internal.h"
|
#include "libc/sock/ipclassify.internal.h"
|
||||||
|
@ -51,12 +48,8 @@
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
#include "libc/sysv/consts/sock.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/xasprintf.h"
|
||||||
#include "libc/x/xsigaction.h"
|
|
||||||
#include "net/https/https.h"
|
#include "net/https/https.h"
|
||||||
#include "third_party/mbedtls/debug.h"
|
|
||||||
#include "third_party/mbedtls/net_sockets.h"
|
#include "third_party/mbedtls/net_sockets.h"
|
||||||
#include "third_party/mbedtls/ssl.h"
|
#include "third_party/mbedtls/ssl.h"
|
||||||
#include "third_party/zlib/zlib.h"
|
#include "third_party/zlib/zlib.h"
|
||||||
|
|
|
@ -26,11 +26,6 @@
|
||||||
#define MAXIMUM 1e9
|
#define MAXIMUM 1e9
|
||||||
#define ITERATIONS 10
|
#define ITERATIONS 10
|
||||||
|
|
||||||
void WarmUp(void) {
|
|
||||||
struct timespec wf = {0, 1};
|
|
||||||
npassert(!clock_nanosleep(CLOCK_REALTIME, 0, &wf, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestSleepRealRelative(void) {
|
void TestSleepRealRelative(void) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("testing: clock_nanosleep(CLOCK_REALTIME) with relative "
|
printf("testing: clock_nanosleep(CLOCK_REALTIME) with relative "
|
||||||
|
@ -68,7 +63,6 @@ void TestSleepMonoRelative(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
WarmUp();
|
|
||||||
TestSleepRealRelative();
|
TestSleepRealRelative();
|
||||||
TestSleepMonoRelative();
|
TestSleepMonoRelative();
|
||||||
}
|
}
|
||||||
|
|
61
tool/viz/setitimer_accuracy.c
Normal file
61
tool/viz/setitimer_accuracy.c
Normal 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();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue