mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Introduce clock_nanosleep()
This commit is contained in:
parent
fe3216e961
commit
b75a4654cf
33 changed files with 553 additions and 100 deletions
|
@ -19,7 +19,7 @@
|
|||
#include "libc/calls/struct/timespec.h"
|
||||
|
||||
/**
|
||||
* Compares two nanosecond timestamps.
|
||||
* Compares nanosecond timestamps.
|
||||
*/
|
||||
int _timespec_cmp(struct timespec a, struct timespec b) {
|
||||
int cmp;
|
||||
|
|
|
@ -20,14 +20,24 @@
|
|||
#include "libc/limits.h"
|
||||
|
||||
/**
|
||||
* Converts timespec interval to microseconds.
|
||||
* Reduces `ts` from 1e-9 to 1e-6 granularity w/ ceil rounding.
|
||||
*/
|
||||
int64_t _timespec_tomicros(struct timespec x) {
|
||||
int64_t _timespec_tomicros(struct timespec ts) {
|
||||
int64_t us;
|
||||
if (!__builtin_mul_overflow(x.tv_sec, 1000000ul, &us) &&
|
||||
!__builtin_add_overflow(us, x.tv_nsec / 1000, &us)) {
|
||||
// reduce precision from nanos to micros
|
||||
if (ts.tv_nsec <= 999999000) {
|
||||
ts.tv_nsec = (ts.tv_nsec + 999) / 1000;
|
||||
} else {
|
||||
ts.tv_nsec = 0;
|
||||
if (ts.tv_sec < INT64_MAX) {
|
||||
ts.tv_sec += 1;
|
||||
}
|
||||
}
|
||||
// convert to scalar result
|
||||
if (!__builtin_mul_overflow(ts.tv_sec, 1000000ul, &us) &&
|
||||
!__builtin_add_overflow(us, ts.tv_nsec, &us)) {
|
||||
return us;
|
||||
} else if (x.tv_sec < 0) {
|
||||
} else if (ts.tv_sec < 0) {
|
||||
return INT64_MIN;
|
||||
} else {
|
||||
return INT64_MAX;
|
||||
|
|
|
@ -20,14 +20,24 @@
|
|||
#include "libc/limits.h"
|
||||
|
||||
/**
|
||||
* Converts timespec interval to milliseconds.
|
||||
* Reduces `ts` from 1e-9 to 1e-3 granularity w/ ceil rounding.
|
||||
*/
|
||||
int64_t _timespec_tomillis(struct timespec x) {
|
||||
int64_t _timespec_tomillis(struct timespec ts) {
|
||||
int64_t ms;
|
||||
if (!__builtin_mul_overflow(x.tv_sec, 1000ul, &ms) &&
|
||||
!__builtin_add_overflow(ms, x.tv_nsec / 1000000, &ms)) {
|
||||
// reduce precision from nanos to millis
|
||||
if (ts.tv_nsec <= 999000000) {
|
||||
ts.tv_nsec = (ts.tv_nsec + 999999) / 1000000;
|
||||
} else {
|
||||
ts.tv_nsec = 0;
|
||||
if (ts.tv_sec < INT64_MAX) {
|
||||
ts.tv_sec += 1;
|
||||
}
|
||||
}
|
||||
// convert to scalar result
|
||||
if (!__builtin_mul_overflow(ts.tv_sec, 1000ul, &ms) &&
|
||||
!__builtin_add_overflow(ms, ts.tv_nsec, &ms)) {
|
||||
return ms;
|
||||
} else if (x.tv_sec < 0) {
|
||||
} else if (ts.tv_sec < 0) {
|
||||
return INT64_MIN;
|
||||
} else {
|
||||
return INT64_MAX;
|
||||
|
|
|
@ -18,6 +18,13 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
|
||||
/**
|
||||
* Reduces `ts` from 1e-9 to 1e-6 granularity w/ ceil rounding.
|
||||
*/
|
||||
struct timeval _timespec_totimeval(struct timespec ts) {
|
||||
return (struct timeval){ts.tv_sec, ts.tv_nsec / 1000};
|
||||
if (ts.tv_nsec < 1000000000 - 999) {
|
||||
return (struct timeval){ts.tv_sec, (ts.tv_nsec + 999) / 1000};
|
||||
} else {
|
||||
return (struct timeval){ts.tv_sec + 1, 0};
|
||||
}
|
||||
}
|
||||
|
|
30
libc/calls/_timeval_cmp.c
Normal file
30
libc/calls/_timeval_cmp.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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/timeval.h"
|
||||
|
||||
/**
|
||||
* Compares microseconds timestamps.
|
||||
*/
|
||||
int _timeval_cmp(struct timeval a, struct timeval b) {
|
||||
int cmp;
|
||||
if (!(cmp = (a.tv_sec > b.tv_sec) - (a.tv_sec < b.tv_sec))) {
|
||||
cmp = (a.tv_usec > b.tv_usec) - (a.tv_usec < b.tv_usec);
|
||||
}
|
||||
return cmp;
|
||||
}
|
26
libc/calls/_timeval_eq.c
Normal file
26
libc/calls/_timeval_eq.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*-*- 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/timeval.h"
|
||||
|
||||
/**
|
||||
* Checks if 𝑥 = 𝑦.
|
||||
*/
|
||||
bool _timeval_eq(struct timeval x, struct timeval y) {
|
||||
return x.tv_sec == y.tv_sec && x.tv_usec == y.tv_usec;
|
||||
}
|
34
libc/calls/_timeval_gt.c
Normal file
34
libc/calls/_timeval_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/timeval.h"
|
||||
|
||||
/**
|
||||
* Returns true if timeval `x` is greater than `y`.
|
||||
*/
|
||||
bool _timeval_gt(struct timeval x, struct timeval y) {
|
||||
if (x.tv_sec > y.tv_sec) {
|
||||
return true;
|
||||
}
|
||||
if (x.tv_sec == y.tv_sec) {
|
||||
if (x.tv_usec > y.tv_usec) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
28
libc/calls/_timeval_gte.c
Normal file
28
libc/calls/_timeval_gte.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/struct/timeval.h"
|
||||
|
||||
/**
|
||||
* Checks if 𝑥 ≥ 𝑦.
|
||||
*/
|
||||
bool _timeval_gte(struct timeval x, struct timeval y) {
|
||||
if (x.tv_sec > y.tv_sec) return true;
|
||||
if (x.tv_sec < y.tv_sec) return false;
|
||||
return x.tv_usec >= y.tv_usec;
|
||||
}
|
32
libc/calls/_timeval_sub.c
Normal file
32
libc/calls/_timeval_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/timeval.h"
|
||||
|
||||
/**
|
||||
* Subtracts two nanosecond timestamps.
|
||||
*/
|
||||
struct timeval _timeval_sub(struct timeval a, struct timeval b) {
|
||||
a.tv_sec -= b.tv_sec;
|
||||
if (a.tv_usec < b.tv_usec) {
|
||||
a.tv_usec += 1000000;
|
||||
a.tv_sec--;
|
||||
}
|
||||
a.tv_usec -= b.tv_usec;
|
||||
return a;
|
||||
}
|
57
libc/calls/clock_nanosleep-nt.c
Normal file
57
libc/calls/clock_nanosleep-nt.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*-*- 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 2021 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/struct/timespec.h"
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/consts/timer.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_clock_nanosleep_nt(int clock, int flags,
|
||||
const struct timespec *req,
|
||||
struct timespec *rem) {
|
||||
struct timespec now, abs;
|
||||
if (flags & TIMER_ABSTIME) {
|
||||
abs = *req;
|
||||
for (;;) {
|
||||
if (sys_clock_gettime_nt(clock, &now)) return -1;
|
||||
if (_timespec_gte(now, abs)) return 0;
|
||||
if (_check_interrupts(false, g_fds.p)) return eintr();
|
||||
SleepEx(MIN(__SIG_POLLING_INTERVAL_MS,
|
||||
_timespec_tomillis(_timespec_sub(abs, now))),
|
||||
false);
|
||||
}
|
||||
} else {
|
||||
if (sys_clock_gettime_nt(clock, &now)) return -1;
|
||||
abs = _timespec_add(now, *req);
|
||||
for (;;) {
|
||||
sys_clock_gettime_nt(clock, &now);
|
||||
if (_timespec_gte(now, abs)) return 0;
|
||||
if (_check_interrupts(false, g_fds.p)) {
|
||||
if (rem) *rem = _timespec_sub(abs, now);
|
||||
return eintr();
|
||||
}
|
||||
SleepEx(MIN(__SIG_POLLING_INTERVAL_MS,
|
||||
_timespec_tomillis(_timespec_sub(abs, now))),
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,29 +17,29 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
// we don't want instrumentation because:
|
||||
// - nanosleep() depends on this and ftrace can take microsecs
|
||||
|
||||
/**
|
||||
* Converts `struct timespec` to `struct timeval`.
|
||||
*
|
||||
* This divides ts.tv_nsec by 1000 with upward rounding and overflow
|
||||
* handling. Your ts.tv_nsec must be on the interval `[0,1000000000)`
|
||||
* otherwise `{-1, -1}` is returned.
|
||||
*
|
||||
* @return converted timeval whose tv_usec will be -1 on error
|
||||
*/
|
||||
noinstrument struct timeval _timespec2timeval(struct timespec ts) {
|
||||
if (0 <= ts.tv_nsec && ts.tv_nsec < 1000000000) {
|
||||
if (0 <= ts.tv_nsec && ts.tv_nsec < 1000000000 - 999) {
|
||||
return (struct timeval){ts.tv_sec, (ts.tv_nsec + 999) / 1000};
|
||||
int sys_clock_nanosleep_openbsd(int clock, int flags,
|
||||
const struct timespec *req,
|
||||
struct timespec *rem) {
|
||||
int res;
|
||||
struct timespec now, rel;
|
||||
if (clock == CLOCK_REALTIME) {
|
||||
if (!flags) {
|
||||
res = sys_nanosleep(req, rem);
|
||||
} else {
|
||||
return (struct timeval){ts.tv_sec + 1, 0};
|
||||
sys_clock_gettime(clock, &now);
|
||||
if (_timespec_gt(*req, now)) {
|
||||
rel = _timespec_sub(*req, now);
|
||||
res = sys_nanosleep(&rel, 0);
|
||||
} else {
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return (struct timeval){-1, -1};
|
||||
res = enotsup();
|
||||
}
|
||||
return res;
|
||||
}
|
49
libc/calls/clock_nanosleep-xnu.c
Normal file
49
libc/calls/clock_nanosleep-xnu.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*-*- 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.internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/struct/timeval.internal.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/consts/timer.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int sys_clock_nanosleep_xnu(int clock, int flags, const struct timespec *req,
|
||||
struct timespec *rem) {
|
||||
int res;
|
||||
struct timeval now, abs, rel;
|
||||
if (clock == CLOCK_REALTIME) {
|
||||
if (flags & TIMER_ABSTIME) {
|
||||
abs = _timespec_totimeval(*req);
|
||||
sys_gettimeofday_xnu(&now, 0, 0);
|
||||
if (_timeval_gt(abs, now)) {
|
||||
rel = _timeval_sub(abs, now);
|
||||
res = sys_select(0, 0, 0, 0, &rel);
|
||||
} else {
|
||||
res = 0;
|
||||
}
|
||||
} else {
|
||||
res = sys_nanosleep_xnu(req, rem);
|
||||
}
|
||||
} else {
|
||||
res = enotsup();
|
||||
}
|
||||
return res;
|
||||
}
|
123
libc/calls/clock_nanosleep.c
Normal file
123
libc/calls/clock_nanosleep.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*-*- 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/struct/timespec.h"
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/struct/timeval.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/consts/timer.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Sleeps for particular amount of time.
|
||||
*
|
||||
* Here's how you could sleep for one second:
|
||||
*
|
||||
* clock_nanosleep(0, 0, &(struct timespec){1}, 0);
|
||||
*
|
||||
* Your sleep will be interrupted automatically if you do something like
|
||||
* press ctrl-c during the wait. That's an `EINTR` error and it lets you
|
||||
* immediately react to status changes. This is always the case, even if
|
||||
* you're using `SA_RESTART` since this is a `@norestart` system call.
|
||||
*
|
||||
* void OnCtrlC(int sig) {} // EINTR only happens after delivery
|
||||
* signal(SIGINT, OnCtrlC); // do delivery rather than kill proc
|
||||
* printf("save me from sleeping forever by pressing ctrl-c\n");
|
||||
* clock_nanosleep(0, 0, &(struct timespec){INT_MAX}, 0);
|
||||
* printf("you're my hero\n");
|
||||
*
|
||||
* If you want to perform an uninterruptible sleep without having to use
|
||||
* sigprocmask() to block all signals then this function provides a good
|
||||
* solution to that problem. For example:
|
||||
*
|
||||
* struct timespec rel, now, abs;
|
||||
* clock_gettime(CLOCK_REALTIME, &now);
|
||||
* rel = _timespec_frommillis(100);
|
||||
* abs = _timespec_add(now, rel);
|
||||
* while (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &abs, 0));
|
||||
*
|
||||
* will accurately spin on `EINTR` errors. That way you're not impeding
|
||||
* signal delivery and you're not losing precision on your wait timeout.
|
||||
* This function has first-class support on Linux, FreeBSD, and NetBSD;
|
||||
* on OpenBSD it's good; on XNU it's bad; and on Windows it's ugly.
|
||||
*
|
||||
* @param clock should be `CLOCK_REALTIME` and you may consult the docs
|
||||
* of your preferred platforms to see what other clocks might work
|
||||
* @param flags can be 0 for relative and `TIMER_ABSTIME` for absolute
|
||||
* @param req can be a relative or absolute time, depending on `flags`
|
||||
* @param rem will be updated with the unslept time only when `flags`
|
||||
* is zero, otherwise `rem` is ignored; when this call completes,
|
||||
* that means `rem` will be set to `{0, 0}`, and shall only have
|
||||
* something else when -1 is returned with `EINTR`, which means
|
||||
* there was a signal delivery that happened mid-sleep and `rem`
|
||||
* reflects (poorly) how much remaining time was left over, in
|
||||
* case the caller wishes to retry the sleep operation, noting
|
||||
* this isn't recommended since relative timestamps can drift
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise EINTR when a signal got delivered while we were waiting
|
||||
* @raise ENOTSUP if `clock` is known but we can't use it here
|
||||
* @raise EINVAL if `clock` is unknown to current platform
|
||||
* @raise EINVAL if `flags` has an unrecognized value
|
||||
* @raise EINVAL if `req->tv_nsec ∉ [0,1000000000)`
|
||||
* @raise EFAULT if bad memory was passed
|
||||
* @raise ENOSYS on bare metal
|
||||
* @norestart
|
||||
*/
|
||||
int clock_nanosleep(int clock, int flags, 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();
|
||||
} else if (clock == 127 || //
|
||||
(flags & ~TIMER_ABSTIME) || //
|
||||
req->tv_sec < 0 || //
|
||||
!(0 <= req->tv_nsec && req->tv_nsec <= 999999999)) {
|
||||
rc = einval();
|
||||
} else if (IsLinux() || IsFreebsd() || IsNetbsd()) {
|
||||
rc = sys_clock_nanosleep(clock, flags, req, rem);
|
||||
} else if (IsXnu()) {
|
||||
rc = sys_clock_nanosleep_xnu(clock, flags, req, rem);
|
||||
} else if (IsOpenbsd()) {
|
||||
rc = sys_clock_nanosleep_openbsd(clock, flags, req, rem);
|
||||
} else if (IsMetal()) {
|
||||
rc = enosys();
|
||||
} else {
|
||||
rc = sys_clock_nanosleep_nt(clock, flags, 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 && !flags && rem) {
|
||||
rem->tv_sec = 0;
|
||||
rem->tv_nsec = 0;
|
||||
}
|
||||
|
||||
STRACE("clock_nanosleep(%s, %s, %s, [%s]) → %d% m", DescribeClockName(clock),
|
||||
DescribeSleepFlags(flags), flags, DescribeTimespec(0, req),
|
||||
DescribeTimespec(rc, rem), rc);
|
||||
|
||||
return rc;
|
||||
}
|
|
@ -20,8 +20,9 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
|
@ -52,10 +53,7 @@ textwindows int sys_nanosleep_nt(const struct timespec *req,
|
|||
}
|
||||
|
||||
// convert timespec to milliseconds
|
||||
if (__builtin_mul_overflow(req->tv_sec, 1000, &ms) ||
|
||||
__builtin_add_overflow(ms, (req->tv_nsec + 999999) / 1000000, &ms)) {
|
||||
ms = INT64_MAX;
|
||||
}
|
||||
ms = _timespec_tomillis(*req);
|
||||
|
||||
for (toto = ms;;) {
|
||||
|
||||
|
|
|
@ -19,40 +19,34 @@
|
|||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/struct/timeval.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
|
||||
// nanosleep() on xnu: a bloodbath of a polyfill
|
||||
// consider using clock_nanosleep(TIMER_ABSTIME)
|
||||
int sys_nanosleep_xnu(const struct timespec *req, struct timespec *rem) {
|
||||
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);
|
||||
|
||||
struct timeval wt, t1, t2, td;
|
||||
if (rem) sys_gettimeofday_xnu(&t1, 0, 0);
|
||||
wt = _timespec_totimeval(*req); // rounds up
|
||||
rc = sys_select(0, 0, 0, 0, &wt);
|
||||
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) {
|
||||
// xnu select() doesn't modify timeout
|
||||
// so we need, yet another system call
|
||||
sys_gettimeofday_xnu(&t2, 0, 0);
|
||||
td = _timeval_sub(t2, t1);
|
||||
if (_timeval_gte(td, wt)) {
|
||||
rem->tv_sec = 0;
|
||||
rem->tv_nsec = 0;
|
||||
} else {
|
||||
*rem = _timeval_totimespec(_timeval_sub(wt, td));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -23,25 +23,23 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Sleeps for a particular amount of time.
|
||||
* Sleeps for relative 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`.
|
||||
* 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()
|
||||
* @see clock_nanosleep()
|
||||
* @norestart
|
||||
*/
|
||||
int nanosleep(const struct timespec *req, struct timespec *rem) {
|
||||
|
@ -53,7 +51,9 @@ int nanosleep(const struct timespec *req, struct timespec *rem) {
|
|||
} else if (req->tv_sec < 0 ||
|
||||
!(0 <= req->tv_nsec && req->tv_nsec <= 999999999)) {
|
||||
rc = einval();
|
||||
} else if (!IsWindows() && !IsMetal() && !IsXnu()) {
|
||||
} else if (IsLinux()) {
|
||||
rc = sys_clock_nanosleep(CLOCK_REALTIME, 0, req, rem);
|
||||
} else if (IsOpenbsd() || IsFreebsd() || IsNetbsd()) {
|
||||
rc = sys_nanosleep(req, rem);
|
||||
} else if (IsXnu()) {
|
||||
rc = sys_nanosleep_xnu(req, rem);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* 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()
|
||||
* @see clock_nanosleep()
|
||||
* @asyncsignalsafe
|
||||
* @norestart
|
||||
*/
|
||||
|
|
|
@ -10,6 +10,7 @@ struct timespec {
|
|||
|
||||
int clock_getres(int, struct timespec *);
|
||||
int clock_gettime(int, struct timespec *);
|
||||
int clock_nanosleep(int, int, const struct timespec *, struct timespec *);
|
||||
int futimens(int, const struct timespec[2]);
|
||||
int nanosleep(const struct timespec *, struct timespec *);
|
||||
int sys_futex(int *, int, int, const struct timespec *, int *);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "libc/mem/alloca.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
/* clang-format off */
|
||||
|
||||
int __sys_utimensat(int, const char *, const struct timespec[2], int) hidden;
|
||||
int __utimens(int, const char *, const struct timespec[2], int) hidden;
|
||||
|
@ -11,6 +12,10 @@ int sys_clock_getres(int, struct timespec *) hidden;
|
|||
int sys_clock_gettime(int, struct timespec *) hidden;
|
||||
int sys_clock_gettime_nt(int, struct timespec *) hidden;
|
||||
int sys_clock_gettime_xnu(int, struct timespec *) hidden;
|
||||
int sys_clock_nanosleep(int, int, const struct timespec *, struct timespec *) hidden;
|
||||
int sys_clock_nanosleep_nt(int, int, const struct timespec *, struct timespec *) hidden;
|
||||
int sys_clock_nanosleep_xnu(int, int, const struct timespec *, struct timespec *) hidden;
|
||||
int sys_clock_nanosleep_openbsd(int, int, const struct timespec *, struct timespec *) hidden;
|
||||
int sys_futimens(int, const struct timespec[2]) hidden;
|
||||
int sys_nanosleep(const struct timespec *, struct timespec *) hidden;
|
||||
int sys_nanosleep_nt(const struct timespec *, struct timespec *) hidden;
|
||||
|
|
|
@ -16,9 +16,14 @@ int gettimeofday(struct timeval *, struct timezone *);
|
|||
int lutimes(const char *, const struct timeval[2]);
|
||||
int utimes(const char *, const struct timeval[2]);
|
||||
|
||||
struct timeval _timeval_add(struct timeval, struct timeval);
|
||||
struct timeval _timespec_totimeval(struct timespec);
|
||||
struct timespec _timeval_totimespec(struct timeval);
|
||||
int _timeval_cmp(struct timeval, struct timeval) pureconst;
|
||||
bool _timeval_eq(struct timeval, struct timeval) pureconst;
|
||||
bool _timeval_gt(struct timeval, struct timeval) pureconst;
|
||||
bool _timeval_gte(struct timeval, struct timeval) pureconst;
|
||||
struct timeval _timeval_add(struct timeval, struct timeval) pureconst;
|
||||
struct timeval _timeval_sub(struct timeval, struct timeval) pureconst;
|
||||
struct timeval _timespec_totimeval(struct timespec) pureconst;
|
||||
struct timespec _timeval_totimespec(struct timeval) pureconst;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -24,13 +24,11 @@
|
|||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise EINTR if a signal was delivered while sleeping
|
||||
* @see nanosleep(), sleep()
|
||||
* @see clock_nanosleep()
|
||||
* @norestart
|
||||
*/
|
||||
int usleep(uint32_t micros) {
|
||||
struct timespec ts = {
|
||||
micros / 1000000,
|
||||
micros % 1000000 * 1000,
|
||||
};
|
||||
struct timespec ts;
|
||||
ts = _timespec_frommicros(micros);
|
||||
return nanosleep(&ts, 0);
|
||||
}
|
||||
|
|
|
@ -39,8 +39,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] = _timespec2timeval(ts[0]);
|
||||
tv[1] = _timespec2timeval(ts[1]);
|
||||
tv[0] = _timespec_totimeval(ts[0]);
|
||||
tv[1] = _timespec_totimeval(ts[1]);
|
||||
rc = sys_utimes(path, tv);
|
||||
} else {
|
||||
rc = sys_utimes(path, NULL);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/struct/timeval.internal.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
|
@ -41,16 +42,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] = _timespec2timeval(st.st_atim);
|
||||
tv[0] = _timespec_totimeval(st.st_atim);
|
||||
} else {
|
||||
tv[0] = _timespec2timeval(ts[0]);
|
||||
tv[0] = _timespec_totimeval(ts[0]);
|
||||
}
|
||||
if (ts[1].tv_nsec == UTIME_NOW) {
|
||||
tv[1] = now;
|
||||
} else if (ts[1].tv_nsec == UTIME_OMIT) {
|
||||
tv[1] = _timespec2timeval(st.st_mtim);
|
||||
tv[1] = _timespec_totimeval(st.st_mtim);
|
||||
} else {
|
||||
tv[1] = _timespec2timeval(ts[1]);
|
||||
tv[1] = _timespec_totimeval(ts[1]);
|
||||
}
|
||||
} else {
|
||||
tv[0] = now;
|
||||
|
|
|
@ -43,7 +43,6 @@ size_t wcsxfrm(wchar_t *, const wchar_t *, size_t);
|
|||
│ cosmopolitan § conversion » time ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
struct timeval _timespec2timeval(struct timespec);
|
||||
int64_t DosDateTimeToUnix(unsigned, unsigned) libcesque nosideeffect;
|
||||
struct timeval WindowsTimeToTimeVal(int64_t) libcesque nosideeffect;
|
||||
struct timespec WindowsTimeToTimeSpec(int64_t) libcesque nosideeffect;
|
||||
|
|
|
@ -50,6 +50,7 @@ const char *DescribeRemapFlags(char[48], int);
|
|||
const char *DescribeRlimitName(char[20], int);
|
||||
const char *DescribeSchedPolicy(char[48], int);
|
||||
const char *DescribeSeccompOperation(int);
|
||||
const char *DescribeSleepFlags(char[16], int);
|
||||
const char *DescribeSockLevel(char[12], int);
|
||||
const char *DescribeSockOptname(char[32], int, int);
|
||||
const char *DescribeSocketFamily(char[12], int);
|
||||
|
@ -92,6 +93,7 @@ const char *DescribeWhence(char[12], int);
|
|||
#define DescribeRemapFlags(x) DescribeRemapFlags(alloca(48), x)
|
||||
#define DescribeRlimitName(rl) DescribeRlimitName(alloca(20), rl)
|
||||
#define DescribeSchedPolicy(x) DescribeSchedPolicy(alloca(48), x)
|
||||
#define DescribeSleepFlags(x) DescribeSleepFlags(alloca(16), x)
|
||||
#define DescribeSockLevel(x) DescribeSockLevel(alloca(12), x)
|
||||
#define DescribeSockOptname(x, y) DescribeSockOptname(alloca(32), x, y)
|
||||
#define DescribeSocketFamily(x) DescribeSocketFamily(alloca(12), x)
|
||||
|
|
37
libc/intrin/describesleepflags.c
Normal file
37
libc/intrin/describesleepflags.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*-*- 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/fmt/itoa.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/sysv/consts/timer.h"
|
||||
|
||||
/**
|
||||
* Describes clock_nanosleep() flags argument.
|
||||
*/
|
||||
const char *(DescribeSleepFlags)(char buf[16], int x) {
|
||||
switch (x) {
|
||||
case 0:
|
||||
return "0";
|
||||
case TIMER_ABSTIME:
|
||||
return "TIMER_ABSTIME";
|
||||
default:
|
||||
FormatInt32(buf, x);
|
||||
return buf;
|
||||
}
|
||||
}
|
|
@ -111,10 +111,10 @@ privileged void __enable_tls(void) {
|
|||
// malloc() being linked, which links _mapanon(). otherwise
|
||||
// if you exceed this, you need to STATIC_YOINK("_mapanon").
|
||||
// please note that it's probably too early to call calloc()
|
||||
assert(_weaken(_mapanon));
|
||||
_npassert(_weaken(_mapanon));
|
||||
siz = ROUNDUP(siz, FRAMESIZE);
|
||||
mem = _weaken(_mapanon)(siz);
|
||||
assert(mem);
|
||||
_npassert(mem);
|
||||
}
|
||||
if (IsAsan()) {
|
||||
// poison the space between .tdata and .tbss
|
||||
|
@ -140,7 +140,7 @@ privileged void __enable_tls(void) {
|
|||
int ax, dx;
|
||||
if (IsWindows()) {
|
||||
__tls_index = __imp_TlsAlloc();
|
||||
assert(0 <= __tls_index && __tls_index < 64);
|
||||
_npassert(0 <= __tls_index && __tls_index < 64);
|
||||
asm("mov\t%1,%%gs:%0" : "=m"(*((long *)0x1480 + __tls_index)) : "r"(tib));
|
||||
} else if (IsFreebsd()) {
|
||||
sys_enable_tls(AMD64_SET_FSBASE, tib);
|
||||
|
|
|
@ -34,11 +34,11 @@
|
|||
* @raise EPERM if terminal is already controlling another sid
|
||||
*/
|
||||
int login_tty(int fd) {
|
||||
int rc;
|
||||
int i, rc;
|
||||
if (IsLinux() || IsBsd()) {
|
||||
setsid();
|
||||
if (!sys_ioctl(fd, TIOCSCTTY, 0)) {
|
||||
for (int i = 0; i < 3; ++i) dup2(fd, i);
|
||||
for (i = 0; i < 3; ++i) dup2(fd, i);
|
||||
if (fd > 2) close(fd);
|
||||
rc = 0;
|
||||
} else {
|
||||
|
|
|
@ -17,14 +17,13 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#define ShouldUseMsabiAttribute() 1
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asmflag.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/enum/pageflags.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
|
|
|
@ -71,6 +71,7 @@ scall sys_dup 0x0290290292029020 globl hidden
|
|||
scall sys_dup2 0x05a05a05a205a021 globl hidden
|
||||
scall sys_pause 0xfffffffffffff022 globl hidden
|
||||
scall sys_nanosleep 0x1ae05b0f0ffff023 globl hidden
|
||||
scall sys_clock_nanosleep 0x1ddfff0f4ffff0e6 globl hidden
|
||||
scall sys_getitimer 0x1aa0460562056024 globl hidden
|
||||
scall sys_setitimer 0x1a90450532053026 globl hidden
|
||||
scall sys_alarm 0xfffffffffffff025 globl hidden
|
||||
|
@ -264,7 +265,6 @@ scall sys_ktimer_settime 0xffffff0edfffffff globl # no wrapper
|
|||
scall sys_clock_settime 0x1ac0580e9ffff0e3 globl # no wrapper
|
||||
scall sys_clock_gettime 0x1ab0570e8ffff0e4 globl hidden # Linux 2.6+ (c. 2003); XNU uses magic address
|
||||
scall sys_clock_getres 0x1ad0590eaffff0e5 globl hidden
|
||||
scall sys_clock_nanosleep 0x1ddfff0f4ffff0e6 globl # no wrapper
|
||||
scall sys_tgkill 0xfffffffffffff0ea globl hidden
|
||||
scall sys_mbind 0xfffffffffffff0ed globl # no wrapper; numa numa yeah
|
||||
scall set_mempolicy 0xfffffffffffff0ee globl
|
||||
|
|
|
@ -1402,6 +1402,7 @@ void *RecentWorker(void *arg) {
|
|||
pthread_setname_np(pthread_self(), "RecentWorker");
|
||||
LOG("RecentWorker started\n");
|
||||
StartOver:
|
||||
db = 0;
|
||||
stmt = 0;
|
||||
bzero(&t, sizeof(t));
|
||||
CHECK_SQL(DbOpen("db.sqlite3", &db));
|
||||
|
@ -1429,6 +1430,7 @@ StartOver:
|
|||
&sb, &sblen, (void *)sqlite3_column_text(stmt, 1), -1, 0),
|
||||
sqlite3_column_int64(stmt, 2)));
|
||||
}
|
||||
CHECK_SQL(sqlite3_reset(stmt));
|
||||
CHECK_SQL(sqlite3_exec(db, "END TRANSACTION", 0, 0, 0));
|
||||
CHECK_SYS(appends(&t.data.p, "]}\n"));
|
||||
t.data.n = appendz(t.data.p).i;
|
||||
|
@ -1478,15 +1480,17 @@ OnError:
|
|||
// single thread for inserting batched claims into the database
|
||||
// this helps us avoid over 9000 threads having fcntl bloodbath
|
||||
void *ClaimWorker(void *arg) {
|
||||
sqlite3 *db;
|
||||
int i, n, rc;
|
||||
sqlite3 *db = 0;
|
||||
sqlite3_stmt *stmt = 0;
|
||||
sqlite3_stmt *stmt;
|
||||
bool warmedup = false;
|
||||
struct Claim *v = _gc(xcalloc(BATCH_MAX, sizeof(struct Claim)));
|
||||
BlockSignals();
|
||||
pthread_setname_np(pthread_self(), "ClaimWorker");
|
||||
LOG("ClaimWorker started\n");
|
||||
StartOver:
|
||||
db = 0;
|
||||
stmt = 0;
|
||||
CHECK_SQL(DbOpen("db.sqlite3", &db));
|
||||
CHECK_DB(DbPrepare(db, &stmt,
|
||||
"INSERT INTO land (ip, nick, created)\n"
|
||||
|
@ -1525,8 +1529,6 @@ StartOver:
|
|||
OnError:
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
stmt = 0;
|
||||
db = 0;
|
||||
goto StartOver;
|
||||
}
|
||||
|
||||
|
|
13
third_party/nsync/common.internal.h
vendored
13
third_party/nsync/common.internal.h
vendored
|
@ -1,5 +1,6 @@
|
|||
#ifndef NSYNC_COMMON_H_
|
||||
#define NSYNC_COMMON_H_
|
||||
#include "libc/assert.h"
|
||||
#include "third_party/nsync/atomic.h"
|
||||
#include "third_party/nsync/atomic.internal.h"
|
||||
#include "third_party/nsync/cv.h"
|
||||
|
@ -220,12 +221,12 @@ static const uint32_t NSYNC_WAITER_TAG = 0x726d2ba9;
|
|||
#define WAITER_IN_USE 0x2 /* waiter in use by a thread */
|
||||
|
||||
#define CONTAINER(t_, f_, p_) ((t_ *)(((char *)(p_)) - offsetof(t_, f_)))
|
||||
#define ASSERT(x) \
|
||||
do { \
|
||||
if (!(x)) { \
|
||||
*(volatile int *)0 = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef TINY
|
||||
#define ASSERT(x) _unassert(x)
|
||||
#else
|
||||
#define ASSERT(x) _npassert(x)
|
||||
#endif
|
||||
|
||||
/* Return a pointer to the nsync_waiter_s containing nsync_dll_element_ *e. */
|
||||
#define DLL_NSYNC_WAITER(e) \
|
||||
|
|
9
third_party/nsync/mu_semaphore_futex.c
vendored
9
third_party/nsync/mu_semaphore_futex.c
vendored
|
@ -15,6 +15,7 @@
|
|||
│ See the License for the specific language governing permissions and │
|
||||
│ limitations under the License. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
@ -30,13 +31,17 @@ Copyright 2016 Google, Inc.\\n\
|
|||
https://github.com/google/nsync\"");
|
||||
// clang-format off
|
||||
|
||||
#ifdef TINY
|
||||
#define ASSERT(x) _unassert(x)
|
||||
#else
|
||||
#define ASSERT(x) _npassert(x)
|
||||
#endif
|
||||
|
||||
/* Check that atomic operations on nsync_atomic_uint32_ can be applied to int. */
|
||||
static const int assert_int_size = 1 /
|
||||
(sizeof (assert_int_size) == sizeof (uint32_t) &&
|
||||
sizeof (nsync_atomic_uint32_) == sizeof (uint32_t));
|
||||
|
||||
#define ASSERT(x) do { if (!(x)) { *(volatile int *)0 = 0; } } while (0)
|
||||
|
||||
struct futex {
|
||||
int i; /* lo half=count; hi half=waiter count */
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue