mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-03 16:30:29 +00:00
Merge branch 'master' into ctl-shared
This commit is contained in:
commit
f7178894ee
29 changed files with 945 additions and 608 deletions
|
@ -4,5 +4,5 @@ UNAMES=$(uname -s)
|
|||
if [ x"$UNAMES" = x"Darwin" ] && [ x"$UNAMEM" = x"arm64" ]; then
|
||||
exec ape "$@"
|
||||
else
|
||||
exec "$@"
|
||||
exec rusage "$@"
|
||||
fi
|
||||
|
|
125
examples/aba.c
Normal file
125
examples/aba.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
#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 <assert.h>
|
||||
#include <cosmo.h>
|
||||
#include <pthread.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// lockless push / pop tutorial
|
||||
//
|
||||
// this file demonstrates how to create a singly linked list that can be
|
||||
// pushed and popped across multiple threads, using only atomics. atomic
|
||||
// operations (rather than using a mutex) make push/pop go faster and it
|
||||
// ensures asynchronous signal safety too. therefore it will be safe for
|
||||
// use in a variety of contexts, such as signal handlers.
|
||||
|
||||
#define THREADS 128
|
||||
#define ITERATIONS 10000
|
||||
|
||||
// adjust mask based on alignment of list struct
|
||||
//
|
||||
// - 0x00fffffffffffff0 may be used if List* is always 16-byte aligned.
|
||||
// We know that's the case here, because we call malloc() to create
|
||||
// every List* object, and malloc() results are always max aligned.
|
||||
//
|
||||
// - 0x00fffffffffffff8 may be used if List* is always 8-byte aligned.
|
||||
// This might be the case if you're pushing and popping stuff that was
|
||||
// allocated from an array, to avoid malloc() calls. This has one
|
||||
// fewer byte of safeguards against the ABA problem though.
|
||||
//
|
||||
// - 0x00fffffffffff000 may be used if List* is always page aligned.
|
||||
// This is a good choice if you use mmap() to allocate each List*
|
||||
// element, since it offers maximum protection against ABA.
|
||||
//
|
||||
// - only the highest byte of a 64-bit pointer is safe to use on our
|
||||
// supported platforms. on most x86 and arm systems, it's possible to
|
||||
// use the top sixteen bits. however that's not the case on more
|
||||
// recent high end x86-64 systems that have pml5t.
|
||||
//
|
||||
#define MASQUE 0x00fffffffffffff0
|
||||
|
||||
#define PTR(x) ((uintptr_t)(x) & MASQUE)
|
||||
#define TAG(x) ROL((uintptr_t)(x) & ~MASQUE, 8)
|
||||
#define ABA(p, t) ((uintptr_t)(p) | (ROR((uintptr_t)(t), 8) & ~MASQUE))
|
||||
#define ROL(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
|
||||
#define ROR(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
|
||||
|
||||
struct List {
|
||||
struct List* next;
|
||||
int count;
|
||||
};
|
||||
|
||||
atomic_uintptr_t list;
|
||||
|
||||
void push(struct List* elem) {
|
||||
uintptr_t tip;
|
||||
assert(!TAG(elem));
|
||||
for (tip = atomic_load_explicit(&list, memory_order_relaxed);;) {
|
||||
elem->next = (struct List*)PTR(tip);
|
||||
if (atomic_compare_exchange_weak_explicit(
|
||||
&list, &tip, ABA(elem, TAG(tip) + 1), memory_order_release,
|
||||
memory_order_relaxed))
|
||||
break;
|
||||
pthread_pause_np();
|
||||
}
|
||||
}
|
||||
|
||||
struct List* pop(void) {
|
||||
uintptr_t tip;
|
||||
struct List* elem;
|
||||
tip = atomic_load_explicit(&list, memory_order_relaxed);
|
||||
while ((elem = (struct List*)PTR(tip))) {
|
||||
if (atomic_compare_exchange_weak_explicit(
|
||||
&list, &tip, ABA(elem->next, TAG(tip) + 1), memory_order_acquire,
|
||||
memory_order_relaxed))
|
||||
break;
|
||||
pthread_pause_np();
|
||||
}
|
||||
return elem;
|
||||
}
|
||||
|
||||
void* tester(void* arg) {
|
||||
struct List* elem;
|
||||
for (int i = 0; i < ITERATIONS; ++i) {
|
||||
while (!(elem = pop())) {
|
||||
elem = malloc(sizeof(*elem));
|
||||
elem->count = 0;
|
||||
push(elem);
|
||||
}
|
||||
elem->count++;
|
||||
push(elem);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("testing aba problem...");
|
||||
fflush(stdout);
|
||||
pthread_t th[THREADS];
|
||||
for (int i = 0; i < THREADS; ++i)
|
||||
pthread_create(&th[i], 0, tester, 0);
|
||||
for (int i = 0; i < THREADS; ++i)
|
||||
pthread_join(th[i], 0);
|
||||
int sum = 0;
|
||||
struct List* elem;
|
||||
while ((elem = pop())) {
|
||||
printf(" %d", elem->count);
|
||||
sum += elem->count;
|
||||
free(elem);
|
||||
}
|
||||
printf("\n");
|
||||
assert(sum == ITERATIONS * THREADS);
|
||||
printf("you are the dancing queen\n");
|
||||
CheckForMemoryLeaks();
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
#include "libc/ctype.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Roman Transliteration, e.g.
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "libc/elf/tinyelf.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/directmap.h"
|
||||
#include "libc/intrin/promises.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
@ -37,7 +38,6 @@
|
|||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
static struct {
|
||||
atomic_uint once;
|
||||
const char *res;
|
||||
char buf[PATH_MAX];
|
||||
} g_comdbg;
|
||||
|
@ -69,35 +69,26 @@ static int GetElfMachine(void) {
|
|||
}
|
||||
|
||||
static bool IsMyDebugBinary(const char *path) {
|
||||
void *addr;
|
||||
int64_t size;
|
||||
uintptr_t value;
|
||||
bool res = false;
|
||||
int fd, e = errno;
|
||||
struct DirectMap dm;
|
||||
BLOCK_CANCELATION;
|
||||
if ((fd = open(path, O_RDONLY | O_CLOEXEC, 0)) != -1) {
|
||||
// sanity test that this .com.dbg file (1) is an elf image, and (2)
|
||||
// contains the same number of bytes of code as our .com executable
|
||||
// which is currently running in memory.
|
||||
if ((size = lseek(fd, 0, SEEK_END)) != -1 &&
|
||||
(dm = sys_mmap((void *)0x12345000000, size, PROT_READ, MAP_SHARED, fd,
|
||||
0))
|
||||
.addr != MAP_FAILED) {
|
||||
if (READ32LE((char *)dm.addr) == READ32LE("\177ELF") &&
|
||||
((Elf64_Ehdr *)dm.addr)->e_machine == GetElfMachine() &&
|
||||
GetElfSymbolValue(dm.addr, "_etext", &value)) {
|
||||
(addr = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)) != MAP_FAILED) {
|
||||
if (READ32LE((char *)addr) == READ32LE("\177ELF") &&
|
||||
((Elf64_Ehdr *)addr)->e_machine == GetElfMachine() &&
|
||||
GetElfSymbolValue(addr, "_etext", &value)) {
|
||||
res = !_etext || value == (uintptr_t)_etext;
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
sys_munmap(dm.addr, size);
|
||||
} else {
|
||||
CloseHandle(dm.maphandle);
|
||||
UnmapViewOfFile(dm.addr);
|
||||
}
|
||||
munmap(addr, size);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
ALLOW_CANCELATION;
|
||||
errno = e;
|
||||
return res;
|
||||
}
|
||||
|
@ -106,7 +97,7 @@ static void FindDebugBinaryInit(void) {
|
|||
const char *comdbg;
|
||||
if (issetugid())
|
||||
return;
|
||||
if ((comdbg = getenv("COMDBG")) && IsMyDebugBinary(comdbg)) {
|
||||
if ((comdbg = getenv("COMDBG"))) {
|
||||
g_comdbg.res = comdbg;
|
||||
return;
|
||||
}
|
||||
|
@ -125,9 +116,18 @@ static void FindDebugBinaryInit(void) {
|
|||
/**
|
||||
* Returns path of binary with the debug information, or null.
|
||||
*
|
||||
* @return path to debug binary, or NULL
|
||||
* You can specify the COMDBG environment variable, with the path of the
|
||||
* debug binary, in case the automatic heuristics fail. What we look for
|
||||
* is GetProgramExecutableName() with ".dbg", ".com.dbg", etc. appended.
|
||||
*
|
||||
* @return path to debug binary, or NULL if we couldn't find it
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
const char *FindDebugBinary(void) {
|
||||
cosmo_once(&g_comdbg.once, FindDebugBinaryInit);
|
||||
return g_comdbg.res;
|
||||
}
|
||||
|
||||
// pay startup cost to make this signal safe from the user's perspective
|
||||
__attribute__((__constructor__(10))) static void FindDebugBinaryCtor(void) {
|
||||
FindDebugBinaryInit();
|
||||
}
|
||||
|
|
|
@ -232,6 +232,21 @@
|
|||
* option might not be a good idea if you're pledging `exec` because
|
||||
* subprocesses can't inherit the `SIGSYS` handler this installs.
|
||||
*
|
||||
* If you experience crashes during startup when execve'ing a cosmo
|
||||
* binary that's had permissions like rpath pledged away, then try doing
|
||||
* this before calling execve. This prevents special startup checks.
|
||||
*
|
||||
* putenv("COMDBG=program.dbg");
|
||||
*
|
||||
* If having pledge() security is mission critical, then add this code
|
||||
* to the start of your main() function to ensure your program fails
|
||||
* with an error if it isn't available.
|
||||
*
|
||||
* if (pledge(0, 0)) {
|
||||
* fprintf(stderr, "error: OS doesn't support pledge() security\n");
|
||||
* exit(1);
|
||||
* }
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise ENOSYS if `pledge(0, 0)` was used and security is not possible
|
||||
* @raise EINVAL if `execpromises` on Linux isn't a subset of `promises`
|
||||
|
|
|
@ -405,6 +405,15 @@ int sys_unveil_linux(const char *path, const char *permissions) {
|
|||
* - `c` allows `path` to be created and removed, corresponding to
|
||||
* the pledge promise "cpath".
|
||||
*
|
||||
* If having unveil() security is mission critical, then add this code
|
||||
* to the start of your main() function to ensure your program fails
|
||||
* with an error if it isn't available.
|
||||
*
|
||||
* if (unveil("", 0) >= 0) {
|
||||
* fprintf(stderr, "error: OS doesn't support unveil() security\n");
|
||||
* exit(1);
|
||||
* }
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno; note: if `unveil("",0)` is used
|
||||
* to perform a feature check, then on Linux a value greater than 0
|
||||
* shall be returned which is the supported Landlock ABI version
|
||||
|
|
|
@ -531,10 +531,6 @@ typedef struct {
|
|||
#pragma GCC diagnostic ignored "-Wold-style-definition" /* orwellian bullsh */
|
||||
#endif
|
||||
|
||||
#if !defined(__cplusplus) && defined(__GNUC__) && __GNUC__ >= 14
|
||||
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
|
||||
#endif
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define DebugBreak() __asm__("int3")
|
||||
#elif defined(__aarch64__)
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2024 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/intrin/atomic.h"
|
||||
|
||||
bool dog(_Atomic(long) *p, long *e, long w) {
|
||||
return atomic_compare_exchange_weak_explicit(p, e, w, memory_order_acq_rel,
|
||||
memory_order_relaxed);
|
||||
}
|
|
@ -29,7 +29,7 @@ struct Map {
|
|||
struct Maps {
|
||||
struct Tree *maps;
|
||||
_Atomic(uint64_t) lock;
|
||||
_Atomic(struct Map *) freed;
|
||||
_Atomic(uintptr_t) freed;
|
||||
size_t count;
|
||||
size_t pages;
|
||||
_Atomic(char *) pick;
|
||||
|
|
|
@ -50,6 +50,13 @@
|
|||
|
||||
#define PGUP(x) (((x) + pagesz - 1) & -pagesz)
|
||||
|
||||
#define MASQUE 0x00fffffffffffff8
|
||||
#define PTR(x) ((uintptr_t)(x) & MASQUE)
|
||||
#define TAG(x) ROL((uintptr_t)(x) & ~MASQUE, 8)
|
||||
#define ABA(p, t) ((uintptr_t)(p) | (ROR((uintptr_t)(t), 8) & ~MASQUE))
|
||||
#define ROL(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
|
||||
#define ROR(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
|
||||
|
||||
#if !MMDEBUG
|
||||
#define ASSERT(x) (void)0
|
||||
#else
|
||||
|
@ -227,14 +234,17 @@ StartOver:
|
|||
}
|
||||
|
||||
void __maps_free(struct Map *map) {
|
||||
uintptr_t tip;
|
||||
ASSERT(!TAG(map));
|
||||
map->size = 0;
|
||||
map->addr = MAP_FAILED;
|
||||
map->freed = atomic_load_explicit(&__maps.freed, memory_order_relaxed);
|
||||
for (;;) {
|
||||
if (atomic_compare_exchange_weak_explicit(&__maps.freed, &map->freed, map,
|
||||
memory_order_release,
|
||||
for (tip = atomic_load_explicit(&__maps.freed, memory_order_relaxed);;) {
|
||||
map->freed = (struct Map *)PTR(tip);
|
||||
if (atomic_compare_exchange_weak_explicit(
|
||||
&__maps.freed, &tip, ABA(map, TAG(tip) + 1), memory_order_release,
|
||||
memory_order_relaxed))
|
||||
break;
|
||||
pthread_pause_np();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,12 +307,13 @@ void __maps_insert(struct Map *map) {
|
|||
|
||||
struct Map *__maps_alloc(void) {
|
||||
struct Map *map;
|
||||
map = atomic_load_explicit(&__maps.freed, memory_order_relaxed);
|
||||
while (map) {
|
||||
if (atomic_compare_exchange_weak_explicit(&__maps.freed, &map, map->freed,
|
||||
memory_order_acquire,
|
||||
memory_order_relaxed))
|
||||
uintptr_t tip = atomic_load_explicit(&__maps.freed, memory_order_relaxed);
|
||||
while ((map = (struct Map *)PTR(tip))) {
|
||||
if (atomic_compare_exchange_weak_explicit(
|
||||
&__maps.freed, &tip, ABA(map->freed, TAG(tip) + 1),
|
||||
memory_order_acquire, memory_order_relaxed))
|
||||
return map;
|
||||
pthread_pause_np();
|
||||
}
|
||||
int gransz = __gransize;
|
||||
struct DirectMap sys = sys_mmap(0, gransz, PROT_READ | PROT_WRITE,
|
||||
|
|
|
@ -59,7 +59,7 @@ textwindows int WSARecv(
|
|||
}
|
||||
if (UNLIKELY(__strace > 0) && strace_enabled(0) > 0) {
|
||||
kprintf(STRACE_PROLOGUE "WSARecv(%lu, [", s);
|
||||
DescribeIovNt(inout_lpBuffers, dwBufferCount,
|
||||
_DescribeIovNt(inout_lpBuffers, dwBufferCount,
|
||||
rc != -1 ? NumberOfBytesRecvd : 0);
|
||||
kprintf("], %u, [%'u], %p, %s, %p) → %d% lm\n", dwBufferCount,
|
||||
NumberOfBytesRecvd, inout_lpFlags,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#define MIN3(a, b, c) \
|
||||
((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c)))
|
||||
|
|
|
@ -7,7 +7,7 @@ struct NtIovec {
|
|||
char *buf;
|
||||
};
|
||||
|
||||
void DescribeIovNt(const struct NtIovec *, uint32_t, ssize_t);
|
||||
void _DescribeIovNt(const struct NtIovec *, uint32_t, ssize_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_IOVEC_H_ */
|
||||
|
|
|
@ -9,9 +9,9 @@ struct NtSecurityAttributes {
|
|||
bool32 bInheritHandle;
|
||||
};
|
||||
|
||||
const char *DescribeNtSecurityAttributes(char[32],
|
||||
const char *_DescribeNtSecurityAttributes(char[32],
|
||||
const struct NtSecurityAttributes *);
|
||||
#define DescribeNtSecurityAttributes(x) \
|
||||
DescribeNtSecurityAttributes(alloca(32), x)
|
||||
_DescribeNtSecurityAttributes(alloca(32), x)
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_SECURITYATTRIBUTES_H_ */
|
||||
|
|
|
@ -119,7 +119,7 @@ void __morph_begin(void) libcesque;
|
|||
void __morph_end(void) libcesque;
|
||||
void __jit_begin(void) libcesque;
|
||||
void __jit_end(void) libcesque;
|
||||
void __clear_cache(void *, void *) libcesque;
|
||||
void __clear_cache(void *, void *);
|
||||
/* portability */
|
||||
bool32 IsGenuineBlink(void) libcesque;
|
||||
bool32 IsCygwin(void) libcesque;
|
||||
|
|
|
@ -44,9 +44,6 @@ $(LIBC_STR_A).pkg: \
|
|||
$(LIBC_STR_A_OBJS) \
|
||||
$(foreach x,$(LIBC_STR_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/libc/str/wow.o: private \
|
||||
CC = gcc
|
||||
|
||||
o/$(MODE)/libc/str/wmemset.o \
|
||||
o/$(MODE)/libc/str/memset16.o \
|
||||
o/$(MODE)/libc/str/dosdatetimetounix.o: private \
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -109,12 +109,15 @@ TEST(pledge, execpromises_notok) {
|
|||
int ws, pid;
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
putenv("COMDBG=REDACTED");
|
||||
__pledge_mode = PLEDGE_PENALTY_RETURN_EPERM;
|
||||
ASSERT_SYS(0, 0, pledge("stdio rpath exec", "stdio"));
|
||||
execl("sock.elf", "sock.elf", 0);
|
||||
_Exit(127);
|
||||
}
|
||||
EXPECT_NE(-1, wait(&ws));
|
||||
EXPECT_FALSE(WIFSIGNALED(ws));
|
||||
EXPECT_EQ(0, WTERMSIG(ws));
|
||||
EXPECT_TRUE(WIFEXITED(ws));
|
||||
EXPECT_EQ(129, WEXITSTATUS(ws));
|
||||
}
|
||||
|
@ -532,6 +535,7 @@ TEST(pledge, execpromises_ok) {
|
|||
int ws, pid;
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
putenv("COMDBG=REDACTED");
|
||||
ASSERT_SYS(0, 0, pledge("stdio exec", "stdio"));
|
||||
execl("life.elf", "life.elf", 0);
|
||||
_Exit(127);
|
||||
|
@ -547,6 +551,7 @@ TEST(pledge, execpromises_notok1) {
|
|||
int ws, pid;
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
putenv("COMDBG=REDACTED");
|
||||
ASSERT_SYS(0, 0, pledge("stdio exec", "stdio"));
|
||||
execl("sock.elf", "sock.elf", 0);
|
||||
_Exit(127);
|
||||
|
@ -562,6 +567,7 @@ TEST(pledge, execpromises_reducesAtExecOnLinux) {
|
|||
int ws, pid;
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
putenv("COMDBG=REDACTED");
|
||||
ASSERT_SYS(0, 0, pledge("stdio inet tty exec", "stdio tty"));
|
||||
execl("sock.elf", "sock.elf", 0);
|
||||
_Exit(127);
|
||||
|
@ -619,6 +625,7 @@ TEST(pledge_openbsd, execpromises_notok) {
|
|||
int ws, pid;
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
putenv("COMDBG=REDACTED");
|
||||
ASSERT_SYS(0, 0, pledge("stdio exec", "stdio"));
|
||||
execl("sock.elf", "sock.elf", 0);
|
||||
_Exit(127);
|
||||
|
|
1
third_party/dlmalloc/threaded.inc
vendored
1
third_party/dlmalloc/threaded.inc
vendored
|
@ -25,6 +25,7 @@
|
|||
#include "libc/thread/thread.h"
|
||||
#include "libc/thread/threads.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/calls/struct/cpuset.h"
|
||||
#include "third_party/dlmalloc/dlmalloc.h"
|
||||
|
||||
#if !FOOTERS || !MSPACES
|
||||
|
|
1
third_party/lua/lua.main.c
vendored
1
third_party/lua/lua.main.c
vendored
|
@ -50,6 +50,7 @@
|
|||
#include "third_party/lua/lrepl.h"
|
||||
#include "third_party/lua/lualib.h"
|
||||
#include "third_party/lua/lunix.h"
|
||||
#include "libc/cosmo.h"
|
||||
#include "libc/mem/leaks.h"
|
||||
__static_yoink("lua_notice");
|
||||
|
||||
|
|
65
third_party/nsync/common.c
vendored
65
third_party/nsync/common.c
vendored
|
@ -15,6 +15,7 @@
|
|||
│ See the License for the specific language governing permissions and │
|
||||
│ limitations under the License. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
@ -136,14 +137,45 @@ waiter *nsync_dll_waiter_samecond_ (struct Dll *e) {
|
|||
|
||||
/* -------------------------------- */
|
||||
|
||||
static _Atomic(waiter *) free_waiters;
|
||||
#define MASQUE 0x00fffffffffffff8
|
||||
#define PTR(x) ((uintptr_t)(x) & MASQUE)
|
||||
#define TAG(x) ROL((uintptr_t)(x) & ~MASQUE, 8)
|
||||
#define ABA(p, t) ((uintptr_t)(p) | (ROR((uintptr_t)(t), 8) & ~MASQUE))
|
||||
#define ROL(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
|
||||
#define ROR(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
|
||||
|
||||
static atomic_uintptr_t free_waiters;
|
||||
|
||||
static void free_waiters_push (waiter *w) {
|
||||
int backoff = 0;
|
||||
w->next_free = atomic_load_explicit (&free_waiters, memory_order_relaxed);
|
||||
while (!atomic_compare_exchange_weak_explicit (&free_waiters, &w->next_free, w,
|
||||
memory_order_acq_rel, memory_order_relaxed))
|
||||
backoff = pthread_delay_np (free_waiters, backoff);
|
||||
uintptr_t tip;
|
||||
ASSERT (!TAG(w));
|
||||
tip = atomic_load_explicit (&free_waiters, memory_order_relaxed);
|
||||
for (;;) {
|
||||
w->next_free = (waiter *) PTR (tip);
|
||||
if (atomic_compare_exchange_weak_explicit (&free_waiters,
|
||||
&tip,
|
||||
ABA (w, TAG (tip) + 1),
|
||||
memory_order_release,
|
||||
memory_order_relaxed))
|
||||
break;
|
||||
pthread_pause_np ();
|
||||
}
|
||||
}
|
||||
|
||||
static waiter *free_waiters_pop (void) {
|
||||
waiter *w;
|
||||
uintptr_t tip;
|
||||
tip = atomic_load_explicit (&free_waiters, memory_order_relaxed);
|
||||
while ((w = (waiter *) PTR (tip))) {
|
||||
if (atomic_compare_exchange_weak_explicit (&free_waiters,
|
||||
&tip,
|
||||
ABA (w->next_free, TAG (tip) + 1),
|
||||
memory_order_acquire,
|
||||
memory_order_relaxed))
|
||||
break;
|
||||
pthread_pause_np ();
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
static void free_waiters_populate (void) {
|
||||
|
@ -172,30 +204,12 @@ static void free_waiters_populate (void) {
|
|||
}
|
||||
w->nw.sem = &w->sem;
|
||||
dll_init (&w->nw.q);
|
||||
NSYNC_ATOMIC_UINT32_STORE_ (&w->nw.waiting, 0);
|
||||
w->nw.flags = NSYNC_WAITER_FLAG_MUCV;
|
||||
ATM_STORE (&w->remove_count, 0);
|
||||
dll_init (&w->same_condition);
|
||||
w->flags = 0;
|
||||
free_waiters_push (w);
|
||||
}
|
||||
}
|
||||
|
||||
static waiter *free_waiters_pop (void) {
|
||||
waiter *w;
|
||||
int backoff = 0;
|
||||
for (;;) {
|
||||
if ((w = atomic_load_explicit (&free_waiters, memory_order_relaxed))) {
|
||||
if (atomic_compare_exchange_weak_explicit (&free_waiters, &w, w->next_free,
|
||||
memory_order_acq_rel, memory_order_relaxed))
|
||||
return w;
|
||||
backoff = pthread_delay_np (free_waiters, backoff);
|
||||
} else {
|
||||
free_waiters_populate ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------- */
|
||||
|
||||
#define waiter_for_thread __get_tls()->tib_nsync
|
||||
|
@ -221,7 +235,8 @@ waiter *nsync_waiter_new_ (void) {
|
|||
tw = waiter_for_thread;
|
||||
w = tw;
|
||||
if (w == NULL || (w->flags & (WAITER_RESERVED|WAITER_IN_USE)) != WAITER_RESERVED) {
|
||||
w = free_waiters_pop ();
|
||||
while (!(w = free_waiters_pop ()))
|
||||
free_waiters_populate ();
|
||||
if (tw == NULL) {
|
||||
w->flags |= WAITER_RESERVED;
|
||||
waiter_for_thread = w;
|
||||
|
|
3
third_party/nsync/mem/nsync_cv.c
vendored
3
third_party/nsync/mem/nsync_cv.c
vendored
|
@ -233,7 +233,9 @@ static int nsync_cv_wait_with_deadline_impl_ (struct nsync_cv_wait_with_deadline
|
|||
/* Requeue on *pmu using existing waiter struct; current thread
|
||||
is the designated waker. */
|
||||
nsync_mu_lock_slow_ (c->cv_mu, c->w, MU_DESIG_WAKER, c->w->l_type);
|
||||
nsync_waiter_free_ (c->w);
|
||||
} else {
|
||||
nsync_waiter_free_ (c->w);
|
||||
/* Traditional case: We've woken from the cv, and need to reacquire *pmu. */
|
||||
if (c->is_reader_mu) {
|
||||
nsync_mu_rlock (c->cv_mu);
|
||||
|
@ -241,7 +243,6 @@ static int nsync_cv_wait_with_deadline_impl_ (struct nsync_cv_wait_with_deadline
|
|||
(*c->lock) (c->pmu);
|
||||
}
|
||||
}
|
||||
nsync_waiter_free_ (c->w);
|
||||
IGNORE_RACES_END ();
|
||||
return (outcome);
|
||||
}
|
||||
|
|
6
third_party/nsync/mu_semaphore_sem.c
vendored
6
third_party/nsync/mu_semaphore_sem.c
vendored
|
@ -52,11 +52,11 @@ static nsync_semaphore *sem_big_enough_for_sem = (nsync_semaphore *) (uintptr_t)
|
|||
(sizeof (struct sem) <= sizeof (*sem_big_enough_for_sem)));
|
||||
|
||||
static void sems_push (struct sem *f) {
|
||||
int backoff = 0;
|
||||
f->next = atomic_load_explicit (&g_sems, memory_order_relaxed);
|
||||
while (!atomic_compare_exchange_weak_explicit (&g_sems, &f->next, f,
|
||||
memory_order_acq_rel, memory_order_relaxed))
|
||||
backoff = pthread_delay_np (&g_sems, backoff);
|
||||
memory_order_acq_rel,
|
||||
memory_order_relaxed))
|
||||
pthread_pause_np ();
|
||||
}
|
||||
|
||||
static bool nsync_mu_semaphore_sem_create (struct sem *f) {
|
||||
|
|
|
@ -417,7 +417,7 @@ statements instead, so that Cosmopolitan Libc's system constants will
|
|||
work as expected. Our modifications to GNU GCC are published under the
|
||||
ISC license at <https://github.com/ahgamut/gcc/tree/portcosmo-14.1>. The
|
||||
binaries you see here were first published at
|
||||
<https://github.com/ahgamut/superconfigure/releases/tag/z0.0.52> which
|
||||
<https://github.com/ahgamut/superconfigure/releases/tag/z0.0.53> which
|
||||
is regularly updated.
|
||||
|
||||
## Legal
|
||||
|
|
|
@ -75,6 +75,15 @@ elif [ ! -d "$TMPDIR" ]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
CLANG=0
|
||||
CC_X86_64="$BIN/x86_64-linux-cosmo-gcc"
|
||||
CC_AARCH64="$BIN/aarch64-linux-cosmo-gcc"
|
||||
CXX_X86_64="$BIN/x86_64-linux-cosmo-g++"
|
||||
CXX_AARCH64="$BIN/aarch64-linux-cosmo-g++"
|
||||
FPORTCOSMO="-fportcosmo"
|
||||
TARGET_X86_64=
|
||||
TARGET_AARCH64=
|
||||
|
||||
X=
|
||||
OPT=
|
||||
ARGS=
|
||||
|
@ -93,6 +102,7 @@ FLAGS_AARCH64=
|
|||
INPUT_FILE_COUNT=0
|
||||
DEPENDENCY_OUTPUT=
|
||||
NEED_DEPENDENCY_OUTPUT=
|
||||
|
||||
for x; do
|
||||
if [ x"$x" != x"${x#* }" ]; then
|
||||
fatal_error "arguments containing spaces unsupported: $x"
|
||||
|
@ -185,6 +195,16 @@ EOF
|
|||
elif [ x"$x" = x"-moptlinux" ]; then
|
||||
MODE=optlinux
|
||||
continue
|
||||
elif [ x"$x" = x"-mclang" ]; then
|
||||
CLANG=1
|
||||
CC_X86_64="$BIN/cosmo-clang"
|
||||
CC_AARCH64="$BIN/cosmo-clang"
|
||||
CXX_X86_64="$BIN/cosmo-clang++"
|
||||
CXX_AARCH64="$BIN/cosmo-clang++"
|
||||
TARGET_X86_64="--target=x86_64"
|
||||
TARGET_AARCH64="--target=aarch64"
|
||||
FPORTCOSMO=
|
||||
continue
|
||||
elif [ x"$x" = x"-m64" ]; then
|
||||
continue
|
||||
elif [ x"$x" = x"-fomit-frame-pointer" ]; then
|
||||
|
@ -298,7 +318,7 @@ fi
|
|||
PLATFORM="-D__COSMOPOLITAN__ -D__COSMOCC__ -D__FATCOSMOCC__"
|
||||
PREDEF="-include libc/integral/normalize.inc"
|
||||
CPPFLAGS="-fno-pie -nostdinc -isystem $BIN/../include"
|
||||
CFLAGS="-fportcosmo -fno-dwarf2-cfi-asm -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-semantic-interposition"
|
||||
CFLAGS="$FPORTCOSMO -fno-dwarf2-cfi-asm -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-semantic-interposition"
|
||||
LDFLAGS="-static -nostdlib -no-pie -fuse-ld=bfd -Wl,-z,noexecstack -Wl,-z,norelro -Wl,--gc-sections"
|
||||
PRECIOUS="-fno-omit-frame-pointer"
|
||||
|
||||
|
@ -307,8 +327,10 @@ if [ x"$OPT" != x"-Os" ] && [ x"$MODE" != x"tiny" ] && [ x"$MODE" != x"optlinux"
|
|||
CFLAGS="$CFLAGS -fno-optimize-sibling-calls -mno-omit-leaf-frame-pointer"
|
||||
fi
|
||||
if [ x"$OPT" != x"-O3" ] && [ x"$MODE" != x"optlinux" ]; then
|
||||
if [ $CLANG -eq 0 ]; then
|
||||
CFLAGS="$CFLAGS -fno-schedule-insns2"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ x"$X" = x"c" ] || [ x"$X" = x"c-header" ]; then
|
||||
CPLUSPLUS=0
|
||||
|
@ -320,11 +342,9 @@ else
|
|||
CPLUSPLUS=0
|
||||
fi
|
||||
|
||||
CC_X86_64="$BIN/x86_64-linux-cosmo-gcc"
|
||||
CC_AARCH64="$BIN/aarch64-linux-cosmo-gcc"
|
||||
if [ $CPLUSPLUS -eq 1 ]; then
|
||||
CC_X86_64="$BIN/x86_64-linux-cosmo-g++"
|
||||
CC_AARCH64="$BIN/aarch64-linux-cosmo-g++"
|
||||
CC_X86_64=$CXX_X86_64
|
||||
CC_AARCH64=$CXX_AARCH64
|
||||
if [ $INTENT != cpp ]; then
|
||||
CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -fuse-cxa-atexit"
|
||||
fi
|
||||
|
@ -461,6 +481,7 @@ build_object() {
|
|||
(
|
||||
set -- \
|
||||
"$CC_X86_64" \
|
||||
$TARGET_X86_64 \
|
||||
-o"$OUTPUT_X86_64" \
|
||||
$PLATFORM \
|
||||
$PREDEF \
|
||||
|
@ -482,6 +503,7 @@ build_object() {
|
|||
(
|
||||
set -- \
|
||||
"$CC_AARCH64" \
|
||||
$TARGET_AARCH64 \
|
||||
-o"$OUTPUT_AARCH64" \
|
||||
$PLATFORM \
|
||||
$PREDEF \
|
||||
|
@ -588,6 +610,7 @@ TEMP_FILES="${TEMP_FILES} $out2"
|
|||
(
|
||||
set -- \
|
||||
"$CC_X86_64" \
|
||||
$TARGET_X86_64 \
|
||||
-o"$OUTPUT_X86_64"\
|
||||
$CRT_X86_64 \
|
||||
$LDFLAGS_X86_64 \
|
||||
|
@ -605,6 +628,7 @@ pid1=$!
|
|||
(
|
||||
set -- \
|
||||
"$CC_AARCH64" \
|
||||
$TARGET_AARCH64 \
|
||||
-o"$OUTPUT_AARCH64"\
|
||||
$CRT_AARCH64 \
|
||||
$LDFLAGS_AARCH64 \
|
||||
|
|
|
@ -182,12 +182,17 @@ fetch() {
|
|||
OLD=$PWD
|
||||
cd "$OUTDIR/"
|
||||
if [ ! -x bin/x86_64-linux-cosmo-gcc ]; then
|
||||
fetch https://github.com/ahgamut/superconfigure/releases/download/z0.0.52/aarch64-gcc.zip
|
||||
unzip aarch64-gcc.zip
|
||||
fetch https://github.com/ahgamut/superconfigure/releases/download/z0.0.53/aarch64-gcc.zip &
|
||||
fetch https://github.com/ahgamut/superconfigure/releases/download/z0.0.53/x86_64-gcc.zip &
|
||||
fetch https://github.com/ahgamut/superconfigure/releases/download/z0.0.53/llvm.zip &
|
||||
wait
|
||||
unzip aarch64-gcc.zip &
|
||||
unzip x86_64-gcc.zip &
|
||||
unzip llvm.zip bin/clang-18 &
|
||||
wait
|
||||
rm -f aarch64-gcc.zip
|
||||
fetch https://github.com/ahgamut/superconfigure/releases/download/z0.0.52/x86_64-gcc.zip
|
||||
unzip x86_64-gcc.zip
|
||||
rm -f x86_64-gcc.zip
|
||||
mv bin/clang-18 bin/cosmo-clang
|
||||
fi
|
||||
rm -f bin/*-cpp
|
||||
rm -f bin/*-gcc-*
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/cosmo.h"
|
||||
#include "libc/ctype.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/dos.h"
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
#define ALLOCATIONS 1000
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue