mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 14:58:30 +00:00
Get threads working well on MacOS Arm64
- Now using 10x better GCD semaphores - We now generate Linux-like thread ids - We now use fast system clock / sleep libraries - The APE M1 loader now generates Linux-like stacks
This commit is contained in:
parent
b5eab2b0b7
commit
bcf9af94bf
2037 changed files with 4664 additions and 4451 deletions
26
libc/calls/clock_gettime-m1.c
Normal file
26
libc/calls/clock_gettime-m1.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/timespec.h"
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
|
||||
int sys_clock_gettime_m1(int clock, struct timespec *ts) {
|
||||
return _sysret(__syslib->clock_gettime(clock, ts));
|
||||
}
|
|
@ -110,8 +110,15 @@ clock_gettime_f *__clock_gettime_get(bool *opt_out_isfast) {
|
|||
if (IsLinux() && (res = CGT_VDSO)) {
|
||||
isfast = true;
|
||||
} else if (IsXnu()) {
|
||||
isfast = false;
|
||||
#ifdef __x86_64__
|
||||
res = sys_clock_gettime_xnu;
|
||||
isfast = false;
|
||||
#elif defined(__aarch64__)
|
||||
res = sys_clock_gettime_m1;
|
||||
isfast = true;
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
} else if (IsWindows()) {
|
||||
isfast = true;
|
||||
res = sys_clock_gettime_nt;
|
||||
|
|
|
@ -16,10 +16,13 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#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/calls/syscall-sysv.internal.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/consts/timer.h"
|
||||
|
@ -27,23 +30,38 @@
|
|||
|
||||
int sys_clock_nanosleep_xnu(int clock, int flags, const struct timespec *req,
|
||||
struct timespec *rem) {
|
||||
int res;
|
||||
struct timeval now, abs, rel;
|
||||
#ifdef __x86_64__
|
||||
struct timeval abs, now, rel;
|
||||
if (clock == CLOCK_REALTIME) {
|
||||
if (flags & TIMER_ABSTIME) {
|
||||
abs = timespec_totimeval(*req);
|
||||
sys_gettimeofday_xnu(&now, 0, 0);
|
||||
if (timeval_cmp(abs, now) > 0) {
|
||||
rel = timeval_sub(abs, now);
|
||||
res = sys_select(0, 0, 0, 0, &rel);
|
||||
return sys_select(0, 0, 0, 0, &rel);
|
||||
} else {
|
||||
res = 0;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
res = sys_nanosleep_xnu(req, rem);
|
||||
return sys_nanosleep_xnu(req, rem);
|
||||
}
|
||||
} else {
|
||||
res = enotsup();
|
||||
return enotsup();
|
||||
}
|
||||
return res;
|
||||
#else
|
||||
long res;
|
||||
struct timespec abs, now, rel;
|
||||
if (flags & TIMER_ABSTIME) {
|
||||
abs = *req;
|
||||
if (!(res = __syslib->clock_gettime(clock, &now))) {
|
||||
if (timespec_cmp(abs, now) > 0) {
|
||||
rel = timespec_sub(abs, now);
|
||||
res = __syslib->nanosleep(&rel, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = __syslib->nanosleep(req, rem);
|
||||
}
|
||||
return _sysret(res);
|
||||
#endif
|
||||
}
|
||||
|
|
35
libc/calls/gettimeofday-m1.c
Normal file
35
libc/calls/gettimeofday-m1.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- 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 2020 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/calls/struct/timeval.h"
|
||||
#include "libc/calls/struct/timeval.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
|
||||
axdx_t sys_gettimeofday_m1(struct timeval *tv, struct timezone *tz, void *wut) {
|
||||
axdx_t ad;
|
||||
struct timespec ts;
|
||||
ad.ax = _sysret(__syslib->clock_gettime(CLOCK_REALTIME, &ts));
|
||||
ad.dx = 0;
|
||||
if (!ad.ax && tv) {
|
||||
*tv = timespec_totimeval(ts);
|
||||
}
|
||||
return ad;
|
||||
}
|
|
@ -82,8 +82,15 @@ gettimeofday_f *__gettimeofday_get(bool *opt_out_isfast) {
|
|||
isfast = true;
|
||||
res = sys_gettimeofday_nt;
|
||||
} else if (IsXnu()) {
|
||||
isfast = false;
|
||||
#ifdef __x86_64__
|
||||
res = sys_gettimeofday_xnu;
|
||||
isfast = false;
|
||||
#elif defined(__aarch64__)
|
||||
res = sys_gettimeofday_m1;
|
||||
isfast = true;
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
} else if (IsMetal()) {
|
||||
isfast = false;
|
||||
res = sys_gettimeofday_metal;
|
||||
|
|
|
@ -20,33 +20,32 @@
|
|||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/struct/timeval.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
#include "libc/sock/internal.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) {
|
||||
#ifdef __x86_64__
|
||||
int rc;
|
||||
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) {
|
||||
if (rem && rc == -1 && errno == EINTR) {
|
||||
sys_gettimeofday_xnu(&t2, 0, 0);
|
||||
td = timeval_sub(t2, t1);
|
||||
if (timeval_cmp(td, wt) >= 0) {
|
||||
rem->tv_sec = 0;
|
||||
rem->tv_nsec = 0;
|
||||
} else if (rc == -1 && errno == EINTR) {
|
||||
// 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_cmp(td, wt) >= 0) {
|
||||
rem->tv_sec = 0;
|
||||
rem->tv_nsec = 0;
|
||||
} else {
|
||||
*rem = timeval_totimespec(timeval_sub(wt, td));
|
||||
}
|
||||
} else {
|
||||
*rem = timeval_totimespec(timeval_sub(wt, td));
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
#else
|
||||
return _sysret(__syslib->nanosleep(req, rem));
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ int __utimens(int, const char *, const struct timespec[2], int) _Hide;
|
|||
int sys_clock_getres(int, struct timespec *) _Hide;
|
||||
int sys_clock_gettime(int, struct timespec *) _Hide;
|
||||
int sys_clock_gettime_nt(int, struct timespec *) _Hide;
|
||||
int sys_clock_gettime_m1(int, struct timespec *) _Hide;
|
||||
int sys_clock_gettime_xnu(int, struct timespec *) _Hide;
|
||||
int sys_clock_nanosleep_nt(int, int, const struct timespec *, struct timespec *) _Hide;
|
||||
int sys_clock_nanosleep_openbsd(int, int, const struct timespec *, struct timespec *) _Hide;
|
||||
|
|
|
@ -9,6 +9,7 @@ axdx_t sys_gettimeofday(struct timeval *, struct timezone *, void *) _Hide;
|
|||
int sys_futimes(int, const struct timeval *) _Hide;
|
||||
int sys_lutimes(const char *, const struct timeval *) _Hide;
|
||||
int sys_utimes(const char *, const struct timeval *) _Hide;
|
||||
axdx_t sys_gettimeofday_m1(struct timeval *, struct timezone *, void *) _Hide;
|
||||
axdx_t sys_gettimeofday_xnu(struct timeval *, struct timezone *, void *) _Hide;
|
||||
axdx_t sys_gettimeofday_nt(struct timeval *, struct timezone *, void *) _Hide;
|
||||
int sys_utimes_nt(const char *, const struct timeval[2]) _Hide;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue