Merge branch 'master' into ctl-shared

This commit is contained in:
Steven Dee (Jōshin) 2024-08-26 20:58:57 -07:00
commit f7178894ee
No known key found for this signature in database
29 changed files with 945 additions and 608 deletions

View file

@ -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
View 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();
}

View file

@ -17,6 +17,7 @@
#include <string.h>
#include <wchar.h>
#include <wctype.h>
#include "libc/ctype.h"
/**
* @fileoverview Roman Transliteration, e.g.

View file

@ -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();
}

View file

@ -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`

View file

@ -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

View file

@ -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__)

View file

@ -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);
}

View file

@ -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;

View file

@ -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,

View file

@ -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,

View file

@ -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)))

View file

@ -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_ */

View file

@ -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_ */

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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");

View file

@ -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;

View file

@ -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);
}

View file

@ -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) {

View file

@ -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

View file

@ -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 \

View file

@ -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-*

View file

@ -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"

View file

@ -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