mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-12 12:50:28 +00:00
Merge branch 'jart:master' into issues-431-gh-actions
This commit is contained in:
commit
aa7a768838
9 changed files with 139 additions and 57 deletions
|
@ -1,50 +1,46 @@
|
||||||
SYNOPSIS
|
# Cosmopolitan Standard Library
|
||||||
|
|
||||||
Cosmopolitan Standard Library.
|
This directory defines static archives defining functions, like
|
||||||
|
`printf()`, `mmap()`, win32, etc. Please note that the Cosmopolitan
|
||||||
|
build configuration doesn't link any C/C++ library dependencies
|
||||||
|
by default, so you still have the flexibility to choose the one
|
||||||
|
provided by your system. If you'd prefer Cosmopolitan, just add
|
||||||
|
`$(LIBC)` and `$(CRT)` to your linker arguments.
|
||||||
|
|
||||||
OVERVIEW
|
Your library is compromised of many bite-sized static archives.
|
||||||
|
We use the checkdeps tool to guarantee that the contents of the
|
||||||
|
archives are organized in a logical way that's easy to use with
|
||||||
|
or without our makefile infrastructure, since there's no cyclic
|
||||||
|
dependencies.
|
||||||
|
|
||||||
This directory defines static archives defining functions, like
|
The Cosmopolitan Library exports only the most stable canonical
|
||||||
printf(), mmap(), win32, etc. Please note that the Cosmopolitan
|
system calls for all supported operating systems, regardless of
|
||||||
build configuration doesn't link any C/C++ library dependencies
|
which platform is used for compilation. We polyfill many of the
|
||||||
by default, so you still have the flexibility to choose the one
|
APIs, e.g. `read()`, `write()` so they work consistently everywhere
|
||||||
provided by your system. If you'd prefer Cosmopolitan, just add
|
while other apis, e.g. `CreateWindowEx()`, might only work on one
|
||||||
$(LIBC) and $(CRT) to your linker arguments.
|
platform, in which case they become no-op functions on others.
|
||||||
|
|
||||||
Your library is compromised of many bite-sized static archives.
|
Cosmopolitan polyfill wrappers will usually use the dollar sign
|
||||||
We use the checkdeps tool to guarantee that the contents of the
|
naming convention, so they may be bypassed when necessary. This
|
||||||
archives are organized in a logical way that's easy to use with
|
same convention is used when multiple implementations of string
|
||||||
or without our makefile infrastructure, since there's no cyclic
|
library and other performance-critical function are provided to
|
||||||
dependencies.
|
allow Cosmopolitan to go fast on both old and newer computers.
|
||||||
|
|
||||||
The Cosmopolitan Library exports only the most stable canonical
|
We take an approach to configuration that relies heavily on the
|
||||||
system calls for all supported operating systems, regardless of
|
compiler's dead code elimination pass (`libc/dce.h`). Most of the
|
||||||
which platform is used for compilation. We polyfill many of the
|
code is written so that, for example, folks not wanting support
|
||||||
APIs, e.g. read(), write() so they work consistently everywhere
|
for OpenBSD can flip a bit in `SUPPORT_VECTOR` and that code will
|
||||||
while other apis, e.g. CreateWindowEx(), might only work on one
|
be omitted from the build. The same is true for builds that are
|
||||||
platform, in which case they become no-op functions on others.
|
tuned using `-march=native` which effectively asks the library to
|
||||||
|
not include runtime support hooks for x86 processors older than
|
||||||
|
what you use.
|
||||||
|
|
||||||
Cosmopolitan polyfill wrappers will usually use the dollar sign
|
Please note that, unlike Cygwin or MinGW, Cosmopolitan does not
|
||||||
naming convention, so they may be bypassed when necessary. This
|
achieve broad support by bolting on a POSIX emulation layer. We
|
||||||
same convention is used when multiple implementations of string
|
do nothing more than (in most cases) stateless API translations
|
||||||
library and other performance-critical function are provided to
|
that get you 90% of the way there in a fast lightweight manner.
|
||||||
allow Cosmopolitan to go fast on both old and newer computers.
|
We therefore can't address some of the subtle differences, such
|
||||||
|
as the nuances of absolute paths on Windows. Our approach could
|
||||||
We take an approach to configuration that relies heavily on the
|
be compared to something more along the lines of, "the Russians
|
||||||
compiler's dead code elimination pass (libc/dce.h). Most of the
|
just used a pencil to write in space", versus spending millions
|
||||||
code is written so that, for example, folks not wanting support
|
researching a pen like NASA.
|
||||||
for OpenBSD can flip a bit in SUPPORT_VECTOR and that code will
|
|
||||||
be omitted from the build. The same is true for builds that are
|
|
||||||
tuned using -march=native which effectively asks the library to
|
|
||||||
not include runtime support hooks for x86 processors older than
|
|
||||||
what you use.
|
|
||||||
|
|
||||||
Please note that, unlike Cygwin or MinGW, Cosmopolitan does not
|
|
||||||
achieve broad support by bolting on a POSIX emulation layer. We
|
|
||||||
do nothing more than (in most cases) stateless API translations
|
|
||||||
that get you 90% of the way there in a fast lightweight manner.
|
|
||||||
We therefore can't address some of the subtle differences, such
|
|
||||||
as the nuances of absolute paths on Windows. Our approach could
|
|
||||||
be compared to something more along the lines of, "the Russians
|
|
||||||
just used a pencil to write in space", versus spending millions
|
|
||||||
researching a pen like NASA.
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ int pthread_rwlock_unlock(pthread_rwlock_t *);
|
||||||
#define pthread_mutex_unlock(mutex) \
|
#define pthread_mutex_unlock(mutex) \
|
||||||
((mutex)->attr == PTHREAD_MUTEX_NORMAL \
|
((mutex)->attr == PTHREAD_MUTEX_NORMAL \
|
||||||
? (atomic_store_explicit(&(mutex)->lock, 0, memory_order_relaxed), \
|
? (atomic_store_explicit(&(mutex)->lock, 0, memory_order_relaxed), \
|
||||||
(IsLinux() && \
|
((IsLinux() || IsOpenbsd()) && \
|
||||||
atomic_load_explicit(&(mutex)->waits, memory_order_relaxed) && \
|
atomic_load_explicit(&(mutex)->waits, memory_order_relaxed) && \
|
||||||
_pthread_mutex_wake(mutex)), \
|
_pthread_mutex_wake(mutex)), \
|
||||||
0) \
|
0) \
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/bits/asmflag.h"
|
||||||
#include "libc/bits/atomic.h"
|
#include "libc/bits/atomic.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
@ -24,16 +25,41 @@
|
||||||
#include "libc/intrin/spinlock.h"
|
#include "libc/intrin/spinlock.h"
|
||||||
#include "libc/linux/futex.h"
|
#include "libc/linux/futex.h"
|
||||||
#include "libc/nexgen32e/threaded.h"
|
#include "libc/nexgen32e/threaded.h"
|
||||||
|
#include "libc/sysv/consts/futex.h"
|
||||||
|
#include "libc/sysv/consts/nr.h"
|
||||||
|
|
||||||
|
static inline int FutexWait(void *addr, int expect, struct timespec *timeout) {
|
||||||
|
int ax;
|
||||||
|
bool cf;
|
||||||
|
asm volatile(CFLAG_ASM("mov\t%6,%%r10\n\t"
|
||||||
|
"clc\n\t"
|
||||||
|
"syscall")
|
||||||
|
: CFLAG_CONSTRAINT(cf), "=a"(ax)
|
||||||
|
: "1"(__NR_futex), "D"(addr), "S"(FUTEX_WAIT), "d"(expect),
|
||||||
|
"g"(timeout)
|
||||||
|
: "rcx", "r10", "r11", "memory");
|
||||||
|
if (cf) ax = -ax;
|
||||||
|
return ax;
|
||||||
|
}
|
||||||
|
|
||||||
static int pthread_mutex_lock_spin(pthread_mutex_t *mutex, int tries) {
|
static int pthread_mutex_lock_spin(pthread_mutex_t *mutex, int tries) {
|
||||||
volatile int i;
|
volatile int i;
|
||||||
|
struct timespec ts;
|
||||||
if (tries < 7) {
|
if (tries < 7) {
|
||||||
for (i = 0; i != 1 << tries; i++) {
|
for (i = 0; i != 1 << tries; i++) {
|
||||||
}
|
}
|
||||||
tries++;
|
tries++;
|
||||||
} else if (IsLinux()) {
|
} else if (IsLinux() || IsOpenbsd()) {
|
||||||
atomic_fetch_add(&mutex->waits, 1);
|
atomic_fetch_add(&mutex->waits, 1);
|
||||||
LinuxFutexWait(&mutex->lock, 1, 0);
|
if (tries < 28) {
|
||||||
|
ts.tv_sec = 0;
|
||||||
|
ts.tv_nsec = 4 << tries;
|
||||||
|
tries++;
|
||||||
|
} else {
|
||||||
|
ts.tv_sec = 1;
|
||||||
|
ts.tv_nsec = 0;
|
||||||
|
}
|
||||||
|
FutexWait(&mutex->lock, 1, &ts);
|
||||||
atomic_fetch_sub(&mutex->waits, 1);
|
atomic_fetch_sub(&mutex->waits, 1);
|
||||||
} else {
|
} else {
|
||||||
sched_yield();
|
sched_yield();
|
||||||
|
|
|
@ -40,7 +40,7 @@ int(pthread_mutex_unlock)(pthread_mutex_t *mutex) {
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case PTHREAD_MUTEX_NORMAL:
|
case PTHREAD_MUTEX_NORMAL:
|
||||||
atomic_store_explicit(&mutex->lock, 0, memory_order_relaxed);
|
atomic_store_explicit(&mutex->lock, 0, memory_order_relaxed);
|
||||||
if (IsLinux() &&
|
if ((IsLinux() || IsOpenbsd()) &&
|
||||||
atomic_load_explicit(&mutex->waits, memory_order_relaxed)) {
|
atomic_load_explicit(&mutex->waits, memory_order_relaxed)) {
|
||||||
_pthread_mutex_wake(mutex);
|
_pthread_mutex_wake(mutex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,23 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/bits/atomic.h"
|
#include "libc/bits/asmflag.h"
|
||||||
#include "libc/dce.h"
|
|
||||||
#include "libc/intrin/pthread.h"
|
#include "libc/intrin/pthread.h"
|
||||||
#include "libc/linux/futex.h"
|
#include "libc/sysv/consts/futex.h"
|
||||||
|
#include "libc/sysv/consts/nr.h"
|
||||||
|
|
||||||
|
static inline int FutexWake(void *addr, int count) {
|
||||||
|
int ax;
|
||||||
|
bool cf;
|
||||||
|
asm volatile(CFLAG_ASM("clc\n\t"
|
||||||
|
"syscall")
|
||||||
|
: CFLAG_CONSTRAINT(cf), "=a"(ax)
|
||||||
|
: "1"(__NR_futex), "D"(addr), "S"(FUTEX_WAKE), "d"(count)
|
||||||
|
: "rcx", "r11", "memory");
|
||||||
|
if (cf) ax = -ax;
|
||||||
|
return ax;
|
||||||
|
}
|
||||||
|
|
||||||
int _pthread_mutex_wake(pthread_mutex_t *mutex) {
|
int _pthread_mutex_wake(pthread_mutex_t *mutex) {
|
||||||
return LinuxFutexWake(&mutex->lock, 1);
|
return FutexWake(&mutex->lock, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/strace.internal.h"
|
#include "libc/calls/strace.internal.h"
|
||||||
|
#include "libc/calls/struct/rlimit.h"
|
||||||
#include "libc/calls/struct/sigset.h"
|
#include "libc/calls/struct/sigset.h"
|
||||||
#include "libc/calls/struct/termios.h"
|
#include "libc/calls/struct/termios.h"
|
||||||
#include "libc/calls/struct/utsname.h"
|
#include "libc/calls/struct/utsname.h"
|
||||||
|
@ -49,6 +50,7 @@
|
||||||
#include "libc/sysv/consts/auxv.h"
|
#include "libc/sysv/consts/auxv.h"
|
||||||
#include "libc/sysv/consts/f.h"
|
#include "libc/sysv/consts/f.h"
|
||||||
#include "libc/sysv/consts/poll.h"
|
#include "libc/sysv/consts/poll.h"
|
||||||
|
#include "libc/sysv/consts/rlim.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
#include "libc/sysv/consts/termios.h"
|
#include "libc/sysv/consts/termios.h"
|
||||||
#include "tool/decode/lib/idname.h"
|
#include "tool/decode/lib/idname.h"
|
||||||
|
@ -140,6 +142,7 @@ textstartup void __printargs(const char *prologue) {
|
||||||
unsigned i, n;
|
unsigned i, n;
|
||||||
int e, x, flags;
|
int e, x, flags;
|
||||||
uintptr_t *auxp;
|
uintptr_t *auxp;
|
||||||
|
struct rlimit rlim;
|
||||||
struct utsname uts;
|
struct utsname uts;
|
||||||
struct termios termios;
|
struct termios termios;
|
||||||
struct AuxiliaryValue *auxinfo;
|
struct AuxiliaryValue *auxinfo;
|
||||||
|
@ -276,6 +279,17 @@ textstartup void __printargs(const char *prologue) {
|
||||||
PRINT(" error: sigprocmask() failed %m");
|
PRINT(" error: sigprocmask() failed %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRINT("");
|
||||||
|
PRINT("RESOURCE LIMITS");
|
||||||
|
for (i = 0; i < RLIM_NLIMITS; ++i) {
|
||||||
|
if (!getrlimit(i, &rlim)) {
|
||||||
|
if (rlim.rlim_cur == RLIM_INFINITY) rlim.rlim_cur = -1;
|
||||||
|
if (rlim.rlim_max == RLIM_INFINITY) rlim.rlim_max = -1;
|
||||||
|
PRINT(" ☼ %-20s %,16ld %,16ld", DescribeRlimitName(i), rlim.rlim_cur,
|
||||||
|
rlim.rlim_max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PRINT("");
|
PRINT("");
|
||||||
PRINT("ARGUMENTS (%p)", __argv);
|
PRINT("ARGUMENTS (%p)", __argv);
|
||||||
if (*__argv) {
|
if (*__argv) {
|
||||||
|
|
|
@ -103,8 +103,9 @@ static void EmptySignalMask(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FixIrregularFds(void) {
|
static void FixIrregularFds(void) {
|
||||||
int i, fd;
|
int i, fd, maxfds;
|
||||||
struct pollfd pfds[64];
|
struct rlimit rlim;
|
||||||
|
struct pollfd *pfds;
|
||||||
for (i = 0; i < 3; ++i) {
|
for (i = 0; i < 3; ++i) {
|
||||||
if (fcntl(i, F_GETFL) == -1) {
|
if (fcntl(i, F_GETFL) == -1) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
@ -115,7 +116,16 @@ static void FixIrregularFds(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < ARRAYLEN(pfds); ++i) {
|
if (IsWindows()) {
|
||||||
|
maxfds = 64;
|
||||||
|
} else {
|
||||||
|
maxfds = 256;
|
||||||
|
if (!getrlimit(RLIMIT_NOFILE, &rlim)) {
|
||||||
|
maxfds = MIN(maxfds, (uint64_t)rlim.rlim_cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pfds = malloc(maxfds * sizeof(struct pollfd));
|
||||||
|
for (i = 0; i < maxfds; ++i) {
|
||||||
pfds[i].fd = i + 3;
|
pfds[i].fd = i + 3;
|
||||||
pfds[i].events = POLLIN;
|
pfds[i].events = POLLIN;
|
||||||
}
|
}
|
||||||
|
@ -123,12 +133,13 @@ static void FixIrregularFds(void) {
|
||||||
// TODO(jart): Fix Blinkenlights poll() / close()
|
// TODO(jart): Fix Blinkenlights poll() / close()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (poll(pfds, ARRAYLEN(pfds), 0) != -1) {
|
if (poll(pfds, maxfds, 0) != -1) {
|
||||||
for (i = 0; i < ARRAYLEN(pfds); ++i) {
|
for (i = 0; i < maxfds; ++i) {
|
||||||
if (pfds[i].revents & POLLNVAL) continue;
|
if (pfds[i].revents & POLLNVAL) continue;
|
||||||
CHECK_EQ(0, close(pfds[i].fd));
|
CHECK_EQ(0, close(pfds[i].fd));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(pfds);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetLimit(int resource, uint64_t soft, uint64_t hard) {
|
static void SetLimit(int resource, uint64_t soft, uint64_t hard) {
|
||||||
|
|
10
third_party/chibicc/as.c
vendored
10
third_party/chibicc/as.c
vendored
|
@ -2328,6 +2328,14 @@ static dontinline void OpBsu(struct As *a, struct Slice opname, int op) {
|
||||||
OpBsuImpl(a, opname, op);
|
OpBsuImpl(a, opname, op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dontinline void OpXadd(struct As *a) {
|
||||||
|
int reg, modrm, disp;
|
||||||
|
reg = GetRegisterReg(a);
|
||||||
|
ConsumeComma(a);
|
||||||
|
modrm = ParseModrm(a, &disp);
|
||||||
|
EmitRexOpModrm(a, 0x0FC0, reg, modrm, disp, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static dontinline int OpF6Impl(struct As *a, struct Slice s, int reg) {
|
static dontinline int OpF6Impl(struct As *a, struct Slice s, int reg) {
|
||||||
int modrm, imm, disp;
|
int modrm, imm, disp;
|
||||||
modrm = ParseModrm(a, &disp);
|
modrm = ParseModrm(a, &disp);
|
||||||
|
@ -3109,6 +3117,7 @@ static void OnUcomiss(struct As *a, struct Slice s) { OpSse(a, 0x0F2E); }
|
||||||
static void OnUd2(struct As *a, struct Slice s) { EmitVarword(a, 0x0F0B); }
|
static void OnUd2(struct As *a, struct Slice s) { EmitVarword(a, 0x0F0B); }
|
||||||
static void OnUnpckhpd(struct As *a, struct Slice s) { OpSse(a, 0x660F15); }
|
static void OnUnpckhpd(struct As *a, struct Slice s) { OpSse(a, 0x660F15); }
|
||||||
static void OnUnpcklpd(struct As *a, struct Slice s) { OpSse(a, 0x660F14); }
|
static void OnUnpcklpd(struct As *a, struct Slice s) { OpSse(a, 0x660F14); }
|
||||||
|
static void OnXadd(struct As *a, struct Slice s) { OpXadd(a); }
|
||||||
static void OnXor(struct As *a, struct Slice s) { OpAlu(a, s, 6); }
|
static void OnXor(struct As *a, struct Slice s) { OpAlu(a, s, 6); }
|
||||||
static void OnXorpd(struct As *a, struct Slice s) { OpSse(a, 0x660F57); }
|
static void OnXorpd(struct As *a, struct Slice s) { OpSse(a, 0x660F57); }
|
||||||
static void OnXorps(struct As *a, struct Slice s) { OpSse(a, 0x0F57); }
|
static void OnXorps(struct As *a, struct Slice s) { OpSse(a, 0x0F57); }
|
||||||
|
@ -3662,6 +3671,7 @@ static const struct Directive8 {
|
||||||
{"unpckhpd", OnUnpckhpd}, //
|
{"unpckhpd", OnUnpckhpd}, //
|
||||||
{"unpcklpd", OnUnpcklpd}, //
|
{"unpcklpd", OnUnpcklpd}, //
|
||||||
{"wait", OnFwait}, //
|
{"wait", OnFwait}, //
|
||||||
|
{"xadd", OnXadd}, //
|
||||||
{"xchg", OnXchg}, //
|
{"xchg", OnXchg}, //
|
||||||
{"xor", OnXor}, //
|
{"xor", OnXor}, //
|
||||||
{"xorb", OnXor}, //
|
{"xorb", OnXor}, //
|
||||||
|
|
13
third_party/chibicc/test/atomic_test.c
vendored
13
third_party/chibicc/test/atomic_test.c
vendored
|
@ -37,5 +37,18 @@ main() {
|
||||||
ASSERT(4, x);
|
ASSERT(4, x);
|
||||||
ASSERT(4, lock);
|
ASSERT(4, lock);
|
||||||
|
|
||||||
|
// CAS success #3
|
||||||
|
x = 4;
|
||||||
|
ASSERT(1, __atomic_compare_exchange_n(&lock, &x, 31337, 0, __ATOMIC_SEQ_CST,
|
||||||
|
__ATOMIC_SEQ_CST));
|
||||||
|
ASSERT(4, x);
|
||||||
|
ASSERT(31337, lock);
|
||||||
|
|
||||||
|
// xadd
|
||||||
|
ASSERT(31337, __atomic_fetch_add(&lock, 31337, __ATOMIC_SEQ_CST));
|
||||||
|
ASSERT(62674, lock);
|
||||||
|
ASSERT(62674, __atomic_fetch_sub(&lock, 31337, __ATOMIC_SEQ_CST));
|
||||||
|
ASSERT(31337, lock);
|
||||||
|
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue