mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-13 22:49:11 +00:00
Make more fixes and improvements
- Remove PAGESIZE constant - Fix realloc() documentation - Fix ttyname_r() error reporting - Make forking more reliable on Windows - Make execvp() a few microseconds faster - Make system() a few microseconds faster - Tighten up the socket-related magic numbers - Loosen restrictions on mmap() offset alignment - Improve GetProgramExecutableName() with getenv("_") - Use mkstemp() as basis for mktemp(), tmpfile(), tmpfd() - Fix flakes in pthread_cancel_test, unix_test, fork_test - Fix recently introduced futex stack overflow regression - Let sockets be passed as stdio to subprocesses on Windows - Improve security of bind() on Windows w/ SO_EXCLUSIVEADDRUSE
This commit is contained in:
parent
140a8a52e5
commit
18bb5888e1
311 changed files with 1239 additions and 2622 deletions
|
@ -54,9 +54,11 @@ int _pthread_cancel_sys(void) {
|
|||
|
||||
static void OnSigThr(int sig, siginfo_t *si, void *ctx) {
|
||||
ucontext_t *uc = ctx;
|
||||
struct CosmoTib *t = __get_tls();
|
||||
struct PosixThread *pt = (struct PosixThread *)t->tib_pthread;
|
||||
if (pt && !(pt->flags & PT_NOCANCEL) &&
|
||||
struct CosmoTib *t;
|
||||
struct PosixThread *pt;
|
||||
if ((t = __get_tls()) && // TODO: why can it be null on freebsd?
|
||||
(pt = (struct PosixThread *)t->tib_pthread) &&
|
||||
!(pt->flags & PT_NOCANCEL) &&
|
||||
atomic_load_explicit(&pt->cancelled, memory_order_acquire)) {
|
||||
sigaddset(&uc->uc_sigmask, sig);
|
||||
if (systemfive_cancellable <= (char *)uc->uc_mcontext.rip &&
|
||||
|
@ -255,14 +257,21 @@ static void ListenForSigThr(void) {
|
|||
* while running read(). Masked mode doesn't have second chances. You
|
||||
* must rigorously check the results of each cancellation point call.
|
||||
*
|
||||
* Unit tests should be able to safely ignore the return value, or at
|
||||
* the very least be programmed to consider ESRCH a successful status
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
* @raise ESRCH if thread isn't alive
|
||||
* @raise ESRCH if system thread wasn't alive or we lost a race
|
||||
*/
|
||||
errno_t pthread_cancel(pthread_t thread) {
|
||||
int e, rc, tid;
|
||||
static bool once;
|
||||
struct PosixThread *pt;
|
||||
if (!once) ListenForSigThr(), once = true;
|
||||
__require_tls();
|
||||
if (!once) {
|
||||
ListenForSigThr();
|
||||
once = true;
|
||||
}
|
||||
pt = (struct PosixThread *)thread;
|
||||
switch (atomic_load_explicit(&pt->status, memory_order_acquire)) {
|
||||
case kPosixThreadZombie:
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/bsr.h"
|
||||
#include "libc/intrin/dll.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/internal.h"
|
||||
|
@ -53,6 +54,10 @@ __static_yoink("_pthread_atfork");
|
|||
#define MAP_ANON_OPENBSD 0x1000
|
||||
#define MAP_STACK_OPENBSD 0x4000
|
||||
|
||||
static unsigned long roundup2pow(unsigned long x) {
|
||||
return x > 1 ? 2ul << _bsrl(x - 1) : x ? 1 : 0;
|
||||
}
|
||||
|
||||
void _pthread_free(struct PosixThread *pt) {
|
||||
if (pt->flags & PT_STATIC) return;
|
||||
free(pt->tls);
|
||||
|
@ -104,13 +109,14 @@ static int FixupCustomStackOnOpenbsd(pthread_attr_t *attr) {
|
|||
// in order to successfully call mmap(), which will return EINVAL if
|
||||
// these calculations should overflow.
|
||||
size_t n;
|
||||
int e, rc;
|
||||
uintptr_t x, y;
|
||||
int e, rc, pagesz;
|
||||
pagesz = getauxval(AT_PAGESZ);
|
||||
n = attr->__stacksize;
|
||||
x = (uintptr_t)attr->__stackaddr;
|
||||
y = ROUNDUP(x, PAGESIZE);
|
||||
y = ROUNDUP(x, pagesz);
|
||||
n -= y - x;
|
||||
n = ROUNDDOWN(n, PAGESIZE);
|
||||
n = ROUNDDOWN(n, pagesz);
|
||||
e = errno;
|
||||
if (__sys_mmap((void *)y, n, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_FIXED | MAP_ANON_OPENBSD | MAP_STACK_OPENBSD,
|
||||
|
@ -176,7 +182,7 @@ static errno_t pthread_create_impl(pthread_t *thread,
|
|||
default_guardsize = getauxval(AT_PAGESZ);
|
||||
pt->flags = PT_OWNSTACK;
|
||||
pt->attr.__stacksize = MAX(pt->attr.__stacksize, GetStackSize());
|
||||
pt->attr.__stacksize = _roundup2pow(pt->attr.__stacksize);
|
||||
pt->attr.__stacksize = roundup2pow(pt->attr.__stacksize);
|
||||
pt->attr.__guardsize = ROUNDUP(pt->attr.__guardsize, default_guardsize);
|
||||
if (pt->attr.__guardsize + default_guardsize >= pt->attr.__stacksize) {
|
||||
_pthread_free(pt);
|
||||
|
|
46
libc/thread/pthread_once.c
Normal file
46
libc/thread/pthread_once.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*-*- 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/thread/thread.h"
|
||||
#include "third_party/nsync/once.h"
|
||||
|
||||
/**
|
||||
* Ensures initialization function is called exactly once, e.g.
|
||||
*
|
||||
* static void *g_factory;
|
||||
*
|
||||
* static void InitFactory(void) {
|
||||
* g_factory = expensive();
|
||||
* }
|
||||
*
|
||||
* void *GetFactory(void) {
|
||||
* static pthread_once_t once = PTHREAD_ONCE_INIT;
|
||||
* pthread_once(&once, InitFactory);
|
||||
* return g_factory;
|
||||
* }
|
||||
*
|
||||
* If multiple threads try to initialize at the same time, then only a
|
||||
* single one will call `init` and the other threads will block until
|
||||
* the winner has returned from the `init` function.
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
*/
|
||||
errno_t pthread_once(pthread_once_t *once, void init(void)) {
|
||||
nsync_run_once((nsync_once *)once, init);
|
||||
return 0;
|
||||
}
|
|
@ -86,11 +86,11 @@ static sem_t *sem_open_impl(const char *path, int oflag, unsigned mode,
|
|||
return SEM_FAILED;
|
||||
}
|
||||
npassert(!fstat(fd, &st));
|
||||
if (st.st_size < PAGESIZE && ftruncate(fd, PAGESIZE) == -1) {
|
||||
if (st.st_size < 4096 && ftruncate(fd, 4096) == -1) {
|
||||
npassert(!close(fd));
|
||||
return SEM_FAILED;
|
||||
}
|
||||
sem = mmap(0, PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
sem = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (sem != MAP_FAILED) {
|
||||
atomic_store_explicit(&sem->sem_value, value, memory_order_relaxed);
|
||||
sem->sem_magic = SEM_MAGIC_NAMED;
|
||||
|
@ -272,7 +272,7 @@ int sem_close(sem_t *sem) {
|
|||
}
|
||||
sem_open_unlock();
|
||||
if (unmap) {
|
||||
npassert(!munmap(sem, PAGESIZE));
|
||||
npassert(!munmap(sem, 4096));
|
||||
}
|
||||
if (delete) {
|
||||
unlink(s->path);
|
||||
|
|
|
@ -146,7 +146,7 @@ int pthread_condattr_destroy(pthread_condattr_t *) paramsnonnull();
|
|||
int pthread_condattr_getpshared(const pthread_condattr_t *, int *) paramsnonnull();
|
||||
int pthread_condattr_init(pthread_condattr_t *) paramsnonnull();
|
||||
int pthread_condattr_setpshared(pthread_condattr_t *, int) paramsnonnull();
|
||||
int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *) paramsnonnull((1, 3));
|
||||
int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *) paramsnonnull((1));
|
||||
int pthread_detach(pthread_t);
|
||||
int pthread_equal(pthread_t, pthread_t);
|
||||
int pthread_getattr_np(pthread_t, pthread_attr_t *) paramsnonnull();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue