mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-01 16:58:30 +00:00
Improve system calls
- Wrap clock_getres() - Wrap sched_setscheduler() - Make sleep() api conformant - Polyfill sleep() using select() - Improve clock_gettime() polyfill - Make nanosleep() POSIX conformant - Slightly improve some DNS functions - Further strengthen pledge() sandboxing - Improve rounding of timeval / timespec - Allow layering of pledge() calls on Linux - Polyfill sched_yield() using select() on XNU - Delete more system constants we probably don't need
This commit is contained in:
parent
5df3e4e7a8
commit
853b6c3864
330 changed files with 1971 additions and 1223 deletions
|
@ -16,15 +16,15 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/math.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
/**
|
||||
* Adds resource usages.
|
||||
* Accumulates resource statistics in `y` to `x`.
|
||||
*/
|
||||
void AddRusage(struct rusage *x, const struct rusage *y) {
|
||||
x->ru_utime = AddTimeval(x->ru_utime, y->ru_utime);
|
||||
x->ru_stime = AddTimeval(x->ru_stime, y->ru_stime);
|
||||
void _addrusage(struct rusage *x, const struct rusage *y) {
|
||||
x->ru_utime = _timeval_add(x->ru_utime, y->ru_utime);
|
||||
x->ru_stime = _timeval_add(x->ru_stime, y->ru_stime);
|
||||
x->ru_maxrss = MAX(x->ru_maxrss, y->ru_maxrss);
|
||||
x->ru_ixrss += y->ru_ixrss;
|
||||
x->ru_idrss += y->ru_idrss;
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/math.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
|
||||
/**
|
||||
* Adds two microsecond timestamps.
|
||||
*/
|
||||
struct timeval AddTimeval(struct timeval x, struct timeval y) {
|
||||
struct timeval _timeval_add(struct timeval x, struct timeval y) {
|
||||
x.tv_sec += y.tv_sec;
|
||||
x.tv_usec += y.tv_usec;
|
||||
if (x.tv_usec >= 1000000) {
|
||||
|
|
69
libc/calls/clock_getres.c
Normal file
69
libc/calls/clock_getres.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*-*- 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 2022 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/asan.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
int sys_clock_getres(int, struct timespec *) hidden;
|
||||
|
||||
static int sys_clock_getres_poly(int clock, struct timespec *ts, int64_t real) {
|
||||
if (clock == CLOCK_REALTIME) {
|
||||
ts->tv_sec = 0;
|
||||
ts->tv_nsec = real;
|
||||
return 0;
|
||||
} else if (clock == CLOCK_MONOTONIC) {
|
||||
ts->tv_sec = 0;
|
||||
ts->tv_nsec = 1;
|
||||
return 0;
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
static int sys_clock_getres_nt(int clock, struct timespec *ts) {
|
||||
return sys_clock_getres_poly(clock, ts, 100);
|
||||
}
|
||||
|
||||
static int sys_clock_getres_xnu(int clock, struct timespec *ts) {
|
||||
return sys_clock_getres_poly(clock, ts, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns granularity of clock.
|
||||
*/
|
||||
int clock_getres(int clock, struct timespec *ts) {
|
||||
int rc;
|
||||
if (!ts || (IsAsan() && !__asan_is_valid_timespec(ts))) {
|
||||
rc = efault();
|
||||
} else if (clock == 127) {
|
||||
rc = einval(); // 127 is used by consts.sh to mean unsupported
|
||||
} else if (IsWindows()) {
|
||||
rc = sys_clock_getres_nt(clock, ts);
|
||||
} else if (IsXnu()) {
|
||||
rc = sys_clock_getres_xnu(clock, ts);
|
||||
} else {
|
||||
rc = sys_clock_getres(clock, ts);
|
||||
}
|
||||
STRACE("clock_getres(%d, [%s]) → %d% m", clock, DescribeTimespec(rc, ts), rc);
|
||||
return rc;
|
||||
}
|
60
libc/calls/clock_gettime-mono.c
Normal file
60
libc/calls/clock_gettime-mono.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*-*- 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 2022 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/bits/likely.h"
|
||||
#include "libc/calls/clock_gettime.internal.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/clockstonanos.internal.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
static struct {
|
||||
bool once;
|
||||
char lock;
|
||||
uint64_t base;
|
||||
struct timespec mono;
|
||||
} g_mono;
|
||||
|
||||
int sys_clock_gettime_mono(struct timespec *ts) {
|
||||
// this routine stops being monotonic after 194 years of uptime
|
||||
uint64_t nanos;
|
||||
struct timespec res;
|
||||
if (X86_HAVE(INVTSC)) {
|
||||
if (__threaded) {
|
||||
_spinlock(&g_mono.lock);
|
||||
}
|
||||
if (UNLIKELY(!g_mono.once)) {
|
||||
clock_gettime(CLOCK_REALTIME, &g_mono.mono);
|
||||
g_mono.base = rdtsc();
|
||||
g_mono.once = true;
|
||||
}
|
||||
nanos = ClocksToNanos(rdtsc(), g_mono.base);
|
||||
res = g_mono.mono;
|
||||
res.tv_sec += nanos / 1000000000;
|
||||
res.tv_nsec += nanos % 1000000000;
|
||||
_spunlock(&g_mono.lock);
|
||||
*ts = res;
|
||||
return 0;
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
}
|
|
@ -16,51 +16,22 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/likely.h"
|
||||
#include "libc/calls/clock_gettime.internal.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/nt/struct/filetime.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/clockstonanos.internal.h"
|
||||
|
||||
textwindows int sys_clock_gettime_nt(int clockid, struct timespec *ts) {
|
||||
uint64_t nanos;
|
||||
static bool once;
|
||||
static char lock;
|
||||
struct timespec res;
|
||||
static uint64_t base;
|
||||
textwindows int sys_clock_gettime_nt(int clock, struct timespec *ts) {
|
||||
struct NtFileTime ft;
|
||||
static struct timespec mono;
|
||||
if (!ts) return efault();
|
||||
if (clockid == CLOCK_REALTIME) {
|
||||
if (clock == CLOCK_REALTIME) {
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
*ts = FileTimeToTimeSpec(ft);
|
||||
return 0;
|
||||
} else if ((clockid == CLOCK_MONOTONIC || clockid == CLOCK_MONOTONIC_RAW) &&
|
||||
X86_HAVE(INVTSC)) {
|
||||
// this routine stops being monotonic after 194 years of uptime
|
||||
if (__threaded) _spinlock(&lock);
|
||||
if (UNLIKELY(!once)) {
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
mono = FileTimeToTimeSpec(ft);
|
||||
base = rdtsc();
|
||||
once = true;
|
||||
}
|
||||
nanos = ClocksToNanos(rdtsc(), base);
|
||||
res = mono;
|
||||
res.tv_sec += nanos / 1000000000;
|
||||
res.tv_nsec += nanos % 1000000000;
|
||||
_spunlock(&lock);
|
||||
*ts = res;
|
||||
return 0;
|
||||
} else if (clock == CLOCK_MONOTONIC) {
|
||||
return sys_clock_gettime_mono(ts);
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
|
|
|
@ -17,19 +17,28 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/clock_gettime.internal.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int sys_clock_gettime_xnu(int clockid, struct timespec *ts) {
|
||||
int sys_clock_gettime_xnu(int clock, struct timespec *ts) {
|
||||
axdx_t ad;
|
||||
ad = sys_gettimeofday((struct timeval *)ts, NULL, NULL);
|
||||
if (ad.ax != -1) {
|
||||
if (ad.ax) {
|
||||
ts->tv_sec = ad.ax;
|
||||
ts->tv_nsec = ad.dx;
|
||||
if (clock == CLOCK_REALTIME) {
|
||||
ad = sys_gettimeofday((struct timeval *)ts, 0, 0);
|
||||
if (ad.ax != -1) {
|
||||
if (ad.ax) {
|
||||
ts->tv_sec = ad.ax;
|
||||
ts->tv_nsec = ad.dx;
|
||||
}
|
||||
ts->tv_nsec *= 1000;
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
ts->tv_nsec *= 1000;
|
||||
return 0;
|
||||
} else if (clock == CLOCK_MONOTONIC) {
|
||||
return sys_clock_gettime_mono(ts);
|
||||
} else {
|
||||
return -1;
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,23 +48,25 @@
|
|||
* __clock_gettime l: 35𝑐 11𝑛𝑠
|
||||
* sys_clock_gettime l: 220𝑐 71𝑛𝑠
|
||||
*
|
||||
* @param clockid can be CLOCK_REALTIME, CLOCK_MONOTONIC, etc.
|
||||
* @param clock can be CLOCK_REALTIME, CLOCK_MONOTONIC, etc.
|
||||
* @param ts is where the result is stored
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @error EINVAL if clockid isn't supported on this system
|
||||
* @error EINVAL if clock isn't supported on this system
|
||||
* @see strftime(), gettimeofday()
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int clock_gettime(int clockid, struct timespec *ts) {
|
||||
int clock_gettime(int clock, struct timespec *ts) {
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid_timespec(ts)) {
|
||||
if (clock == 127) {
|
||||
rc = einval(); // 127 is used by consts.sh to mean unsupported
|
||||
} else if (!ts || (IsAsan() && !__asan_is_valid_timespec(ts))) {
|
||||
rc = efault();
|
||||
} else {
|
||||
rc = __clock_gettime(clockid, ts);
|
||||
rc = __clock_gettime(clock, ts);
|
||||
}
|
||||
#if SYSDEBUG
|
||||
if (!__time_critical) {
|
||||
STRACE("clock_gettime(%d, [%s]) → %d% m", clockid, DescribeTimespec(rc, ts),
|
||||
STRACE("clock_gettime(%d, [%s]) → %d% m", clock, DescribeTimespec(rc, ts),
|
||||
rc);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -9,6 +9,7 @@ typedef int clock_gettime_f(int, struct timespec *);
|
|||
extern clock_gettime_f *__clock_gettime;
|
||||
clock_gettime_f *__clock_gettime_get(bool *) hidden;
|
||||
int __clock_gettime_init(int, struct timespec *) hidden;
|
||||
int sys_clock_gettime_mono(struct timespec *) hidden;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_MATH_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_MATH_H_
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct timeval AddTimeval(struct timeval, struct timeval);
|
||||
struct timespec AddTimespec(struct timespec, struct timespec);
|
||||
void AddRusage(struct rusage *, const struct rusage *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_MATH_H_ */
|
|
@ -16,64 +16,84 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/nt/time.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/clockstonanos.internal.h"
|
||||
|
||||
textwindows noinstrument int sys_nanosleep_nt(const struct timespec *req,
|
||||
struct timespec *rem) {
|
||||
int rc;
|
||||
textwindows int sys_nanosleep_nt(const struct timespec *req,
|
||||
struct timespec *rem) {
|
||||
bool alertable;
|
||||
uint32_t slice;
|
||||
int64_t ms, sec, nsec;
|
||||
uint64_t begin;
|
||||
int64_t ms, toto, nanos;
|
||||
struct timespec elapsed;
|
||||
|
||||
// check req is legal timespec
|
||||
if (!(0 <= req->tv_nsec && req->tv_nsec < 1000000000)) {
|
||||
return einval();
|
||||
}
|
||||
|
||||
// save beginning timestamp
|
||||
if (!__time_critical && rem) {
|
||||
begin = rdtsc();
|
||||
} else {
|
||||
begin = 0; // to prevent uninitialized warning
|
||||
}
|
||||
|
||||
// convert timespec to milliseconds
|
||||
if (__builtin_mul_overflow(req->tv_sec, 1000, &ms) ||
|
||||
__builtin_add_overflow(ms, req->tv_nsec / 1000000, &ms)) {
|
||||
__builtin_add_overflow(ms, (req->tv_nsec + 999999) / 1000000, &ms)) {
|
||||
ms = INT64_MAX;
|
||||
}
|
||||
if (!ms && (req->tv_sec || req->tv_nsec)) {
|
||||
ms = 1;
|
||||
}
|
||||
rc = 0;
|
||||
do {
|
||||
|
||||
for (toto = ms;;) {
|
||||
|
||||
// check if signal was delivered
|
||||
if (!__time_critical && _check_interrupts(false, g_fds.p)) {
|
||||
rc = eintr();
|
||||
break;
|
||||
if (rem) {
|
||||
nanos = ClocksToNanos(rdtsc(), begin);
|
||||
elapsed.tv_sec = nanos / 1000000000;
|
||||
elapsed.tv_nsec = nanos % 1000000000;
|
||||
*rem = _timespec_sub(*req, elapsed);
|
||||
if (rem->tv_sec < 0) {
|
||||
rem->tv_sec = 0;
|
||||
rem->tv_nsec = 0;
|
||||
}
|
||||
}
|
||||
return eintr();
|
||||
}
|
||||
|
||||
// configure the sleep
|
||||
slice = MIN(__SIG_POLLING_INTERVAL_MS, ms);
|
||||
if (__time_critical) {
|
||||
alertable = false;
|
||||
} else {
|
||||
alertable = true;
|
||||
POLLTRACE("sys_nanosleep_nt polling for %'ldms of %'ld");
|
||||
POLLTRACE("... sleeping %'ldms of %'ld", toto - ms, toto);
|
||||
}
|
||||
|
||||
// perform the sleep
|
||||
if (SleepEx(slice, alertable) == kNtWaitIoCompletion) {
|
||||
POLLTRACE("IOCP EINTR");
|
||||
POLLTRACE("IOCP EINTR"); // in case we ever figure it out
|
||||
continue;
|
||||
}
|
||||
ms -= slice;
|
||||
} while (ms > 0);
|
||||
ms = MAX(ms, 0);
|
||||
if (rem) {
|
||||
sec = ms / 1000;
|
||||
nsec = ms % 1000 * 1000000000;
|
||||
rem->tv_nsec -= nsec;
|
||||
if (rem->tv_nsec < 0) {
|
||||
--rem->tv_sec;
|
||||
rem->tv_nsec = 1000000000 - rem->tv_nsec;
|
||||
}
|
||||
rem->tv_sec -= sec;
|
||||
if (rem->tv_sec < 0) {
|
||||
rem->tv_sec = 0;
|
||||
rem->tv_nsec = 0;
|
||||
|
||||
// check if full duration has elapsed
|
||||
if ((ms -= slice) <= 0) {
|
||||
if (rem) {
|
||||
rem->tv_sec = 0;
|
||||
rem->tv_nsec = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -16,15 +16,43 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
|
||||
int sys_nanosleep_xnu(const struct timespec *req, struct timespec *rem) {
|
||||
long millis;
|
||||
millis = req->tv_nsec / 1000;
|
||||
millis = MAX(1, millis);
|
||||
return sys_select(0, 0, 0, 0, &(struct timeval){req->tv_sec, millis});
|
||||
int rc;
|
||||
axdx_t axdx;
|
||||
struct timeval tv;
|
||||
struct timespec begin, end, elapsed;
|
||||
|
||||
if (rem) {
|
||||
if (sys_clock_gettime_xnu(CLOCK_MONOTONIC, &begin) == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
tv = _timespec2timeval(*req);
|
||||
rc = sys_select(0, 0, 0, 0, &tv);
|
||||
|
||||
if (rem) {
|
||||
if (!rc) {
|
||||
rem->tv_sec = 0;
|
||||
rem->tv_nsec = 0;
|
||||
} else if (rc == -1 && errno == EINTR) {
|
||||
sys_clock_gettime_xnu(CLOCK_MONOTONIC, &end);
|
||||
elapsed = _timespec_sub(end, begin);
|
||||
*rem = _timespec_sub(*req, elapsed);
|
||||
if (rem->tv_sec < 0) {
|
||||
rem->tv_sec = 0;
|
||||
rem->tv_nsec = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -27,10 +27,26 @@
|
|||
|
||||
/**
|
||||
* Sleeps for a particular amount of time.
|
||||
*
|
||||
* @param req is the duration of time we should sleep
|
||||
* @param rem if non-NULL will receive the amount of time that wasn't
|
||||
* slept because a signal was delivered. If no signal's delivered
|
||||
* then this value will be set to `{0, 0}`. It's also fine to set
|
||||
* this value to the same pointer as `req`.
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise EINVAL if `req->tv_nsec ∉ [0,1000000000)`
|
||||
* @raise EINTR if a signal was delivered, and `rem` is updated
|
||||
* @raise EFAULT if `req` is NULL or `req` / `rem` is a bad pointer
|
||||
* @raise ENOSYS on bare metal
|
||||
* @note POSIX.1 specifies nanosleep() measures against `CLOCK_REALTIME`
|
||||
* however Linux measures uses `CLOCK_MONOTONIC`. This shouldn't
|
||||
* matter, since POSIX.1 further specifies that discontinuous
|
||||
* changes in `CLOCK_REALTIME` shouldn't impact nanosleep()
|
||||
* @norestart
|
||||
*/
|
||||
noinstrument int nanosleep(const struct timespec *req, struct timespec *rem) {
|
||||
int nanosleep(const struct timespec *req, struct timespec *rem) {
|
||||
int rc;
|
||||
|
||||
if (!req || (IsAsan() && (!__asan_is_valid_timespec(req) ||
|
||||
(rem && !__asan_is_valid_timespec(rem))))) {
|
||||
rc = efault();
|
||||
|
@ -46,9 +62,21 @@ noinstrument int nanosleep(const struct timespec *req, struct timespec *rem) {
|
|||
} else {
|
||||
rc = sys_nanosleep_nt(req, rem);
|
||||
}
|
||||
|
||||
// Linux Kernel doesn't change the remainder value on success, but
|
||||
// some kernels like OpenBSD will. POSIX doesn't specify the Linux
|
||||
// behavior. So we polyfill it here.
|
||||
if (!rc && rem) {
|
||||
rem->tv_sec = 0;
|
||||
rem->tv_nsec = 0;
|
||||
}
|
||||
|
||||
#if defined(SYSDEBUG) && _POLLTRACE
|
||||
if (!__time_critical) {
|
||||
POLLTRACE("nanosleep(%s, [%s]) → %d% m", DescribeTimespec(rc, req),
|
||||
DescribeTimespec(rc, rem), rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
50
libc/calls/pause-nt.c
Normal file
50
libc/calls/pause-nt.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*-*- 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 2022 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/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_pause_nt(void) {
|
||||
long ms, totoms;
|
||||
ms = 0;
|
||||
totoms = 0;
|
||||
for (;;) {
|
||||
|
||||
if (_check_interrupts(false, g_fds.p)) {
|
||||
return eintr();
|
||||
}
|
||||
|
||||
if (SleepEx(__SIG_POLLING_INTERVAL_MS, true) == kNtWaitIoCompletion) {
|
||||
POLLTRACE("IOCP EINTR"); // in case we ever figure it out
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined(SYSDEBUG) && defined(_POLLTRACE)
|
||||
ms += __SIG_POLLING_INTERVAL_MS;
|
||||
if (ms >= __SIG_LOGGING_INTERVAL_MS) {
|
||||
totoms += ms, ms = 0;
|
||||
POLLTRACE("... pausing for %'lums...", totoms);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -18,34 +18,51 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/sock/internal.h"
|
||||
|
||||
/**
|
||||
* Waits for signal.
|
||||
*
|
||||
* This suspends execution until an unmasked signal is delivered and its
|
||||
* callback function has been called. The current signal mask is used.
|
||||
* This suspends execution until an unmasked signal is delivered. If the
|
||||
* signal delivery kills the process, this won't return. The signal mask
|
||||
* of the current thread is used. If a signal handler exists, this shall
|
||||
* return after it's been invoked.
|
||||
*
|
||||
* @return should always be -1 w/ EINTR
|
||||
* This function is equivalent to:
|
||||
*
|
||||
* select(0, 0, 0, 0, 0);
|
||||
*
|
||||
* However this has a tinier footprint and better logging.
|
||||
*
|
||||
* @return -1 w/ errno set to EINTR
|
||||
* @see sigsuspend()
|
||||
* @norestart
|
||||
*/
|
||||
int pause(void) {
|
||||
int e, rc;
|
||||
sigset_t mask;
|
||||
e = errno;
|
||||
int rc;
|
||||
STRACE("pause() → [...]");
|
||||
if ((rc = sys_pause()) == -1 && errno == ENOSYS) {
|
||||
errno = e;
|
||||
if (sigprocmask(SIG_BLOCK, 0, &mask) == -1) return -1;
|
||||
rc = sigsuspend(&mask);
|
||||
|
||||
if (!IsWindows()) {
|
||||
// We'll polyfill pause() using select() with a null timeout, which
|
||||
// should hopefully do the same thing, which means wait forever but
|
||||
// the usual signal interrupt rules apply.
|
||||
//
|
||||
// "If the readfds, writefds, and errorfds arguments are all null
|
||||
// pointers and the timeout argument is not a null pointer, the
|
||||
// pselect() or select() function shall block for the time
|
||||
// specified, or until interrupted by a signal. If the readfds,
|
||||
// writefds, and errorfds arguments are all null pointers and the
|
||||
// timeout argument is a null pointer, the pselect() or select()
|
||||
// function shall block until interrupted by a signal." ──Quoth
|
||||
// IEEE 1003.1-2017 §functions/select
|
||||
//
|
||||
rc = sys_select(0, 0, 0, 0, 0);
|
||||
} else {
|
||||
rc = sys_pause_nt();
|
||||
}
|
||||
|
||||
STRACE("[...] pause → %d% m", rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
/**
|
||||
* Tunes process on Linux.
|
||||
*
|
||||
* @raise ENOSYS on non-Linux.
|
||||
* @raise ENOSYS on non-Linux
|
||||
*/
|
||||
privileged int prctl(int operation, ...) {
|
||||
int rc;
|
||||
|
|
33
libc/calls/sched-sysv.internal.h
Normal file
33
libc/calls/sched-sysv.internal.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_SCHED_SYSV_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_SCHED_SYSV_INTERNAL_H_
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define MAXCPUS_NETBSD 256
|
||||
#define MAXCPUS_OPENBSD 64
|
||||
#define P_ALL_LWPS 0 /* for effect on all threads in pid */
|
||||
|
||||
int sys_sched_get_priority_max(int);
|
||||
int sys_sched_get_priority_min(int);
|
||||
int sys_sched_getparam(int, struct sched_param *);
|
||||
int sys_sched_getscheduler(int);
|
||||
int sys_sched_setaffinity(int, uint64_t, const void *) hidden;
|
||||
int sys_sched_setparam(int, const struct sched_param *);
|
||||
int sys_sched_setscheduler(int, int, const struct sched_param *);
|
||||
int sys_sched_yield(void) hidden;
|
||||
int64_t sys_sched_getaffinity(int, uint64_t, void *) hidden;
|
||||
|
||||
int sys_sched_getscheduler_netbsd(int);
|
||||
int sys_sched_setparam_netbsd(int, int, int, const struct sched_param *) //
|
||||
asm("sys_sched_setparam");
|
||||
int sys_sched_getparam_netbsd(int, int, int *, struct sched_param *) //
|
||||
asm("sys_sched_getparam");
|
||||
int sys_sched_setaffinity_netbsd(int, int, size_t, const void *) //
|
||||
asm("sys_sched_setaffinity");
|
||||
int sys_sched_getaffinity_netbsd(int, int, size_t, void *) //
|
||||
asm("sys_sched_setaffinity");
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_SCHED_SYSV_INTERNAL_H_ */
|
53
libc/calls/sched_get_priority_max.c
Normal file
53
libc/calls/sched_get_priority_max.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*-*- 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 2022 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/sched-sysv.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/sched.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static int sys_sched_get_priority_max_netbsd(int policy) {
|
||||
if (policy == SCHED_OTHER) {
|
||||
return -1;
|
||||
} else if (policy == SCHED_RR || policy == SCHED_FIFO) {
|
||||
return 63; // NetBSD Libc needs 19 system calls to compute this!
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns maximum `sched_param::sched_priority` for `policy`.
|
||||
*
|
||||
* @return priority, or -1 w/ errno
|
||||
* @raise ENOSYS on XNU, Windows, OpenBSD
|
||||
* @raise EINVAL if `policy` is invalid
|
||||
*/
|
||||
int sched_get_priority_max(int policy) {
|
||||
int rc;
|
||||
if (IsNetbsd()) {
|
||||
rc = sys_sched_get_priority_max_netbsd(policy);
|
||||
} else {
|
||||
rc = sys_sched_get_priority_max(policy);
|
||||
}
|
||||
STRACE("sched_get_priority_max(%s) → %d% m", DescribeSchedPolicy(policy), rc);
|
||||
return rc;
|
||||
}
|
53
libc/calls/sched_get_priority_min.c
Normal file
53
libc/calls/sched_get_priority_min.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*-*- 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 2022 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/sched-sysv.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/sched.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static int sys_sched_get_priority_min_netbsd(int policy) {
|
||||
if (policy == SCHED_OTHER) {
|
||||
return -1;
|
||||
} else if (policy == SCHED_RR || policy == SCHED_FIFO) {
|
||||
return 0; // NetBSD Libc needs 19 system calls to compute this!
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns minimum `sched_param::sched_priority` for `policy`.
|
||||
*
|
||||
* @return priority, or -1 w/ errno
|
||||
* @raise ENOSYS on XNU, Windows, OpenBSD
|
||||
* @raise EINVAL if `policy` is invalid
|
||||
*/
|
||||
int sched_get_priority_min(int policy) {
|
||||
int rc;
|
||||
if (IsNetbsd()) {
|
||||
rc = sys_sched_get_priority_min_netbsd(policy);
|
||||
} else {
|
||||
rc = sys_sched_get_priority_min(policy);
|
||||
}
|
||||
STRACE("sched_get_priority_min(%s) → %d% m", DescribeSchedPolicy(policy), rc);
|
||||
return rc;
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
|
28
libc/calls/sched_getparam.c
Normal file
28
libc/calls/sched_getparam.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- 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 2022 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/sched-sysv.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
|
||||
/**
|
||||
* Gets scheduler policy parameter.
|
||||
* @raise ENOSYS on XNU, Windows
|
||||
*/
|
||||
int sched_getparam(int pid, struct sched_param *param) {
|
||||
return sys_sched_getparam(pid, param);
|
||||
}
|
31
libc/calls/sched_getscheduler-netbsd.c
Normal file
31
libc/calls/sched_getscheduler-netbsd.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- 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 2022 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/sched-sysv.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
|
||||
int sys_sched_getscheduler_netbsd(int pid) {
|
||||
int policy;
|
||||
struct sched_param sp;
|
||||
if (sys_sched_getparam_netbsd(pid, P_ALL_LWPS, &policy, &sp) != -1) {
|
||||
return policy;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
39
libc/calls/sched_getscheduler.c
Normal file
39
libc/calls/sched_getscheduler.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- 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 2022 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/sched-sysv.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/dce.h"
|
||||
|
||||
/**
|
||||
* Gets scheduler policy for `pid`.
|
||||
*
|
||||
* @param pid is id of process (where 0 is same as getpid())
|
||||
* @return scheduler policy, or -1 w/ errno
|
||||
*/
|
||||
int sched_getscheduler(int pid) {
|
||||
int rc;
|
||||
if (IsNetbsd()) {
|
||||
rc = sys_sched_getscheduler_netbsd(pid);
|
||||
} else {
|
||||
rc = sys_sched_getscheduler(pid);
|
||||
}
|
||||
STRACE("sched_getscheduler(%d) → %d% m", pid, rc);
|
||||
return rc;
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sched-sysv.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
|
|
28
libc/calls/sched_setparam.c
Normal file
28
libc/calls/sched_setparam.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- 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 2022 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/sched-sysv.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
|
||||
/**
|
||||
* Sets scheduler policy parameter.
|
||||
* @raise ENOSYS on XNU, Windows
|
||||
*/
|
||||
int sched_setparam(int pid, const struct sched_param *param) {
|
||||
return sys_sched_setparam(pid, param);
|
||||
}
|
106
libc/calls/sched_setscheduler.c
Normal file
106
libc/calls/sched_setscheduler.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*-*- 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 2022 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/sched-sysv.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Sets scheduling policy of process, e.g.
|
||||
*
|
||||
* struct sched_param p = {sched_get_priority_max(SCHED_OTHER)};
|
||||
* LOGIFNEG1(sched_setscheduler(0, SCHED_OTHER, &p));
|
||||
*
|
||||
* Processes with numerically higher priority values are scheduled
|
||||
* before processes with numerically lower priority values.
|
||||
*
|
||||
* @param pid is the id of the process whose scheduling policy should be
|
||||
* changed. This applies to all threads associated with the process.
|
||||
* Linux is special; the kernel treats this as a thread id (noting
|
||||
* that `getpid() == gettid()` is always the case on Linux for the
|
||||
* main thread) and will only take effect for the specified tid.
|
||||
* Therefore this function is POSIX-compliant iif `!__threaded`.
|
||||
* Setting `pid` to zero means the same thing as getpid().
|
||||
*
|
||||
* @param policy specifies the kernel's timesharing strategy.
|
||||
*
|
||||
* The `policy` must have one of:
|
||||
*
|
||||
* - `SCHED_OTHER` (or `SCHED_NORMAL`) for the default policy
|
||||
* - `SCHED_RR` for real-time round-robin scheduling
|
||||
* - `SCHED_FIFO` for real-time first-in first-out scheduling
|
||||
* - `SCHED_BATCH` for "batch" style execution of processes if
|
||||
* supported (Linux), otherwise it's treated as `SCHED_OTHER`
|
||||
* - `SCHED_IDLE` for running very low priority background jobs
|
||||
* if it's supported (Linux), otherwise this is `SCHED_OTHER`
|
||||
*
|
||||
* The `policy` may optionally bitwise-or any one of:
|
||||
*
|
||||
* - `SCHED_RESET_ON_FORK` will cause the scheduling policy to be
|
||||
* automatically reset to `SCHED_NORMAL` upon fork() if supported;
|
||||
* otherwise this flag is polyfilled as zero, so that it may be
|
||||
* safely used (without having to check if the o/s is Linux).
|
||||
*
|
||||
* @param param must be set to the scheduler parameter, which should be
|
||||
* greater than or equal to sched_get_priority_min(policy) and less
|
||||
* than or equal to sched_get_priority_max(policy). Linux allows the
|
||||
* static priority range 1 to 99 for the `SCHED_FIFO` and `SCHED_RR`
|
||||
* policies, and the priority 0 for the remaining policies.
|
||||
*
|
||||
* @return the former scheduling policy of the specified process. If
|
||||
* this function fails, then the scheduling policy is not changed,
|
||||
* and -1 w/ errno is returned.
|
||||
*
|
||||
* @raise ENOSYS on XNU, Windows, OpenBSD
|
||||
* @raise EPERM if not authorized to use scheduler in question (e.g.
|
||||
* trying to use a real-time scheduler as non-root on Linux) or
|
||||
* possibly because pledge() was used and isn't allowing this
|
||||
* @raise EINVAL if `param` is NULL
|
||||
* @raise EINVAL if `policy` is invalid
|
||||
* @raise EINVAL if `param` has value out of ranges defined by `policy`
|
||||
*/
|
||||
int sched_setscheduler(int pid, int policy, const struct sched_param *param) {
|
||||
int rc, old;
|
||||
|
||||
if (IsNetbsd()) {
|
||||
rc = sys_sched_getscheduler_netbsd(pid);
|
||||
} else {
|
||||
rc = sys_sched_getscheduler(pid);
|
||||
}
|
||||
|
||||
if (rc != -1) {
|
||||
old = rc;
|
||||
if (IsNetbsd()) {
|
||||
rc = sys_sched_setparam_netbsd(pid, P_ALL_LWPS, policy, param);
|
||||
} else {
|
||||
rc = sys_sched_setscheduler(pid, policy, param);
|
||||
}
|
||||
if (rc != -1) {
|
||||
rc = old;
|
||||
}
|
||||
}
|
||||
|
||||
STRACE("sched_setscheduler(%d, %s, %s) → %d% m", pid,
|
||||
DescribeSchedPolicy(policy), DescribeSchedParam(param), rc);
|
||||
return rc;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_SCHED_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_SCHED_H_
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int sched_setscheduler(int, int, const struct sched_param *);
|
||||
int sched_getscheduler(int);
|
||||
int sched_setparam(int, const struct sched_param *);
|
||||
int sched_getparam(int, struct sched_param *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_SCHED_H_ */
|
|
@ -26,6 +26,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
|
@ -80,6 +81,7 @@ textwindows void _check_sigalrm(void) {
|
|||
textwindows int sys_setitimer_nt(int which, const struct itimerval *newvalue,
|
||||
struct itimerval *out_opt_oldvalue) {
|
||||
long double elapsed, untilnext;
|
||||
|
||||
if (which != ITIMER_REAL ||
|
||||
(newvalue && (!(0 <= newvalue->it_value.tv_usec &&
|
||||
newvalue->it_value.tv_usec < 1000000) ||
|
||||
|
@ -87,6 +89,7 @@ textwindows int sys_setitimer_nt(int which, const struct itimerval *newvalue,
|
|||
newvalue->it_interval.tv_usec < 1000000)))) {
|
||||
return einval();
|
||||
}
|
||||
|
||||
if (out_opt_oldvalue) {
|
||||
if (__hastimer) {
|
||||
elapsed = nowl() - __lastalrm;
|
||||
|
@ -106,6 +109,7 @@ textwindows int sys_setitimer_nt(int which, const struct itimerval *newvalue,
|
|||
out_opt_oldvalue->it_value.tv_usec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (newvalue) {
|
||||
if (newvalue->it_interval.tv_sec || newvalue->it_interval.tv_usec ||
|
||||
newvalue->it_value.tv_sec || newvalue->it_value.tv_usec) {
|
||||
|
@ -124,5 +128,6 @@ textwindows int sys_setitimer_nt(int which, const struct itimerval *newvalue,
|
|||
__hastimer = false;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,16 +16,32 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
/**
|
||||
* Sleeps for a particular amount of time.
|
||||
* Sleeps for particular number of seconds.
|
||||
*
|
||||
* @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
|
||||
* @see nanosleep(), usleep()
|
||||
* @asyncsignalsafe
|
||||
* @norestart
|
||||
*/
|
||||
int sleep(uint32_t seconds) {
|
||||
return nanosleep(&(struct timespec){seconds, 0}, NULL);
|
||||
unsigned sleep(unsigned seconds) {
|
||||
int err;
|
||||
unsigned unslept;
|
||||
struct timespec tv = {seconds};
|
||||
err = errno;
|
||||
nanosleep(&tv, &tv);
|
||||
errno = err;
|
||||
unslept = tv.tv_sec;
|
||||
if (tv.tv_nsec && unslept < UINT_MAX) {
|
||||
++unslept;
|
||||
}
|
||||
return unslept;
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ COSMOPOLITAN_C_START_
|
|||
#define BPF_MAXINSNS 4096
|
||||
|
||||
#define BPF_CLASS(code) ((code)&0x07)
|
||||
#define BPF_LD 0x00 /* load ops */
|
||||
#define BPF_LDX 0x01 /* load into register */
|
||||
#define BPF_LD 0x00 /* load into accumulator */
|
||||
#define BPF_LDX 0x01 /* load into index register */
|
||||
#define BPF_ST 0x02 /* store from immediate */
|
||||
#define BPF_STX 0x03 /* store from register */
|
||||
#define BPF_ALU 0x04 /* 32-bit arithmetic */
|
||||
|
@ -19,6 +19,7 @@ COSMOPOLITAN_C_START_
|
|||
#define BPF_W 0x00 /* 32-bit */
|
||||
#define BPF_H 0x08 /* 16-bit */
|
||||
#define BPF_B 0x10 /* 8-bit */
|
||||
#define BPF_DW 0x18 /* 64-bit (eBPF only) */
|
||||
|
||||
#define BPF_MODE(code) ((code)&0xe0)
|
||||
#define BPF_IMM 0x00 /* 64-bit immediate */
|
||||
|
@ -52,7 +53,6 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
#define BPF_JMP32 0x06
|
||||
#define BPF_ALU64 0x07
|
||||
#define BPF_DW 0x18
|
||||
#define BPF_ATOMIC 0xc0
|
||||
#define BPF_XADD 0xc0
|
||||
#define BPF_MOV 0xb0
|
||||
|
|
|
@ -25,6 +25,7 @@ struct rusage {
|
|||
int getrusage(int, struct rusage *);
|
||||
int wait3(int *, int, struct rusage *);
|
||||
int wait4(int, int *, int, struct rusage *);
|
||||
void _addrusage(struct rusage *, const struct rusage *);
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_RUSAGE_H_ */
|
||||
|
|
|
@ -6,5 +6,12 @@ struct sched_param {
|
|||
int32_t sched_priority;
|
||||
};
|
||||
|
||||
int sched_get_priority_max(int);
|
||||
int sched_get_priority_min(int);
|
||||
int sched_getparam(int, struct sched_param *);
|
||||
int sched_getscheduler(int);
|
||||
int sched_setparam(int, const struct sched_param *);
|
||||
int sched_setscheduler(int, int, const struct sched_param *);
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SCHED_PARAM_H_ */
|
||||
|
|
|
@ -8,6 +8,9 @@ struct timespec {
|
|||
};
|
||||
|
||||
int sys_futex(int *, int, int, const struct timespec *, int *);
|
||||
bool _timespec_gt(struct timespec, struct timespec);
|
||||
struct timespec _timespec_add(struct timespec, struct timespec);
|
||||
struct timespec _timespec_sub(struct timespec, struct timespec);
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_TIMESPEC_H_ */
|
||||
|
|
34
libc/calls/struct/timespec_gt.c
Normal file
34
libc/calls/struct/timespec_gt.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*-*- 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 2022 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/struct/timespec.h"
|
||||
|
||||
/**
|
||||
* Returns true if timespec `x` is greater than `y`.
|
||||
*/
|
||||
bool _timespec_gt(struct timespec x, struct timespec y) {
|
||||
if (x.tv_sec > y.tv_sec) {
|
||||
return true;
|
||||
}
|
||||
if (x.tv_sec == y.tv_sec) {
|
||||
if (x.tv_nsec > y.tv_nsec) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -8,6 +8,7 @@ struct timeval {
|
|||
};
|
||||
|
||||
int lutimes(const char *, const struct timeval[2]);
|
||||
struct timeval _timeval_add(struct timeval, struct timeval);
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_TIMEVAL_H_ */
|
||||
|
|
|
@ -74,8 +74,6 @@ i32 sys_pipe2(i32[hasatleast 2], u32) hidden;
|
|||
i32 sys_pledge(const char *, const char *) hidden;
|
||||
i32 sys_posix_openpt(i32) hidden;
|
||||
i32 sys_renameat(i32, const char *, i32, const char *) hidden;
|
||||
i32 sys_sched_setaffinity(i32, u64, const void *) hidden;
|
||||
i32 sys_sched_yield(void) hidden;
|
||||
i32 sys_setgid(i32) hidden;
|
||||
i32 sys_setpgid(i32, i32) hidden;
|
||||
i32 sys_setpriority(i32, u32, i32) hidden;
|
||||
|
@ -103,7 +101,6 @@ i64 sys_pwrite(i32, const void *, u64, i64, i64) hidden;
|
|||
i64 sys_read(i32, void *, u64) hidden;
|
||||
i64 sys_readlink(const char *, char *, u64) hidden;
|
||||
i64 sys_readlinkat(int, const char *, char *, u64) hidden;
|
||||
i64 sys_sched_getaffinity(i32, u64, void *) hidden;
|
||||
i64 sys_sendfile(i32, i32, i64 *, u64) hidden;
|
||||
i64 sys_splice(i32, i64 *, i32, i64 *, u64, u32) hidden;
|
||||
i64 sys_write(i32, const void *, u64) hidden;
|
||||
|
|
|
@ -13,6 +13,7 @@ int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX], int) hidden;
|
|||
int __mkntpathat(int, const char *, int, char16_t[hasatleast PATH_MAX]) hidden;
|
||||
int __sample_pids(int[hasatleast 64], int64_t[hasatleast 64], bool) hidden;
|
||||
int ntaccesscheck(const char16_t *, uint32_t) paramsnonnull() hidden;
|
||||
int sys_pause_nt(void) hidden;
|
||||
int64_t __fix_enotdir(int64_t, char16_t *) hidden;
|
||||
int64_t __fix_enotdir3(int64_t, char16_t *, char16_t *) hidden;
|
||||
int64_t __winerr(void) nocallback privileged;
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/math.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
|
||||
/**
|
||||
* Adds two nanosecond timestamps.
|
||||
*/
|
||||
struct timespec AddTimespec(struct timespec x, struct timespec y) {
|
||||
struct timespec _timespec_add(struct timespec x, struct timespec y) {
|
||||
x.tv_sec += y.tv_sec;
|
||||
x.tv_nsec += y.tv_nsec;
|
||||
if (x.tv_nsec >= 10000000000) {
|
32
libc/calls/timespec_sub.c
Normal file
32
libc/calls/timespec_sub.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 2022 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/struct/timespec.h"
|
||||
|
||||
/**
|
||||
* Subtracts two nanosecond timestamps.
|
||||
*/
|
||||
struct timespec _timespec_sub(struct timespec x, struct timespec y) {
|
||||
x.tv_sec -= y.tv_sec;
|
||||
x.tv_nsec -= y.tv_nsec;
|
||||
if (x.tv_nsec < 0) {
|
||||
x.tv_nsec += 1000000000;
|
||||
x.tv_sec -= 1;
|
||||
}
|
||||
return x;
|
||||
}
|
|
@ -16,17 +16,21 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
/**
|
||||
* Sleeps for particular amount of microseconds.
|
||||
* Sleeps for particular number of microseconds.
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise EINTR if a signal was delivered while sleeping
|
||||
* @see nanosleep(), sleep()
|
||||
* @norestart
|
||||
*/
|
||||
int usleep(uint32_t microseconds) {
|
||||
return nanosleep(&(struct timespec){(uint64_t)microseconds / 1000000,
|
||||
(uint64_t)microseconds % 1000000 * 1000},
|
||||
NULL);
|
||||
int usleep(uint32_t micros) {
|
||||
struct timespec ts = {
|
||||
micros / 1000000,
|
||||
micros % 1000000 * 1000,
|
||||
};
|
||||
return nanosleep(&ts, 0);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
@ -37,10 +38,8 @@ int sys_utimensat(int dirfd, const char *path, const struct timespec ts[2],
|
|||
if (rc == -1 && errno == ENOSYS && path) {
|
||||
errno = olderr;
|
||||
if (ts) {
|
||||
tv[0].tv_sec = ts[0].tv_sec;
|
||||
tv[0].tv_usec = ts[0].tv_nsec / 1000;
|
||||
tv[1].tv_sec = ts[1].tv_sec;
|
||||
tv[1].tv_usec = ts[1].tv_nsec / 1000;
|
||||
tv[0] = _timespec2timeval(ts[0]);
|
||||
tv[1] = _timespec2timeval(ts[1]);
|
||||
rc = sys_utimes(path, tv);
|
||||
} else {
|
||||
rc = sys_utimes(path, NULL);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/utime.h"
|
||||
|
@ -40,20 +41,16 @@ int sys_utimensat_xnu(int dirfd, const char *path, const struct timespec ts[2],
|
|||
if (ts[0].tv_nsec == UTIME_NOW) {
|
||||
tv[0] = now;
|
||||
} else if (ts[0].tv_nsec == UTIME_OMIT) {
|
||||
tv[0].tv_sec = st.st_atim.tv_sec;
|
||||
tv[0].tv_usec = st.st_atim.tv_nsec / 1000;
|
||||
tv[0] = _timespec2timeval(st.st_atim);
|
||||
} else {
|
||||
tv[0].tv_sec = ts[0].tv_sec;
|
||||
tv[0].tv_usec = ts[0].tv_nsec / 1000;
|
||||
tv[0] = _timespec2timeval(ts[0]);
|
||||
}
|
||||
if (ts[1].tv_nsec == UTIME_NOW) {
|
||||
tv[1] = now;
|
||||
} else if (ts[1].tv_nsec == UTIME_OMIT) {
|
||||
tv[1].tv_sec = st.st_mtim.tv_sec;
|
||||
tv[1].tv_usec = st.st_mtim.tv_nsec / 1000;
|
||||
tv[1] = _timespec2timeval(st.st_mtim);
|
||||
} else {
|
||||
tv[1].tv_sec = ts[1].tv_sec;
|
||||
tv[1].tv_usec = ts[1].tv_nsec / 1000;
|
||||
tv[1] = _timespec2timeval(ts[1]);
|
||||
}
|
||||
} else {
|
||||
tv[0] = now;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue