mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-26 20:40:28 +00:00
Refactor some code
- Write tests for cthreads - Fix bugs in pe2.com tool - Fix ASAN issue with GetDosEnviron() - Consolidate the cthread header files - Some code size optimizations for MODE= - Attempted to squash a tls linker warning - Attempted to get futexes working on FreeBSD
This commit is contained in:
parent
909e54510d
commit
425ff5dff0
61 changed files with 529 additions and 382 deletions
|
@ -164,6 +164,14 @@ o//libc/calls/fcntl.o: \
|
|||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
# we always want -Os because:
|
||||
# it's early runtime mandatory and quite huge without it
|
||||
o//libc/calls/getcwd.greg.o \
|
||||
o//libc/calls/getcwd-nt.greg.o \
|
||||
o//libc/calls/getcwd-xnu.greg.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
LIBC_CALLS_LIBS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)))
|
||||
LIBC_CALLS_SRCS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_CALLS_HDRS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_HDRS))
|
||||
|
|
|
@ -28,18 +28,28 @@
|
|||
#define XNU_F_GETPATH 50
|
||||
#define XNU_MAXPATHLEN 1024
|
||||
|
||||
static inline bool CopyString(char *d, const char *s, size_t n) {
|
||||
size_t i;
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (!(d[i] = s[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
char *sys_getcwd_xnu(char *res, size_t size) {
|
||||
int fd;
|
||||
union metastat st[2];
|
||||
char buf[XNU_MAXPATHLEN], *ret = NULL;
|
||||
if ((fd = sys_openat(AT_FDCWD, ".", O_RDONLY | O_DIRECTORY, 0)) != -1) {
|
||||
if (__sys_fstat(fd, &st[0]) != -1) {
|
||||
if (METASTAT(st[0], st_dev) && METASTAT(st[0], st_ino)) {
|
||||
if (st[0].xnu.st_dev && st[0].xnu.st_ino) {
|
||||
if (__sys_fcntl(fd, XNU_F_GETPATH, (uintptr_t)buf) != -1) {
|
||||
if (__sys_fstatat(AT_FDCWD, buf, &st[1], 0) != -1) {
|
||||
if (METASTAT(st[0], st_dev) == METASTAT(st[1], st_dev) &&
|
||||
METASTAT(st[0], st_ino) == METASTAT(st[1], st_ino)) {
|
||||
if (memccpy(res, buf, '\0', size)) {
|
||||
if (st[0].xnu.st_dev == st[1].xnu.st_dev &&
|
||||
st[0].xnu.st_ino == st[1].xnu.st_ino) {
|
||||
if (CopyString(res, buf, size)) {
|
||||
ret = res;
|
||||
} else {
|
||||
erange();
|
||||
|
|
|
@ -753,7 +753,7 @@ dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
|
|||
p = __fatalbuf;
|
||||
kprintf("\n\e[J\e[1;31masan error\e[0m: %s %d-byte %s at %p shadow %p\n",
|
||||
__asan_describe_access_poison(kind), size, message, addr,
|
||||
SHADOW(addr), __argv[0]);
|
||||
SHADOW(addr));
|
||||
if (0 < size && size < 80) {
|
||||
base = (char *)addr - ((80 >> 1) - (size >> 1));
|
||||
for (i = 0; i < 80; ++i) {
|
||||
|
|
|
@ -58,7 +58,7 @@ privileged int gettid(void) {
|
|||
struct WinThread *wt;
|
||||
|
||||
if (__tls_enabled) {
|
||||
rc = *(int *)(__get_tls() + 0x38);
|
||||
rc = *(int *)(__get_tls_inline() + 0x38);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,23 +21,28 @@
|
|||
#include "libc/log/log.h"
|
||||
#include "libc/nexgen32e/vendor.internal.h"
|
||||
#include "libc/nt/struct/teb.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
#define kBufSize 1024
|
||||
#define kPid "TracerPid:\t"
|
||||
|
||||
static textwindows noasan bool IsBeingDebugged(void) {
|
||||
return !!NtGetPeb()->BeingDebugged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if gdb, strace, windbg, etc. is controlling process.
|
||||
* @return non-zero if attached, otherwise 0
|
||||
*/
|
||||
noasan noubsan int IsDebuggerPresent(bool force) {
|
||||
int IsDebuggerPresent(bool force) {
|
||||
/* asan runtime depends on this function */
|
||||
int fd, res;
|
||||
ssize_t got;
|
||||
char *p, buf[1024];
|
||||
if (!force && IsGenuineCosmo()) return 0;
|
||||
if (!force && getenv("HEISENDEBUG")) return 0;
|
||||
if (IsWindows()) return NtGetPeb()->BeingDebugged; /* needs noasan */
|
||||
if (!force && __getenv(environ, "HEISENDEBUG")) return 0;
|
||||
if (IsWindows()) return IsBeingDebugged();
|
||||
if (__isworker) return false;
|
||||
res = 0;
|
||||
if ((fd = __sysv_open("/proc/self/status", O_RDONLY, 0)) >= 0) {
|
|
@ -1,6 +1,5 @@
|
|||
#ifndef LIBC_ISYSTEM_PTHREAD_H_
|
||||
#define LIBC_ISYSTEM_PTHREAD_H_
|
||||
|
||||
#include "libc/calls/calls.h"
|
||||
|
||||
#define PTHREAD_ONCE_INIT 0
|
||||
|
|
|
@ -59,8 +59,8 @@ $(LIBC_LOG_A).pkg: \
|
|||
$(LIBC_LOG_A_OBJS) \
|
||||
$(foreach x,$(LIBC_LOG_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/libc/log/backtrace2.greg.o \
|
||||
o/$(MODE)/libc/log/backtrace3.greg.o: \
|
||||
o/$(MODE)/libc/log/backtrace2.o \
|
||||
o/$(MODE)/libc/log/backtrace3.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-fno-sanitize=all
|
||||
|
||||
|
@ -68,10 +68,7 @@ o/$(MODE)/libc/log/checkfail.o: \
|
|||
OVERRIDE_CFLAGS += \
|
||||
-mgeneral-regs-only
|
||||
|
||||
o/$(MODE)/libc/log/restoretty.greg.o \
|
||||
o/$(MODE)/libc/log/attachdebugger.o \
|
||||
o/$(MODE)/libc/log/backtrace2.o \
|
||||
o/$(MODE)/libc/log/backtrace3.o \
|
||||
o/$(MODE)/libc/log/checkaligned.o \
|
||||
o/$(MODE)/libc/log/checkfail.o \
|
||||
o/$(MODE)/libc/log/checkfail_ndebug.o \
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/log/color.internal.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
|
||||
|
@ -60,7 +61,7 @@ void __restore_tty(void) {
|
|||
int e;
|
||||
if (__isrestorable && !__isworker && !__nocolor) {
|
||||
e = errno;
|
||||
sys_write(0, ANSI_RESTORE, strlen(ANSI_RESTORE));
|
||||
sys_write(0, ANSI_RESTORE, __strlen(ANSI_RESTORE));
|
||||
sys_ioctl(0, TCSETSF, &__oldtermios);
|
||||
errno = e;
|
||||
}
|
|
@ -8,19 +8,12 @@ extern int __threaded;
|
|||
extern bool __tls_enabled;
|
||||
extern unsigned __tls_index;
|
||||
|
||||
char *__get_tls(void) libcesque nosideeffect;
|
||||
void *__initialize_tls(char[64]);
|
||||
void __install_tls(char[64]);
|
||||
|
||||
#if defined(__GNUC__) && defined(__x86_64__) && !defined(__STRICT_ANSI__)
|
||||
/**
|
||||
* Returns address of thread information block.
|
||||
*
|
||||
* This function must not be called until TLS is initialized.
|
||||
*
|
||||
* @see __install_tls()
|
||||
* @see clone()
|
||||
*/
|
||||
static noasan inline char *__get_tls(void) {
|
||||
static noasan inline char *__get_tls_inline(void) {
|
||||
char *tib, *lin = (char *)0x30;
|
||||
if (IsLinux() || IsFreebsd() || IsNetbsd() || IsOpenbsd()) {
|
||||
asm("mov\t%%fs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/thread/create.h"
|
||||
|
||||
static int thepid;
|
||||
static uint128_t thepool;
|
||||
|
|
|
@ -468,7 +468,8 @@ int sys_clone_linux(int flags, char *stk, int *ptid, int *ctid, void *tls,
|
|||
* effectively work around libc features like atfork(), so that means
|
||||
* other calls like getpid() may return incorrect values.
|
||||
*
|
||||
* @param func is your callback function
|
||||
* @param func is your callback function, which this wrapper requires
|
||||
* not be null, otherwise EINVAL is raised
|
||||
* @param stk points to the bottom of a caller allocated stack, which
|
||||
* must be allocated via mmap() using the MAP_STACK flag, or else
|
||||
* you won't get optimal performance and it won't work on OpenBSD
|
||||
|
@ -532,20 +533,22 @@ int clone(int (*func)(void *), void *stk, size_t stksz, int flags, void *arg,
|
|||
__threaded = gettid();
|
||||
}
|
||||
|
||||
if (IsAsan() &&
|
||||
((stksz > PAGESIZE &&
|
||||
!__asan_is_valid((char *)stk + PAGESIZE, stksz - PAGESIZE)) ||
|
||||
((flags & CLONE_SETTLS) && !__asan_is_valid(tls, tlssz)) ||
|
||||
((flags & CLONE_SETTLS) && !__asan_is_valid(tls, sizeof(long))) ||
|
||||
((flags & CLONE_PARENT_SETTID) &&
|
||||
!__asan_is_valid(ptid, sizeof(*ptid))) ||
|
||||
((flags & CLONE_CHILD_SETTID) &&
|
||||
!__asan_is_valid(ctid, sizeof(*ctid))))) {
|
||||
rc = efault();
|
||||
if (!func) {
|
||||
rc = einval();
|
||||
} else if (!IsTiny() &&
|
||||
(((flags & CLONE_VM) && (stksz < PAGESIZE || (stksz & 15))) ||
|
||||
((flags & CLONE_SETTLS) && (tlssz < 64 || (tlssz & 7))))) {
|
||||
rc = einval();
|
||||
} else if (IsAsan() &&
|
||||
((stksz > PAGESIZE &&
|
||||
!__asan_is_valid((char *)stk + PAGESIZE, stksz - PAGESIZE)) ||
|
||||
((flags & CLONE_SETTLS) && !__asan_is_valid(tls, tlssz)) ||
|
||||
((flags & CLONE_SETTLS) && !__asan_is_valid(tls, sizeof(long))) ||
|
||||
((flags & CLONE_PARENT_SETTID) &&
|
||||
!__asan_is_valid(ptid, sizeof(*ptid))) ||
|
||||
((flags & CLONE_CHILD_SETTID) &&
|
||||
!__asan_is_valid(ctid, sizeof(*ctid))))) {
|
||||
rc = efault();
|
||||
} else if (IsLinux()) {
|
||||
rc =
|
||||
sys_clone_linux(flags, (char *)stk + stksz, ptid, ctid, tls, func, arg);
|
||||
|
|
|
@ -125,7 +125,7 @@ textwindows noasan noinstrument int GetDosEnviron(const char16_t *env,
|
|||
while (*env) {
|
||||
if (i + 1 < max) envp[i++] = buf;
|
||||
r = Recode16to8(buf, size, env);
|
||||
if ((p = memchr(buf, '=', r.ax)) && IsAlpha(p[1]) && p[2] == ':' &&
|
||||
if ((p = MemChr(buf, '=', r.ax)) && IsAlpha(p[1]) && p[2] == ':' &&
|
||||
(p[3] == '\\' || p[3] == '/')) {
|
||||
FixPath(p + 1);
|
||||
}
|
||||
|
|
|
@ -16,29 +16,56 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/atomic.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/lockcmpxchg.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
typedef void *pthread_t;
|
||||
typedef bool pthread_once_t;
|
||||
typedef int pthread_once_t;
|
||||
typedef int pthread_mutex_t;
|
||||
|
||||
int pthread_once(pthread_once_t *once, void init(void)) {
|
||||
if (_lockcmpxchg(once, 0, 1)) init();
|
||||
int x;
|
||||
unsigned tries;
|
||||
switch ((x = atomic_load(once))) {
|
||||
case 0:
|
||||
if (atomic_compare_exchange_strong(once, &x, 1)) {
|
||||
init();
|
||||
atomic_store(once, 2);
|
||||
break;
|
||||
}
|
||||
// fallthrough
|
||||
case 1:
|
||||
tries = 0;
|
||||
do {
|
||||
if (++tries & 7) {
|
||||
__builtin_ia32_pause();
|
||||
} else {
|
||||
sched_yield();
|
||||
}
|
||||
} while (atomic_load(once) == 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_mutex_lock(pthread_mutex_t *mutex) {
|
||||
return EINVAL;
|
||||
_spinlock(mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_mutex_trylock(pthread_mutex_t *mutex) {
|
||||
return EINVAL;
|
||||
return _trylock(mutex);
|
||||
}
|
||||
|
||||
int pthread_mutex_unlock(pthread_mutex_t *mutex) {
|
||||
return EPERM;
|
||||
_spunlock(mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_cancel(pthread_t thread) {
|
||||
|
|
|
@ -21,11 +21,15 @@
|
|||
|
||||
/**
|
||||
* Returns file descriptor associated with stream.
|
||||
*
|
||||
* @param f is file stream object pointer
|
||||
* @return fd on success or -1 w/ errno;
|
||||
* @threadsafe
|
||||
*/
|
||||
int fileno_unlocked(FILE *f) {
|
||||
if (f->fd != -1) {
|
||||
return f->fd;
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
int fileno(FILE *f) {
|
||||
int rc;
|
||||
flockfile(f);
|
||||
rc = fileno_unlocked(f);
|
||||
funlockfile(f);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
|
@ -16,14 +16,19 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
// Returns file descriptor associated with stream.
|
||||
//
|
||||
// @param rdi has file stream object pointer
|
||||
// @see fileno_unlocked()
|
||||
// @threadsafe
|
||||
fileno: mov %rdi,%r11
|
||||
ezlea fileno_unlocked,ax
|
||||
jmp stdio_unlock
|
||||
.endfn fileno,globl
|
||||
/**
|
||||
* Returns file descriptor associated with stream.
|
||||
*
|
||||
* @param f is file stream object pointer
|
||||
* @return fd on success or -1 w/ errno;
|
||||
*/
|
||||
int fileno_unlocked(FILE *f) {
|
||||
if (f->fd != -1) {
|
||||
return f->fd;
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
|
@ -24,15 +23,12 @@
|
|||
*
|
||||
* @param c is byte to buffer or write, which is masked
|
||||
* @return c as unsigned char if written or -1 w/ errno
|
||||
* @threadsafe
|
||||
*/
|
||||
int fputc_unlocked(int c, FILE *f) {
|
||||
unsigned char b;
|
||||
if (c != '\n' && f->beg < f->size && f->bufmode != _IONBF) {
|
||||
f->buf[f->beg++] = c;
|
||||
return c & 255;
|
||||
} else {
|
||||
b = c;
|
||||
if (!fwrite_unlocked(&b, 1, 1, f)) return -1;
|
||||
return b;
|
||||
}
|
||||
int fputc(int c, FILE *f) {
|
||||
int rc;
|
||||
flockfile(f);
|
||||
rc = fputc_unlocked(c, f);
|
||||
funlockfile(f);
|
||||
return rc;
|
||||
}
|
||||
|
|
38
libc/stdio/fputc_unlocked.c
Normal file
38
libc/stdio/fputc_unlocked.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 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/calls.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* Writes byte to stream.
|
||||
*
|
||||
* @param c is byte to buffer or write, which is masked
|
||||
* @return c as unsigned char if written or -1 w/ errno
|
||||
*/
|
||||
int fputc_unlocked(int c, FILE *f) {
|
||||
unsigned char b;
|
||||
if (c != '\n' && f->beg < f->size && f->bufmode != _IONBF) {
|
||||
f->buf[f->beg++] = c;
|
||||
return c & 255;
|
||||
} else {
|
||||
b = c;
|
||||
if (!fwrite_unlocked(&b, 1, 1, f)) return -1;
|
||||
return b;
|
||||
}
|
||||
}
|
|
@ -19,13 +19,6 @@
|
|||
#include "libc/bits/bits.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static inline noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
|
||||
return (uint64_t)(255 & p[7]) << 070 | (uint64_t)(255 & p[6]) << 060 |
|
||||
(uint64_t)(255 & p[5]) << 050 | (uint64_t)(255 & p[4]) << 040 |
|
||||
(uint64_t)(255 & p[3]) << 030 | (uint64_t)(255 & p[2]) << 020 |
|
||||
(uint64_t)(255 & p[1]) << 010 | (uint64_t)(255 & p[0]) << 000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies at most N bytes from SRC to DST until 𝑐 is encountered.
|
||||
*
|
||||
|
|
|
@ -27,5 +27,5 @@
|
|||
*/
|
||||
privileged nocallersavedregisters errno_t *(__errno_location)(void) {
|
||||
if (!__tls_enabled) return &__errno;
|
||||
return (errno_t *)(__get_tls() + 0x3c);
|
||||
return (errno_t *)(__get_tls_inline() + 0x3c);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
/*-*- 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 │
|
||||
│ 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 │
|
||||
|
@ -16,16 +16,17 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
|
||||
// Writes character to stream.
|
||||
//
|
||||
// @param rdi c is byte to buffer or write, which is masked
|
||||
// @param rsi has stream object pointer
|
||||
// @return c as unsigned char if written or -1 w/ errno
|
||||
// @see fputc_unlocked()
|
||||
// @threadsafe
|
||||
fputc: mov %rsi,%r11
|
||||
ezlea fputc_unlocked,ax
|
||||
jmp stdio_unlock
|
||||
.endfn fputc,globl
|
||||
/**
|
||||
* Returns address of thread information block.
|
||||
*
|
||||
* This function must not be called until TLS is initialized.
|
||||
*
|
||||
* @see __get_tls_inline()
|
||||
* @see __install_tls()
|
||||
* @see clone()
|
||||
*/
|
||||
optimizespeed char *__get_tls(void) {
|
||||
return __get_tls_inline();
|
||||
}
|
|
@ -39,6 +39,7 @@ LIBC_SYSV_A_FILES := \
|
|||
libc/sysv/systemfive.S \
|
||||
libc/sysv/errno_location.greg.c \
|
||||
libc/sysv/errno.c \
|
||||
libc/sysv/gettls.greg.c \
|
||||
libc/sysv/errfun.S \
|
||||
libc/sysv/strace.greg.c \
|
||||
libc/sysv/describeos.greg.c \
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/thread/attr.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
#define MIN_STACKSIZE (8 * PAGESIZE) // includes guard, rounds up to FRAMESIZE
|
||||
#define MIN_GUARDSIZE PAGESIZE
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_THREAD_ATTR_H_
|
||||
#define COSMOPOLITAN_LIBC_THREAD_ATTR_H_
|
||||
|
||||
#define CTHREAD_CREATE_DETACHED 1
|
||||
#define CTHREAD_CREATE_JOINABLE 0
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @fileoverview cosmopolitan thread attributes
|
||||
*/
|
||||
|
||||
typedef struct cthread_attr_t {
|
||||
size_t stacksize, guardsize;
|
||||
int mode;
|
||||
} cthread_attr_t;
|
||||
|
||||
int cthread_attr_init(cthread_attr_t*);
|
||||
int cthread_attr_destroy(cthread_attr_t*);
|
||||
int cthread_attr_setstacksize(cthread_attr_t*, size_t);
|
||||
size_t thread_attr_getstacksize(const cthread_attr_t*);
|
||||
int cthread_attr_setguardsize(cthread_attr_t*, size_t);
|
||||
size_t cthread_attr_getguardsize(const cthread_attr_t*);
|
||||
int cthread_attr_setdetachstate(cthread_attr_t*, int);
|
||||
int cthread_attr_getdetachstate(const cthread_attr_t*);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_ATTR_H_ */
|
|
@ -28,10 +28,7 @@
|
|||
#include "libc/sysv/consts/clone.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/thread/attr.h"
|
||||
#include "libc/thread/create.h"
|
||||
#include "libc/thread/descriptor.h"
|
||||
#include "libc/thread/zombie.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
STATIC_YOINK("_main_thread_ctor");
|
||||
|
||||
|
@ -99,8 +96,8 @@ static int cthread_start(void *arg) {
|
|||
* @return 0 on success, or error number on failure
|
||||
* @threadsafe
|
||||
*/
|
||||
int cthread_create(cthread_t *restrict ptd, const cthread_attr_t *restrict attr,
|
||||
void *(*func)(void *), void *restrict arg) {
|
||||
int cthread_create(cthread_t *ptd, const cthread_attr_t *attr,
|
||||
void *(*func)(void *), void *arg) {
|
||||
int rc, tid;
|
||||
cthread_t td;
|
||||
cthread_attr_t default_attr;
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_THREAD_CREATE_H_
|
||||
#define COSMOPOLITAN_LIBC_THREAD_CREATE_H_
|
||||
#include "libc/thread/attr.h"
|
||||
#include "libc/thread/descriptor.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @fileoverview Create a cosmopolitan thread
|
||||
*/
|
||||
|
||||
int cthread_create(cthread_t *restrict, const cthread_attr_t *restrict,
|
||||
void *(*)(void *), void *restrict);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_CREATE_H_ */
|
|
@ -1,41 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_THREAD_DESCRIPTOR_H_
|
||||
#define COSMOPOLITAN_LIBC_THREAD_DESCRIPTOR_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* @fileoverview thread types
|
||||
*/
|
||||
|
||||
enum cthread_state {
|
||||
cthread_started = 0,
|
||||
cthread_joining = 1,
|
||||
cthread_finished = 2,
|
||||
cthread_detached = 4,
|
||||
cthread_main = 127,
|
||||
};
|
||||
|
||||
struct cthread_descriptor_t {
|
||||
struct cthread_descriptor_t *self; /* 0x00 */
|
||||
void *(*func)(void *); /* 0x08 */
|
||||
int32_t __pad0; /* 0x10 */
|
||||
int32_t state; /* 0x14 */
|
||||
void *arg; /* 0x18 */
|
||||
void *pthread_ret_ptr; /* 0x20 */
|
||||
int64_t __pad1; /* 0x28 */
|
||||
struct cthread_descriptor_t *self2; /* 0x30 */
|
||||
int32_t tid; /* 0x38 */
|
||||
int32_t err; /* 0x3c */
|
||||
void *exitcode;
|
||||
struct {
|
||||
char *top, *bottom;
|
||||
} stack, alloc;
|
||||
jmp_buf exiter;
|
||||
};
|
||||
|
||||
typedef struct cthread_descriptor_t *cthread_t;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_DESCRIPTOR_H_ */
|
|
@ -22,8 +22,7 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/thread/descriptor.h"
|
||||
#include "libc/thread/detach.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
/**
|
||||
* Detaches thread.
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_THREAD_DETACH_H_
|
||||
#define COSMOPOLITAN_LIBC_THREAD_DETACH_H_
|
||||
#include "libc/thread/descriptor.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @fileoverview detach a thread
|
||||
*/
|
||||
|
||||
int cthread_detach(cthread_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_DETACH_H_ */
|
||||
|
|
@ -18,8 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/thread/exit.h"
|
||||
#include "libc/thread/self.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
/**
|
||||
* Exits cosmopolitan thread.
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_THREAD_EXIT_H_
|
||||
#define COSMOPOLITAN_LIBC_THREAD_EXIT_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
wontreturn void cthread_exit(void *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_EXIT_H_ */
|
|
@ -3,8 +3,6 @@
|
|||
#include "libc/bits/asmflag.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/errno.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @fileoverview FreeBSD Threading
|
||||
|
@ -13,6 +11,13 @@ COSMOPOLITAN_C_START_
|
|||
* maximum legal range is PID_MAX + 2 (100001) through INT_MAX
|
||||
*/
|
||||
|
||||
#define UMTX_OP_MUTEX_WAIT 17
|
||||
#define UMTX_OP_MUTEX_WAKE 18
|
||||
#define UMTX_ABSTIME 1
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct rtprio {
|
||||
uint16_t type; /* scheduling class */
|
||||
uint16_t prio;
|
||||
|
@ -31,6 +36,14 @@ struct thr_param {
|
|||
struct rtprio *rtp;
|
||||
};
|
||||
|
||||
struct _umtx_time {
|
||||
struct timespec _timeout;
|
||||
uint32_t _flags;
|
||||
uint32_t _clockid;
|
||||
};
|
||||
|
||||
int _umtx_op(void *, int, unsigned long, void *, void *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_FREEBSD_INTERNAL_H_ */
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/thread/descriptor.h"
|
||||
#include "libc/thread/self.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
static textstartup void _main_thread_init(void) {
|
||||
_Static_assert(offsetof(struct cthread_descriptor_t, self) == 0x00, "");
|
||||
|
@ -67,6 +66,7 @@ static textstartup void _main_thread_init(void) {
|
|||
// Set FS
|
||||
__install_tls((char *)td);
|
||||
assert(cthread_self()->tid == gettid());
|
||||
__threaded = true;
|
||||
}
|
||||
|
||||
const void *const _main_thread_ctor[] initarray = {
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/futex.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/thread/descriptor.h"
|
||||
#include "libc/thread/join.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
/**
|
||||
* Waits for thread to terminate and frees its memory.
|
||||
|
@ -43,7 +42,7 @@
|
|||
* @threadsafe
|
||||
*/
|
||||
int cthread_join(cthread_t td, void **exitcode) {
|
||||
int rc, tid;
|
||||
int x, rc, tid;
|
||||
// otherwise, tid could be set to 0 even though `state` is not
|
||||
// finished mark thread as joining
|
||||
if (!td || (IsAsan() && !__asan_is_valid(td, sizeof(*td)))) {
|
||||
|
@ -55,11 +54,10 @@ int cthread_join(cthread_t td, void **exitcode) {
|
|||
rc = EINVAL;
|
||||
} else {
|
||||
if (~atomic_fetch_add(&td->state, cthread_joining) & cthread_finished) {
|
||||
if (IsLinux() || IsOpenbsd()) {
|
||||
while ((x = atomic_load(&td->tid))) {
|
||||
// FUTEX_WAIT_PRIVATE makes it hang
|
||||
futex((uint32_t *)&td->tid, FUTEX_WAIT, tid, 0, 0);
|
||||
cthread_memory_wait32((uint32_t *)&td->tid, x, 0);
|
||||
}
|
||||
_spinlock(&td->tid);
|
||||
}
|
||||
if (exitcode) {
|
||||
*exitcode = td->exitcode;
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_THREAD_JOIN_H_
|
||||
#define COSMOPOLITAN_LIBC_THREAD_JOIN_H_
|
||||
#include "libc/thread/descriptor.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int cthread_join(cthread_t, void **);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_JOIN_H_ */
|
|
@ -16,7 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/thread/self.h"
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
STATIC_YOINK("_main_thread_ctor");
|
||||
|
||||
|
@ -24,5 +25,5 @@ STATIC_YOINK("_main_thread_ctor");
|
|||
* Returns thread descriptor of the current thread.
|
||||
*/
|
||||
cthread_t(cthread_self)(void) {
|
||||
return cthread_self();
|
||||
return (cthread_t)__get_tls_inline();
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_THREAD_SELF_H_
|
||||
#define COSMOPOLITAN_LIBC_THREAD_SELF_H_
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
#include "libc/thread/descriptor.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern const void *const _main_thread_ctor[];
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#define cthread_self() \
|
||||
({ \
|
||||
YOINK(_main_thread_ctor); \
|
||||
((cthread_t)__get_tls()); \
|
||||
})
|
||||
#else
|
||||
cthread_t cthread_self(void);
|
||||
#endif
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_SELF_H_ */
|
|
@ -17,9 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/atomic.h"
|
||||
#include "libc/thread/sem.h"
|
||||
#include "libc/thread/wait.h"
|
||||
#include "libc/thread/yield.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
STATIC_YOINK("_main_thread_ctor");
|
||||
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_THREAD_NATIVESEM_H_
|
||||
#define COSMOPOLITAN_LIBC_THREAD_NATIVESEM_H_
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @fileoverview native semaphore for implementation details
|
||||
*/
|
||||
|
||||
typedef union cthread_sem_t {
|
||||
struct {
|
||||
uint64_t count;
|
||||
} linux;
|
||||
} cthread_sem_t;
|
||||
|
||||
int cthread_sem_init(cthread_sem_t *, int);
|
||||
int cthread_sem_destroy(cthread_sem_t *);
|
||||
int cthread_sem_wait(cthread_sem_t *, int, const struct timespec *);
|
||||
int cthread_sem_signal(cthread_sem_t *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_SELF_H_ */
|
80
libc/thread/thread.h
Normal file
80
libc/thread/thread.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_THREAD_THREAD_H_
|
||||
#define COSMOPOLITAN_LIBC_THREAD_THREAD_H_
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
#define CTHREAD_CREATE_DETACHED 1
|
||||
#define CTHREAD_CREATE_JOINABLE 0
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
enum cthread_state {
|
||||
cthread_started = 0,
|
||||
cthread_joining = 1,
|
||||
cthread_finished = 2,
|
||||
cthread_detached = 4,
|
||||
cthread_main = 127,
|
||||
};
|
||||
|
||||
struct cthread_descriptor_t {
|
||||
struct cthread_descriptor_t *self; /* 0x00 */
|
||||
void *(*func)(void *); /* 0x08 */
|
||||
int32_t __pad0; /* 0x10 */
|
||||
int32_t state; /* 0x14 */
|
||||
void *arg; /* 0x18 */
|
||||
void *pthread_ret_ptr; /* 0x20 */
|
||||
int64_t __pad1; /* 0x28 */
|
||||
struct cthread_descriptor_t *self2; /* 0x30 */
|
||||
int32_t tid; /* 0x38 */
|
||||
int32_t err; /* 0x3c */
|
||||
void *exitcode;
|
||||
struct {
|
||||
char *top, *bottom;
|
||||
} stack, alloc;
|
||||
jmp_buf exiter;
|
||||
};
|
||||
|
||||
typedef struct cthread_descriptor_t *cthread_t;
|
||||
|
||||
typedef union cthread_sem_t {
|
||||
struct {
|
||||
uint64_t count;
|
||||
} linux;
|
||||
} cthread_sem_t;
|
||||
|
||||
typedef struct cthread_attr_t {
|
||||
size_t stacksize, guardsize;
|
||||
int mode;
|
||||
} cthread_attr_t;
|
||||
|
||||
extern const void *const _main_thread_ctor[];
|
||||
|
||||
int cthread_create(cthread_t *, const cthread_attr_t *, void *(*)(void *),
|
||||
void *);
|
||||
|
||||
int cthread_yield(void);
|
||||
cthread_t cthread_self(void);
|
||||
int cthread_join(cthread_t, void **);
|
||||
void cthread_exit(void *) wontreturn;
|
||||
int cthread_detach(cthread_t);
|
||||
int cthread_attr_init(cthread_attr_t *);
|
||||
int cthread_attr_destroy(cthread_attr_t *);
|
||||
int cthread_attr_setstacksize(cthread_attr_t *, size_t);
|
||||
size_t thread_attr_getstacksize(const cthread_attr_t *);
|
||||
int cthread_attr_setguardsize(cthread_attr_t *, size_t);
|
||||
size_t cthread_attr_getguardsize(const cthread_attr_t *);
|
||||
int cthread_attr_setdetachstate(cthread_attr_t *, int);
|
||||
int cthread_attr_getdetachstate(const cthread_attr_t *);
|
||||
int cthread_sem_init(cthread_sem_t *, int);
|
||||
int cthread_sem_destroy(cthread_sem_t *);
|
||||
int cthread_sem_wait(cthread_sem_t *, int, const struct timespec *);
|
||||
int cthread_sem_signal(cthread_sem_t *);
|
||||
int cthread_memory_wait32(uint32_t *, uint32_t, const struct timespec *);
|
||||
int cthread_memory_wake32(uint32_t *, int);
|
||||
void cthread_zombies_add(cthread_t);
|
||||
void cthread_zombies_reap(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_THREAD_H_ */
|
|
@ -19,12 +19,33 @@
|
|||
#include "libc/bits/atomic.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/consts/futex.h"
|
||||
#include "libc/thread/freebsd.internal.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
int cthread_memory_wait32(uint32_t* addr, uint32_t val,
|
||||
const struct timespec* timeout) {
|
||||
size_t size;
|
||||
struct _umtx_time *put, ut;
|
||||
if (IsLinux() || IsOpenbsd()) {
|
||||
return futex(addr, FUTEX_WAIT, val, timeout, 0);
|
||||
|
||||
#if 0
|
||||
} else if (IsFreebsd()) {
|
||||
if (!timeout) {
|
||||
put = 0;
|
||||
size = 0;
|
||||
} else {
|
||||
ut._flags = 0;
|
||||
ut._clockid = CLOCK_REALTIME;
|
||||
ut._timeout = *timeout;
|
||||
put = &ut;
|
||||
size = sizeof(ut);
|
||||
}
|
||||
return _umtx_op(addr, UMTX_OP_MUTEX_WAIT, 0, &size, put);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
unsigned tries;
|
||||
for (tries = 1; atomic_load(addr) == val; ++tries) {
|
||||
|
@ -41,6 +62,10 @@ int cthread_memory_wait32(uint32_t* addr, uint32_t val,
|
|||
int cthread_memory_wake32(uint32_t* addr, int n) {
|
||||
if (IsLinux() || IsOpenbsd()) {
|
||||
return futex(addr, FUTEX_WAKE, n, 0, 0);
|
||||
#if 0
|
||||
} else if (IsFreebsd()) {
|
||||
return _umtx_op(addr, UMTX_OP_MUTEX_WAKE, n, 0, 0);
|
||||
#endif
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_THREAD_WAIT_H_
|
||||
#define COSMOPOLITAN_LIBC_THREAD_WAIT_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @fileoverview wait on memory
|
||||
*/
|
||||
struct timespec;
|
||||
|
||||
int cthread_memory_wait32(uint32_t*, uint32_t, const struct timespec*);
|
||||
int cthread_memory_wake32(uint32_t*, int);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_WAIT_H_ */
|
|
@ -17,7 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/thread/yield.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
/**
|
||||
* Asks operating system to handoff remaining time slice.
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_THREAD_YIELD_H_
|
||||
#define COSMOPOLITAN_LIBC_THREAD_YIELD_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @fileoverview yield thread to OS scheduler
|
||||
*/
|
||||
|
||||
int cthread_yield(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_YIELD_H_ */
|
|
@ -19,7 +19,7 @@
|
|||
#include "libc/bits/atomic.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/thread/zombie.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
static struct Zombie {
|
||||
struct Zombie *next;
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_THREAD_ZOMBIE_H_
|
||||
#define COSMOPOLITAN_LIBC_THREAD_ZOMBIE_H_
|
||||
#include "libc/thread/descriptor.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void cthread_zombies_add(cthread_t);
|
||||
void cthread_zombies_reap(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_ZOMBIE_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue