mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Improve quality of our ANSI C clock() function
It now works most excellently across all supported operating sytsems (earlier it didn't work on NT and XNU). Demo code is available in examples/clock.c and this change also adds some of the newer ANSI C time functions like timespec_get(), plus timespec_getres() which hasn't even come out yet as it's C23
This commit is contained in:
parent
7ff0ea8c13
commit
12d9e1e128
24 changed files with 254 additions and 76 deletions
41
examples/clock.c
Normal file
41
examples/clock.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
/**
|
||||
* @fileoverview clock() function demo
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
unsigned long i;
|
||||
volatile unsigned long x;
|
||||
struct timespec now, start, next, interval;
|
||||
printf("hammering the cpu...\n");
|
||||
next = start = _timespec_mono();
|
||||
interval = _timespec_frommillis(500);
|
||||
next = _timespec_add(next, interval);
|
||||
for (;;) {
|
||||
for (i = 0;; ++i) {
|
||||
x *= 7;
|
||||
if (!(i % 256)) {
|
||||
now = _timespec_mono();
|
||||
if (_timespec_gte(now, next)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
next = _timespec_add(next, interval);
|
||||
printf("consumed %10g seconds monotonic time and %10g seconds cpu time\n",
|
||||
_timespec_tonanos(_timespec_sub(now, start)) / 1000000000.,
|
||||
(double)clock() / CLOCKS_PER_SEC);
|
||||
}
|
||||
}
|
|
@ -8,14 +8,14 @@
|
|||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char name[254];
|
||||
CHECK_NE(-1, gethostname(name, sizeof(name)));
|
||||
printf("gethostname() → %`'s\n", name);
|
||||
CHECK_NE(-1, getdomainname(name, sizeof(name)));
|
||||
printf("getdomainname() → %`'s\n", name);
|
||||
gethostname(name, sizeof(name));
|
||||
kprintf("gethostname() → %#s\n", name);
|
||||
getdomainname(name, sizeof(name));
|
||||
kprintf("getdomainname() → %#s\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
|
29
libc/calls/_timespec_fromnanos.c
Normal file
29
libc/calls/_timespec_fromnanos.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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"
|
||||
|
||||
/**
|
||||
* Converts timespec interval from nanoseconds.
|
||||
*/
|
||||
struct timespec _timespec_fromnanos(int64_t x) {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = x / 1000000000;
|
||||
ts.tv_nsec = x % 1000000000;
|
||||
return ts;
|
||||
}
|
|
@ -184,9 +184,11 @@ o//libc/calls/statfs2cosmo.o: private \
|
|||
|
||||
# we always want -O2 because:
|
||||
# division is expensive if not optimized
|
||||
o/$(MODE)/libc/calls/clock.o \
|
||||
o/$(MODE)/libc/calls/_timespec_tomillis.o \
|
||||
o/$(MODE)/libc/calls/_timespec_tomicros.o \
|
||||
o/$(MODE)/libc/calls/_timespec_totimeval.o \
|
||||
o/$(MODE)/libc/calls/_timespec_fromnanos.o \
|
||||
o/$(MODE)/libc/calls/_timespec_frommillis.o \
|
||||
o/$(MODE)/libc/calls/_timespec_frommicros.o: private \
|
||||
OVERRIDE_CFLAGS += \
|
||||
|
|
|
@ -16,36 +16,51 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/consts/rusage.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
/**
|
||||
* Returns how much CPU program has consumed on time-sharing system.
|
||||
* Returns sum of CPU time consumed by current process since birth.
|
||||
*
|
||||
* @return value that can be divided by CLOCKS_PER_SEC, or -1 w/ errno
|
||||
* @see clock_gettime()
|
||||
* This function provides a basic idea of how computationally expensive
|
||||
* your program is, in terms of both the userspace and kernel processor
|
||||
* resources it's hitherto consumed. Here's an example of how you might
|
||||
* display this information:
|
||||
*
|
||||
* printf("consumed %g seconds of cpu time\n",
|
||||
* (double)clock() / CLOCKS_PER_SEC);
|
||||
*
|
||||
* This function offers at best microsecond accuracy on all supported
|
||||
* platforms. Please note the reported values might be a bit chunkier
|
||||
* depending on the kernel scheduler sampling interval see `CLK_TCK`.
|
||||
*
|
||||
* @return units of CPU time consumed, where each unit's time length
|
||||
* should be `1./CLOCKS_PER_SEC` seconds; Cosmopolitan currently
|
||||
* returns the unit count in microseconds, i.e. `CLOCKS_PER_SEC`
|
||||
* is hard-coded as 1000000. On failure this returns -1 / errno.
|
||||
* @raise ENOSYS should be returned currently if run on Bare Metal
|
||||
* @see clock_gettime() which polyfills this on Linux and BSDs
|
||||
* @see getrusage() which polyfills this on XNU and NT
|
||||
*/
|
||||
int64_t clock(void) {
|
||||
int e;
|
||||
struct rusage ru;
|
||||
struct timespec ts;
|
||||
struct NtFileTime creation_time, exit_time, kernel_time, user_time;
|
||||
int64_t proc, total;
|
||||
// polyfill on Windows where CLOCK_PROCESS_CPUTIME_ID may be not available
|
||||
if (IsWindows() && CLOCK_PROCESS_CPUTIME_ID == -1) {
|
||||
proc = GetCurrentProcess();
|
||||
if (!GetProcessTimes(proc, &creation_time, &exit_time, &kernel_time,
|
||||
&user_time))
|
||||
e = errno;
|
||||
if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == -1) {
|
||||
errno = e;
|
||||
if (getrusage(RUSAGE_SELF, &ru) != -1) {
|
||||
ts = _timeval_totimespec(_timeval_add(ru.ru_utime, ru.ru_stime));
|
||||
} else {
|
||||
return -1;
|
||||
total = ReadFileTime(kernel_time) + ReadFileTime(user_time);
|
||||
ts = WindowsDurationToTimeSpec(total);
|
||||
} else if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return ts.tv_sec * CLOCKS_PER_SEC +
|
||||
ts.tv_nsec / (1000000000 / CLOCKS_PER_SEC);
|
||||
// convert nanoseconds to microseconds w/ ceil rounding
|
||||
// this would need roughly ~7,019,309 years to overflow
|
||||
return ts.tv_sec * 1000000 + (ts.tv_nsec + 999) / 1000;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
#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;
|
||||
|
@ -65,6 +63,7 @@ int clock_getres(int clock, struct timespec *ts) {
|
|||
} else {
|
||||
rc = sys_clock_getres(clock, ts);
|
||||
}
|
||||
STRACE("clock_getres(%d, [%s]) → %d% m", clock, DescribeTimespec(rc, ts), rc);
|
||||
STRACE("clock_getres(%s, [%s]) → %d% m", DescribeClockName(clock),
|
||||
DescribeTimespec(rc, ts), rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -16,38 +16,33 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/clock_gettime.internal.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/clockstonanos.internal.h"
|
||||
|
||||
static struct {
|
||||
pthread_once_t once;
|
||||
uint64_t base;
|
||||
struct timespec mono;
|
||||
struct timespec base_wall;
|
||||
uint64_t base_tick;
|
||||
} g_mono;
|
||||
|
||||
static void sys_clock_gettime_mono_init(void) {
|
||||
clock_gettime(CLOCK_REALTIME, &g_mono.mono);
|
||||
g_mono.base = rdtsc();
|
||||
g_mono.once = true;
|
||||
g_mono.base_wall = _timespec_real();
|
||||
g_mono.base_tick = rdtsc();
|
||||
}
|
||||
|
||||
int sys_clock_gettime_mono(struct timespec *ts) {
|
||||
// this routine stops being monotonic after 194 years of uptime
|
||||
int sys_clock_gettime_mono(struct timespec *time) {
|
||||
uint64_t nanos;
|
||||
uint64_t cycles;
|
||||
struct timespec res;
|
||||
if (X86_HAVE(INVTSC)) {
|
||||
pthread_once(&g_mono.once, sys_clock_gettime_mono_init);
|
||||
nanos = ClocksToNanos(rdtsc(), g_mono.base);
|
||||
res = g_mono.mono;
|
||||
res.tv_sec += nanos / 1000000000;
|
||||
res.tv_nsec += nanos % 1000000000;
|
||||
*ts = res;
|
||||
cycles = rdtsc() - g_mono.base_tick;
|
||||
nanos = cycles / 3;
|
||||
*time = _timespec_add(g_mono.base_wall, _timespec_fromnanos(nanos));
|
||||
return 0;
|
||||
} else {
|
||||
return einval();
|
||||
|
|
|
@ -66,8 +66,8 @@ int clock_gettime(int clock, struct timespec *ts) {
|
|||
}
|
||||
#if SYSDEBUG
|
||||
if (!__time_critical) {
|
||||
STRACE("clock_gettime(%d, [%s]) → %d% m", clock, DescribeTimespec(rc, ts),
|
||||
rc);
|
||||
STRACE("clock_gettime(%s, [%s]) → %d% m", DescribeClockName(clock),
|
||||
DescribeTimespec(rc, ts), rc);
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
|
|
|
@ -14,6 +14,8 @@ int futimens(int, const struct timespec[2]);
|
|||
int nanosleep(const struct timespec *, struct timespec *);
|
||||
int sys_futex(int *, int, int, const struct timespec *, int *);
|
||||
int utimensat(int, const char *, const struct timespec[2], int);
|
||||
int timespec_get(struct timespec *, int);
|
||||
int timespec_getres(struct timespec *, int);
|
||||
|
||||
bool _timespec_eq(struct timespec, struct timespec) pureconst;
|
||||
bool _timespec_gte(struct timespec, struct timespec) pureconst;
|
||||
|
@ -21,6 +23,7 @@ int64_t _timespec_tomicros(struct timespec) pureconst;
|
|||
int64_t _timespec_tomillis(struct timespec) pureconst;
|
||||
int64_t _timespec_tonanos(struct timespec) pureconst;
|
||||
struct timespec _timespec_add(struct timespec, struct timespec) pureconst;
|
||||
struct timespec _timespec_fromnanos(int64_t) pureconst;
|
||||
struct timespec _timespec_frommicros(int64_t) pureconst;
|
||||
struct timespec _timespec_frommillis(int64_t) pureconst;
|
||||
struct timespec _timespec_mono(void);
|
||||
|
|
|
@ -6,14 +6,15 @@
|
|||
COSMOPOLITAN_C_START_
|
||||
|
||||
int __sys_utimensat(int, const char *, const struct timespec *, int) hidden;
|
||||
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_futimens(int, const struct timespec *) hidden;
|
||||
int sys_nanosleep(const struct timespec *, struct timespec *) hidden;
|
||||
int sys_utimensat(int, const char *, const struct timespec *, int) hidden;
|
||||
int sys_clock_gettime_nt(int, struct timespec *) hidden;
|
||||
int sys_nanosleep_nt(const struct timespec *, struct timespec *) hidden;
|
||||
int sys_nanosleep_xnu(const struct timespec *, struct timespec *) hidden;
|
||||
int sys_utimensat(int, const char *, const struct timespec *, int) hidden;
|
||||
int sys_utimensat_nt(int, const char *, const struct timespec *, int) hidden;
|
||||
int sys_utimensat_xnu(int, const char *, const struct timespec *, int) hidden;
|
||||
|
||||
|
|
36
libc/calls/timespec_get.c
Normal file
36
libc/calls/timespec_get.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
/**
|
||||
* Returns high-precision timestamp, the C11 way.
|
||||
*
|
||||
* @param ts receives `CLOCK_REALTIME` timestamp
|
||||
* @param base must be `TIME_UTC`
|
||||
* @return `base` on success, or `0` on failure
|
||||
*/
|
||||
int timespec_get(struct timespec *ts, int base) {
|
||||
if (base == TIME_UTC && !clock_gettime(CLOCK_REALTIME, ts)) {
|
||||
return base;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
36
libc/calls/timespec_getres.c
Normal file
36
libc/calls/timespec_getres.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
/**
|
||||
* Returns high-precision timestamp granularity, the C23 way.
|
||||
*
|
||||
* @param ts receives granularity as a relative timestamp
|
||||
* @param base must be `TIME_UTC`
|
||||
* @return `base` on success, or `0` on failure
|
||||
*/
|
||||
int timespec_getres(struct timespec *ts, int base) {
|
||||
if (base == TIME_UTC && !clock_getres(CLOCK_REALTIME, ts)) {
|
||||
return base;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -158,6 +158,9 @@ struct thatispacked mayalias __usi128ma {
|
|||
#define _mm_srli_si128(M128I, IMM) \
|
||||
((__m128i)__builtin_ia32_psrldqi128((__v2di)(__m128i)(M128I), (int)(IMM)*8))
|
||||
|
||||
#define _mm_cmpeq_epi8(a, b) ((__m128i)((__v16qi)(a) == (__v16qi)(b)))
|
||||
#define _mm_movemask_epi8(a) __builtin_ia32_pmovmskb128((__v16qi)(a))
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § it's a trap! » sse2 » scalar ops ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
@ -218,19 +221,18 @@ struct thatispacked mayalias __usi128ma {
|
|||
#define _mm_cmpunord_sd(M128D_0, M128D_1) \
|
||||
__builtin_ia32_cmpunordsd((__v2df)(M128D_0), (__v2df)(M128D_1))
|
||||
|
||||
#define _mm_SSE2(op, A, B) \
|
||||
({ \
|
||||
__m128i R = A; \
|
||||
asm(#op " %1, %0" \
|
||||
: "+x"(R) : "xm"(B)); \
|
||||
R; \
|
||||
#define _mm_SSE2(op, A, B) \
|
||||
({ \
|
||||
__m128i R = A; \
|
||||
asm(#op " %1, %0" : "+x"(R) : "xm"(B)); \
|
||||
R; \
|
||||
})
|
||||
#define _mm_mul_epu32(A, B) _mm_SSE2(pmuludq, A, B)
|
||||
#define _mm_add_epi64(A, B) _mm_SSE2(paddq, A, B)
|
||||
#define _mm_srli_epi64(A, B) _mm_SSE2(psrlq, A, B)
|
||||
#define _mm_slli_epi64(A, B) _mm_SSE2(psllq, A, B)
|
||||
#define _mm_unpacklo_epi64(A, B) _mm_SSE2(punpcklqdq, A, B)
|
||||
#define _mm_unpackhi_epi64(A, B) _mm_SSE2(punpckhqdq, A, B)
|
||||
#define _mm_mul_epu32(A, B) _mm_SSE2(pmuludq, A, B)
|
||||
#define _mm_add_epi64(A, B) _mm_SSE2(paddq, A, B)
|
||||
#define _mm_srli_epi64(A, B) _mm_SSE2(psrlq, A, B)
|
||||
#define _mm_slli_epi64(A, B) _mm_SSE2(psllq, A, B)
|
||||
#define _mm_unpacklo_epi64(A, B) _mm_SSE2(punpcklqdq, A, B)
|
||||
#define _mm_unpackhi_epi64(A, B) _mm_SSE2(punpckhqdq, A, B)
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § it's a trap! » sse2 » miscellaneous ─╬─│┼
|
||||
|
|
|
@ -17,10 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#define ShouldUseMsabiAttribute() 1
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
|
@ -28,11 +24,15 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/fmt/divmod10.internal.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/lockcmpxchg.h"
|
||||
#include "libc/intrin/nomultics.internal.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
@ -53,7 +53,6 @@
|
|||
#include "libc/str/utf16.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/time/clockstonanos.internal.h"
|
||||
|
||||
extern hidden struct SymbolTable *__symtab;
|
||||
|
||||
|
@ -306,7 +305,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
|
|||
continue;
|
||||
|
||||
case 'T':
|
||||
x = ClocksToNanos(rdtsc(), kStartTsc) % 86400000000000;
|
||||
x = (rdtsc() - kStartTsc) / 3 % 86400000000000;
|
||||
goto FormatUnsigned;
|
||||
|
||||
case 'P':
|
||||
|
|
|
@ -1615,8 +1615,6 @@ syscon iff IFF_MASTER 0x0400 0 0 0 0 0
|
|||
syscon iff IFF_PORTSEL 0x2000 0 0 0 0 0
|
||||
syscon iff IFF_SLAVE 0x0800 0 0 0 0 0
|
||||
|
||||
syscon misc CLOCKS_PER_SEC 1000000 1000000 0x80 100 100 10000000
|
||||
|
||||
syscon sock SOCK_STREAM 1 1 1 1 1 1 # consensus
|
||||
syscon sock SOCK_DGRAM 2 2 2 2 2 2 # consensus
|
||||
syscon sock SOCK_RAW 3 3 3 3 3 3 # consensus
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon misc,CLOCKS_PER_SEC,1000000,1000000,0x80,100,100,10000000
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon sicode,SI_KERNEL,0x80,0x80000000,0x010006,0x80000000,0x80000000,0x80
|
||||
.syscon sicode,SI_KERNEL,128,0x80000000,0x010006,0x80000000,0x80000000,0x80
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @fileoverview Cosmopolitan POSIX Thread Internals
|
||||
*/
|
||||
|
||||
enum PosixThreadStatus {
|
||||
kPosixThreadStarted,
|
||||
kPosixThreadDetached,
|
||||
|
|
|
@ -33,13 +33,13 @@ static int PosixThread(void *arg, int tid) {
|
|||
((cthread_t)__get_tls())->pthread = pt;
|
||||
pt->rc = pt->start_routine(pt->arg);
|
||||
}
|
||||
if (atomic_load_explicit(&pt->status, memory_order_relaxed) ==
|
||||
if (atomic_load_explicit(&pt->status, memory_order_acquire) ==
|
||||
kPosixThreadDetached) {
|
||||
atomic_store_explicit(&pt->status, kPosixThreadZombie,
|
||||
memory_order_relaxed);
|
||||
memory_order_release);
|
||||
} else {
|
||||
atomic_store_explicit(&pt->status, kPosixThreadTerminated,
|
||||
memory_order_relaxed);
|
||||
memory_order_release);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -47,6 +47,25 @@ static int PosixThread(void *arg, int tid) {
|
|||
/**
|
||||
* Creates thread.
|
||||
*
|
||||
* Here's the OSI model of threads in Cosmopolitan:
|
||||
*
|
||||
* ┌──────────────────┐
|
||||
* │ pthread_create() │ - Standard
|
||||
* └─────────┬────────┘ Abstraction
|
||||
* ┌─────────┴────────┐
|
||||
* │ _spawn() │ - Cosmopolitan
|
||||
* └─────────┬────────┘ Abstraction
|
||||
* ┌─────────┴────────┐
|
||||
* │ clone() │ - Polyfill
|
||||
* └─────────┬────────┘
|
||||
* ┌────────┬──┴──┬─┬─────────┐ - Kernel
|
||||
* ┌─────┴─────┐ │ │┌┴──────┐ │ Interfaces
|
||||
* │ sys_clone │ │ ││ tfork │ │
|
||||
* └───────────┘ │ │└───────┘ ┌┴─────────────┐
|
||||
* ┌───────────────┴──┐ ┌┴────────┐ │ CreateThread │
|
||||
* │ bsdthread_create │ │ thr_new │ └──────────────┘
|
||||
* └──────────────────┘ └─────────┘
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
*/
|
||||
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/atomic.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_TIME_TIME_H_
|
||||
#define COSMOPOLITAN_LIBC_TIME_TIME_H_
|
||||
|
||||
#define TIME_UTC 1
|
||||
#define CLOCKS_PER_SEC 1000000L
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
|
@ -10,7 +14,6 @@ hidden extern const char kMonthName[12][10];
|
|||
hidden extern const unsigned short kMonthYearDay[2][12];
|
||||
|
||||
extern char *tzname[2];
|
||||
extern long CLOCKS_PER_SEC;
|
||||
extern long timezone;
|
||||
extern int daylight;
|
||||
|
||||
|
|
1
third_party/python/Modules/timemodule.c
vendored
1
third_party/python/Modules/timemodule.c
vendored
|
@ -110,7 +110,6 @@ PyDoc_STRVAR(time_ns_doc,
|
|||
Return the current time in nanoseconds since the Epoch.");
|
||||
|
||||
#ifdef HAVE_CLOCK
|
||||
#define CLOCKS_PER_SEC CLK_TCK
|
||||
static PyObject *
|
||||
floatclock(_Py_clock_info_t *info)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue