Make improvements

- Improve compatibility with Blink virtual machine
- Add non-POSIX APIs for joining threads and signal masks
- Never ever use anything except 32-bit integers for atomics
- Add some `#undef` statements to workaround `ctags` problems
This commit is contained in:
Justine Tunney 2022-11-10 21:52:47 -08:00
parent b46ac13504
commit f2af97711b
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
114 changed files with 902 additions and 363 deletions

View file

@ -715,7 +715,7 @@ ASSERT(IS2POW(ape_stack_memsz),
"ape_stack_memsz must be a two power");
ASSERT(ape_stack_vaddr % ape_stack_memsz == 0,
"ape_stack_vaddr must have ape_stack_memsz alignment; try using STATIC_STACK_ADDR(0x700000040000 - ape_stack_memsz);");
"ape_stack_vaddr must have ape_stack_memsz alignment; try using STATIC_STACK_ADDR(0x700000040000 & -ape_stack_memsz);");
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");

View file

@ -240,6 +240,8 @@ static bool ShouldUseSpinNanosleep(int clock, int flags,
errno_t clock_nanosleep(int clock, int flags, const struct timespec *req,
struct timespec *rem) {
int rc;
LOCKTRACE("clock_nanosleep(%s, %s, %s) → ...", DescribeClockName(clock),
DescribeSleepFlags(flags), DescribeTimespec(0, req));
if (IsMetal()) {
rc = ENOSYS;
} else if (!req || (IsAsan() && (!__asan_is_valid_timespec(req) ||
@ -259,7 +261,7 @@ errno_t clock_nanosleep(int clock, int flags, const struct timespec *req,
if (__tls_enabled && !(__get_tls()->tib_flags & TIB_FLAG_TIME_CRITICAL)) {
STRACE("clock_nanosleep(%s, %s, %s, [%s]) → %s", DescribeClockName(clock),
DescribeSleepFlags(flags), DescribeTimespec(0, req),
DescribeTimespec(rc, rem), DescribeErrnoResult(rc));
DescribeTimespec(rc, rem), DescribeErrno(rc));
}
#endif
return rc;

View file

@ -26,8 +26,6 @@
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
int sys_fexecve(int, char *const[], char *const[]);
/**
* Executes binary executable at file descriptor.
*

View file

@ -24,6 +24,7 @@
#include "libc/errno.h"
#include "libc/intrin/promises.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nexgen32e/vendor.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
@ -238,8 +239,10 @@
int pledge(const char *promises, const char *execpromises) {
int e, rc;
unsigned long ipromises, iexecpromises;
if (!ParsePromises(promises, &ipromises) &&
!ParsePromises(execpromises, &iexecpromises)) {
if (IsGenuineCosmo()) {
rc = 0; // blink doesn't support seccomp
} else if (!ParsePromises(promises, &ipromises) &&
!ParsePromises(execpromises, &iexecpromises)) {
if (IsLinux()) {
// copy exec and execnative from promises to execpromises
iexecpromises = ~(~iexecpromises | (~ipromises & (1ul << PROMISE_EXEC)));

View file

@ -37,6 +37,7 @@ i32 sys_dup(i32) _Hide;
i32 sys_dup2(i32, i32) _Hide;
i32 sys_dup3(i32, i32, i32) _Hide;
i32 sys_execve(const char *, char *const[], char *const[]) _Hide;
i32 sys_execveat(i32, const char *, char *const[], char *const[], i32) _Hide;
i32 sys_faccessat(i32, const char *, i32, u32) _Hide;
i32 sys_faccessat2(i32, const char *, i32, u32) _Hide;
i32 sys_fadvise(i32, i64, i64, i32) _Hide;
@ -47,6 +48,7 @@ i32 sys_fchown(i64, u32, u32) _Hide;
i32 sys_fchownat(i32, const char *, u32, u32, u32) _Hide;
i32 sys_fcntl(i32, i32, u64, i32 (*)(i32, i32, ...)) _Hide;
i32 sys_fdatasync(i32) _Hide;
i32 sys_fexecve(i32, char *const[], char *const[]) _Hide;
i32 sys_flock(i32, i32) _Hide;
i32 sys_fork(void) _Hide;
i32 sys_fsync(i32) _Hide;

View file

@ -31,6 +31,7 @@
#include "libc/fmt/conv.h"
#include "libc/intrin/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/vendor.internal.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
@ -353,7 +354,9 @@ int sys_unveil_linux(const char *path, const char *permissions) {
int unveil(const char *path, const char *permissions) {
int e, rc;
e = errno;
if (IsLinux()) {
if (IsGenuineCosmo()) {
rc = 0; // blink doesn't support landlock
} else if (IsLinux()) {
rc = sys_unveil_linux(path, permissions);
} else {
rc = sys_unveil(path, permissions);

View file

@ -159,7 +159,7 @@ static struct AsanMorgue {
static bool __asan_once(void) {
bool want = false;
static _Atomic(bool) once;
static atomic_int once;
return atomic_compare_exchange_strong_explicit(
&once, &want, true, memory_order_relaxed, memory_order_relaxed);
}

View file

@ -20,7 +20,11 @@
#include "libc/fmt/itoa.h"
#include "libc/intrin/describeflags.internal.h"
const char *(DescribeArchPrctlCode)(char buf[12], int x) {
#ifdef DescribeArchPrctlCode
#undef DescribeArchPrctlCode
#endif
const char *DescribeArchPrctlCode(char buf[12], int x) {
if (x == ARCH_SET_FS) return "ARCH_SET_FS";
if (x == ARCH_GET_FS) return "ARCH_GET_FS";
if (x == ARCH_SET_GS) return "ARCH_SET_GS";

View file

@ -20,11 +20,15 @@
#include "libc/intrin/kprintf.h"
#include "libc/nexgen32e/stackframe.h"
#ifdef DescribeBacktrace
#undef DescribeBacktrace
#endif
#define N 64
#define append(...) o += ksnprintf(buf + o, N - o, __VA_ARGS__)
const char *(DescribeBacktrace)(char buf[N], struct StackFrame *fr) {
const char *DescribeBacktrace(char buf[N], struct StackFrame *fr) {
int o = 0;
bool gotsome = false;
while (fr) {

View file

@ -22,6 +22,10 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/cap.h"
#ifdef DescribeCapability
#undef DescribeCapability
#endif
static const struct thatispacked {
unsigned char x;
const char *s;
@ -69,7 +73,7 @@ static const struct thatispacked {
{CAP_CHECKPOINT_RESTORE, "CHECKPOINT_RESTORE"}, //
};
const char *(DescribeCapability)(char buf[32], int x) {
const char *DescribeCapability(char buf[32], int x) {
int i;
for (i = 0; i < ARRAYLEN(kCapabilityName); ++i) {
if (kCapabilityName[i].x == x) {

View file

@ -19,9 +19,13 @@
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/describeflags.internal.h"
#ifdef DescribeClockName
#undef DescribeClockName
#endif
/**
* Describes clock_gettime() clock argument.
*/
const char *(DescribeClockName)(char buf[32], int x) {
const char *DescribeClockName(char buf[32], int x) {
return DescribeMagnum(buf, kClockNames, "CLOCK_", x);
}

View file

@ -20,7 +20,11 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/sysv/consts/at.h"
const char *(DescribeDirfd)(char buf[12], int dirfd) {
#ifdef DescribeDirfd
#undef DescribeDirfd
#endif
const char *DescribeDirfd(char buf[12], int dirfd) {
if (dirfd == AT_FDCWD) return "AT_FDCWD";
FormatInt32(buf, dirfd);
return buf;

View file

@ -21,6 +21,10 @@
#include "libc/nt/enum/processaccess.h"
#include "libc/sysv/consts/dn.h"
#ifdef DescribeDnotifyFlags
#undef DescribeDnotifyFlags
#endif
static const struct DescribeFlags kDnotifyFlags[] = {
{DN_ACCESS, "ACCESS"}, //
{DN_MODIFY, "MODIFY"}, //
@ -31,7 +35,7 @@ static const struct DescribeFlags kDnotifyFlags[] = {
{DN_MULTISHOT, "MULTISHOT"}, //
};
const char *(DescribeDnotifyFlags)(char buf[80], int x) {
const char *DescribeDnotifyFlags(char buf[80], int x) {
return DescribeFlags(buf, 80, kDnotifyFlags, ARRAYLEN(kDnotifyFlags), "DN_",
x);
}

View file

@ -20,12 +20,22 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/str/str.h"
const char *(DescribeErrnoResult)(char buf[12], int ax) {
#ifdef DescribeErrno
#undef DescribeErrno
#endif
const char *DescribeErrno(char buf[20], int ax) {
char *p = buf;
const char *s;
if (ax > -4095u && (s = _strerrno(-ax))) {
if (ax < 0) {
*p++ = '-';
ax = -ax;
}
if ((s = _strerrno(ax))) {
stpcpy(p, s);
return s;
} else {
FormatInt32(buf, ax);
FormatInt32(p, ax);
return buf;
}
}

View file

@ -21,7 +21,11 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/str/str.h"
const char *(DescribeFcntlCmd)(char buf[20], int x) {
#ifdef DescribeFcntlCmd
#undef DescribeFcntlCmd
#endif
const char *DescribeFcntlCmd(char buf[20], int x) {
const char *s;
if (x >= 0 && (s = GetMagnumStr(kFcntlCmds, x))) {
buf[0] = 'F';

View file

@ -17,8 +17,7 @@ const char *DescribeCapability(char[32], int);
const char *DescribeClockName(char[32], int);
const char *DescribeDirfd(char[12], int);
const char *DescribeDnotifyFlags(char[80], int);
const char *DescribeErrno(char[12], int);
const char *DescribeErrnoResult(char[12], int);
const char *DescribeErrno(char[20], int);
const char *DescribeFcntlCmd(char[20], int);
const char *DescribeFlockType(char[12], int);
const char *DescribeFrame(char[32], int);
@ -71,8 +70,7 @@ const char *DescribeWhichPrio(char[12], int);
#define DescribeClockName(x) DescribeClockName(alloca(32), x)
#define DescribeDirfd(x) DescribeDirfd(alloca(12), x)
#define DescribeDnotifyFlags(x) DescribeDnotifyFlags(alloca(80), x)
#define DescribeErrno(x) DescribeErrno(alloca(12), x)
#define DescribeErrnoResult(x) DescribeErrnoResult(alloca(12), x)
#define DescribeErrno(x) DescribeErrno(alloca(20), x)
#define DescribeFcntlCmd(x) DescribeFcntlCmd(alloca(20), x)
#define DescribeFlockType(x) DescribeFlockType(alloca(12), x)
#define DescribeFrame(x) DescribeFrame(alloca(32), x)

View file

@ -24,11 +24,15 @@
#include "libc/intrin/kprintf.h"
#include "libc/sysv/consts/f.h"
#ifdef DescribeFlock
#undef DescribeFlock
#endif
#define N 300
#define append(...) o += ksnprintf(buf + o, N - o, __VA_ARGS__)
const char *(DescribeFlock)(char buf[N], int cmd, const struct flock *l) {
const char *DescribeFlock(char buf[N], int cmd, const struct flock *l) {
int o = 0;
if (!l) return "NULL";

View file

@ -19,7 +19,11 @@
#include "libc/fmt/itoa.h"
#include "libc/sysv/consts/f.h"
const char *(DescribeFlockType)(char buf[12], int x) {
#ifdef DescribeFlockType
#undef DescribeFlockType
#endif
const char *DescribeFlockType(char buf[12], int x) {
if (x == F_RDLCK) return "F_RDLCK";
if (x == F_WRLCK) return "F_WRLCK";
if (x == F_UNLCK) return "F_UNLCK";

View file

@ -26,6 +26,10 @@
#include "libc/runtime/runtime.h"
#include "libc/runtime/winargs.internal.h"
#ifdef DescribeFrame
#undef DescribeFrame
#endif
#define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16)
#define UNSHADOW(x) ((int64_t)(MAX(0, (x)-0x7fff8000)) << 3)
#define FRAME(x) ((int)((x) >> 16))
@ -74,7 +78,7 @@ static const char *GetFrameName(int x) {
}
}
const char *(DescribeFrame)(char buf[32], int x) {
const char *DescribeFrame(char buf[32], int x) {
char *p;
if (IsShadowFrame(x)) {
ksnprintf(buf, 32, "%s %s %.8x", GetFrameName(x),

View file

@ -21,7 +21,11 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/futex.h"
const char *(DescribeFutexOp)(char buf[64], int x) {
#ifdef DescribeFutexOp
#undef DescribeFutexOp
#endif
const char *DescribeFutexOp(char buf[64], int x) {
bool priv = false;
if (x & FUTEX_PRIVATE_FLAG) {

View file

@ -24,10 +24,14 @@
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#ifdef DescribeGidList
#undef DescribeGidList
#endif
#define N 128
const char *(DescribeGidList)(char buf[N], int rc, int size,
const uint32_t list[]) {
const char *DescribeGidList(char buf[N], int rc, int size,
const uint32_t list[]) {
if ((rc == -1) || (size < 0)) return "n/a";
if (!size) return "{}";
if (!list) return "NULL";

View file

@ -20,7 +20,11 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/sysv/consts/sig.h"
const char *(DescribeHow)(char buf[12], int how) {
#ifdef DescribeHow
#undef DescribeHow
#endif
const char *DescribeHow(char buf[12], int how) {
if (how == SIG_BLOCK) return "SIG_BLOCK";
if (how == SIG_UNBLOCK) return "SIG_UNBLOCK";
if (how == SIG_SETMASK) return "SIG_SETMASK";

View file

@ -24,12 +24,16 @@
#include "libc/limits.h"
#include "libc/macros.internal.h"
#ifdef DescribeIovec
#undef DescribeIovec
#endif
#define N 300
#define append(...) o += ksnprintf(buf + o, N - o, __VA_ARGS__)
const char *(DescribeIovec)(char buf[N], ssize_t rc, const struct iovec *iov,
int iovlen) {
const char *DescribeIovec(char buf[N], ssize_t rc, const struct iovec *iov,
int iovlen) {
const char *d;
int i, j, o = 0;

View file

@ -22,7 +22,11 @@
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
const char *(DescribeMapFlags)(char buf[64], int x) {
#ifdef DescribeMapFlags
#undef DescribeMapFlags
#endif
const char *DescribeMapFlags(char buf[64], int x) {
const struct DescribeFlags kMapFlags[] = {
{MAP_STACK, "STACK"}, // order matters
{MAP_PRIVATE, "PRIVATE"}, //

View file

@ -21,6 +21,10 @@
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#ifdef DescribeMapping
#undef DescribeMapping
#endif
static char DescribeMapType(int flags) {
switch (flags & MAP_TYPE) {
case MAP_FILE:
@ -44,7 +48,7 @@ char *DescribeProt(char p[4], int prot) {
return p;
}
const char *(DescribeMapping)(char p[8], int prot, int flags) {
const char *DescribeMapping(char p[8], int prot, int flags) {
/* asan runtime depends on this function */
DescribeProt(p, prot);
p[3] = DescribeMapType(flags);

View file

@ -20,6 +20,10 @@
#include "libc/macros.internal.h"
#include "libc/nt/enum/consolemodeflags.h"
#ifdef DescribeNtConsoleInFlags
#undef DescribeNtConsoleInFlags
#endif
static const struct DescribeFlags kConsoleModeInputFlags[] = {
{kNtEnableProcessedInput, "ProcessedInput"}, //
{kNtEnableLineInput, "LineInput"}, //
@ -33,7 +37,7 @@ static const struct DescribeFlags kConsoleModeInputFlags[] = {
{kNtEnableVirtualTerminalInput, "VirtualTerminalInput"}, //
};
const char *(DescribeNtConsoleInFlags)(char buf[256], uint32_t x) {
const char *DescribeNtConsoleInFlags(char buf[256], uint32_t x) {
return DescribeFlags(buf, 256, kConsoleModeInputFlags,
ARRAYLEN(kConsoleModeInputFlags), "kNtEnable", x);
}

View file

@ -20,6 +20,10 @@
#include "libc/macros.internal.h"
#include "libc/nt/enum/consolemodeflags.h"
#ifdef DescribeNtConsoleOutFlags
#undef DescribeNtConsoleOutFlags
#endif
static const struct DescribeFlags kConsoleModeOutputFlags[] = {
{kNtEnableProcessedOutput, "EnableProcessedOutput"}, //
{kNtEnableWrapAtEolOutput, "EnableWrapAtEolOutput"}, //
@ -28,7 +32,7 @@ static const struct DescribeFlags kConsoleModeOutputFlags[] = {
{kNtEnableLvbGridWorldwide, "EnableLvbGridWorldwide"}, //
};
const char *(DescribeNtConsoleOutFlags)(char buf[128], uint32_t x) {
const char *DescribeNtConsoleOutFlags(char buf[128], uint32_t x) {
return DescribeFlags(buf, 128, kConsoleModeOutputFlags,
ARRAYLEN(kConsoleModeOutputFlags), "kNt", x);
}

View file

@ -21,6 +21,10 @@
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/filesharemode.h"
#ifdef DescribeNtFileAccessFlags
#undef DescribeNtFileAccessFlags
#endif
static const struct DescribeFlags kFileAccessflags[] = {
{kNtFileAllAccess, "FileAllAccess"}, // order matters
{kNtFileGenericRead, "FileGenericRead"}, // order matters
@ -63,7 +67,7 @@ static const struct DescribeFlags kFileAccessflags[] = {
{kNtTokenAdjustSessionid, "TokenAdjustSessionid"}, //
};
const char *(DescribeNtFileAccessFlags)(char buf[512], uint32_t x) {
const char *DescribeNtFileAccessFlags(char buf[512], uint32_t x) {
return DescribeFlags(buf, 512, kFileAccessflags, ARRAYLEN(kFileAccessflags),
"kNt", x);
}

View file

@ -21,6 +21,10 @@
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/runtime/runtime.h"
#ifdef DescribeNtFileFlagAttr
#undef DescribeNtFileFlagAttr
#endif
static const struct DescribeFlags kFileFlags[] = {
{kNtFileAttributeReadonly, "AttributeReadonly"}, //
{kNtFileAttributeHidden, "AttributeHidden"}, //
@ -50,7 +54,7 @@ static const struct DescribeFlags kFileFlags[] = {
{kNtFileFlagFirstPipeInstance, "FlagFirstPipeInstance"}, //
};
const char *(DescribeNtFileFlagAttr)(char buf[256], uint32_t x) {
const char *DescribeNtFileFlagAttr(char buf[256], uint32_t x) {
if (x == -1u) return "-1u";
return DescribeFlags(buf, 256, kFileFlags, ARRAYLEN(kFileFlags), "kNtFile",
x);

View file

@ -20,6 +20,10 @@
#include "libc/macros.internal.h"
#include "libc/nt/enum/filemapflags.h"
#ifdef DescribeNtFileMapFlags
#undef DescribeNtFileMapFlags
#endif
static const struct DescribeFlags kFileMapFlags[] = {
{kNtFileMapCopy, "Copy"}, //
{kNtFileMapWrite, "Write"}, //
@ -30,7 +34,7 @@ static const struct DescribeFlags kFileMapFlags[] = {
{kNtFileMapLargePages, "LargePages"}, //
};
const char *(DescribeNtFileMapFlags)(char buf[64], uint32_t x) {
const char *DescribeNtFileMapFlags(char buf[64], uint32_t x) {
return DescribeFlags(buf, 64, kFileMapFlags, ARRAYLEN(kFileMapFlags),
"kNtFileMap", x);
}

View file

@ -20,13 +20,17 @@
#include "libc/macros.internal.h"
#include "libc/nt/enum/filesharemode.h"
#ifdef DescribeNtFileShareFlags
#undef DescribeNtFileShareFlags
#endif
static const struct DescribeFlags kFileShareflags[] = {
{kNtFileShareRead, "Read"}, //
{kNtFileShareWrite, "Write"}, //
{kNtFileShareDelete, "Delete"}, //
};
const char *(DescribeNtFileShareFlags)(char buf[64], uint32_t x) {
const char *DescribeNtFileShareFlags(char buf[64], uint32_t x) {
return DescribeFlags(buf, 64, kFileShareflags, ARRAYLEN(kFileShareflags),
"kNtFileShare", x);
}

View file

@ -21,6 +21,10 @@
#include "libc/nt/enum/filetype.h"
#include "libc/sysv/consts/mremap.h"
#ifdef DescribeNtFiletypeFlags
#undef DescribeNtFiletypeFlags
#endif
static const struct DescribeFlags kFiletypeFlags[] = {
{kNtFileTypeRemote, "Remote"}, //
{kNtFileTypePipe, "Pipe"}, // order matters
@ -28,7 +32,7 @@ static const struct DescribeFlags kFiletypeFlags[] = {
{kNtFileTypeChar, "Char"}, //
};
const char *(DescribeNtFiletypeFlags)(char buf[64], uint32_t x) {
const char *DescribeNtFiletypeFlags(char buf[64], uint32_t x) {
return DescribeFlags(buf, 64, kFiletypeFlags, ARRAYLEN(kFiletypeFlags),
"kNtFileType", x);
}

View file

@ -20,12 +20,16 @@
#include "libc/macros.internal.h"
#include "libc/nt/enum/filelockflags.h"
#ifdef DescribeNtLockFileFlags
#undef DescribeNtLockFileFlags
#endif
static const struct DescribeFlags kNtLockFileFlags[] = {
{kNtLockfileFailImmediately, "FailImmediately"}, //
{kNtLockfileExclusiveLock, "ExclusiveLock"}, //
};
const char *(DescribeNtLockFileFlags)(char buf[64], uint32_t x) {
const char *DescribeNtLockFileFlags(char buf[64], uint32_t x) {
return DescribeFlags(buf, 64, kNtLockFileFlags, ARRAYLEN(kNtLockFileFlags),
"kNtLockfile", x);
}

View file

@ -20,6 +20,10 @@
#include "libc/macros.internal.h"
#include "libc/nt/enum/movefileexflags.h"
#ifdef DescribeNtMovFileInpFlags
#undef DescribeNtMovFileInpFlags
#endif
static const struct DescribeFlags kMoveFileInputFlags[] = {
{kNtMovefileReplaceExisting, "ReplaceExisting"}, //
{kNtMovefileCopyAllowed, "CopyAllowed"}, //
@ -29,7 +33,7 @@ static const struct DescribeFlags kMoveFileInputFlags[] = {
{kNtMovefileFailIfNotTrackable, "FailIfNotTrackable"}, //
};
const char *(DescribeNtMovFileInpFlags)(char buf[256], uint32_t x) {
const char *DescribeNtMovFileInpFlags(char buf[256], uint32_t x) {
return DescribeFlags(buf, 256, kMoveFileInputFlags,
ARRAYLEN(kMoveFileInputFlags), "kNtMovefile", x);
}

View file

@ -20,6 +20,10 @@
#include "libc/macros.internal.h"
#include "libc/nt/enum/pageflags.h"
#ifdef DescribeNtPageFlags
#undef DescribeNtPageFlags
#endif
static const struct DescribeFlags kPageFlags[] = {
{kNtPageNoaccess, "PageNoaccess"}, //
{kNtPageReadonly, "PageReadonly"}, //
@ -41,6 +45,6 @@ static const struct DescribeFlags kPageFlags[] = {
{kNtSecWritecombine, "SecWritecombine"}, //
};
const char *(DescribeNtPageFlags)(char buf[64], uint32_t x) {
const char *DescribeNtPageFlags(char buf[64], uint32_t x) {
return DescribeFlags(buf, 64, kPageFlags, ARRAYLEN(kPageFlags), "kNt", x);
}

View file

@ -21,6 +21,10 @@
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/ipc.h"
#ifdef DescribeNtPipeModeFlags
#undef DescribeNtPipeModeFlags
#endif
static const struct DescribeFlags kPipeModeFlags[] = {
{kNtPipeNowait, "Nowait"}, // 0x0000000001
{kNtPipeReadmodeMessage, "ReadmodeMessage"}, // 0x0000000002
@ -32,7 +36,7 @@ static const struct DescribeFlags kPipeModeFlags[] = {
//{kNtPipeTypeByte, "TypeByte"}, // 0x00000000
};
const char *(DescribeNtPipeModeFlags)(char buf[64], uint32_t x) {
const char *DescribeNtPipeModeFlags(char buf[64], uint32_t x) {
return DescribeFlags(buf, 64, kPipeModeFlags, ARRAYLEN(kPipeModeFlags),
"kNtPipe", x);
}

View file

@ -21,13 +21,17 @@
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/ipc.h"
#ifdef DescribeNtPipeOpenFlags
#undef DescribeNtPipeOpenFlags
#endif
static const struct DescribeFlags kPipeOpenFlags[] = {
{kNtPipeAccessDuplex, "Duplex"}, // 0x00000003
{kNtPipeAccessOutbound, "Outbound"}, // 0x00000002
{kNtPipeAccessInbound, "Inbound"}, // 0x00000001
};
const char *(DescribeNtPipeOpenFlags)(char buf[64], uint32_t x) {
const char *DescribeNtPipeOpenFlags(char buf[64], uint32_t x) {
return DescribeFlags(buf, 64, kPipeOpenFlags, ARRAYLEN(kPipeOpenFlags),
"kNtPipeAccess", x);
}

View file

@ -20,6 +20,10 @@
#include "libc/macros.internal.h"
#include "libc/nt/enum/processaccess.h"
#ifdef DescribeNtProcAccessFlags
#undef DescribeNtProcAccessFlags
#endif
static const struct DescribeFlags kProcessAccessflags[] = {
{kNtProcessAllAccess, "AllAccess"}, //
{kNtProcessCreateProcess, "CreateProcess"}, //
@ -37,7 +41,7 @@ static const struct DescribeFlags kProcessAccessflags[] = {
{kNtProcessSynchronize, "Synchronize"}, //
};
const char *(DescribeNtProcAccessFlags)(char buf[256], uint32_t x) {
const char *DescribeNtProcAccessFlags(char buf[256], uint32_t x) {
return DescribeFlags(buf, 256, kProcessAccessflags,
ARRAYLEN(kProcessAccessflags), "kNtProcess", x);
}

View file

@ -21,6 +21,10 @@
#include "libc/nt/enum/startf.h"
#include "libc/sysv/consts/prot.h"
#ifdef DescribeNtStartFlags
#undef DescribeNtStartFlags
#endif
static const struct DescribeFlags kNtStartFlags[] = {
{kNtStartfUseshowwindow, "Useshowwindow"}, //
{kNtStartfUsesize, "Usesize"}, //
@ -38,7 +42,7 @@ static const struct DescribeFlags kNtStartFlags[] = {
{kNtStartfUntrustedsource, "Untrustedsource"}, //
};
const char *(DescribeNtStartFlags)(char buf[128], uint32_t x) {
const char *DescribeNtStartFlags(char buf[128], uint32_t x) {
return DescribeFlags(buf, 128, kNtStartFlags, ARRAYLEN(kNtStartFlags),
"kNtStartf", x);
}

View file

@ -20,12 +20,16 @@
#include "libc/macros.internal.h"
#include "libc/nt/enum/symboliclink.h"
#ifdef DescribeNtSymlinkFlags
#undef DescribeNtSymlinkFlags
#endif
static const struct DescribeFlags kSymbolicLinkflags[] = {
{kNtSymbolicLinkFlagDirectory, "Directory"}, //
{kNtSymbolicLinkFlagAllowUnprivilegedCreate, "AllowUnprivilegedCreate"}, //
};
const char *(DescribeNtSymlinkFlags)(char buf[64], uint32_t x) {
const char *DescribeNtSymlinkFlags(char buf[64], uint32_t x) {
return DescribeFlags(buf, 64, kSymbolicLinkflags,
ARRAYLEN(kSymbolicLinkflags), "kNtSymbolicLinkFlag", x);
}

View file

@ -23,12 +23,16 @@
#include "libc/macros.internal.h"
#include "libc/sysv/consts/sol.h"
#ifdef DescribeOpenFlags
#undef DescribeOpenFlags
#endif
#define N (PAGESIZE / 2 / sizeof(struct DescribeFlags))
/**
* Describes clock_gettime() clock argument.
*/
const char *(DescribeOpenFlags)(char buf[128], int x) {
const char *DescribeOpenFlags(char buf[128], int x) {
char *s;
int i, n;
struct DescribeFlags d[N];

View file

@ -22,6 +22,10 @@
#include "libc/nt/enum/filesharemode.h"
#include "libc/sysv/consts/personality.h"
#ifdef DescribePersonalityFlags
#undef DescribePersonalityFlags
#endif
static const struct DescribeFlags kPersonalityFlags[] = {
{ADDR_COMPAT_LAYOUT, "ADDR_COMPAT_LAYOUT"}, //
{READ_IMPLIES_EXEC, "READ_IMPLIES_EXEC"}, //
@ -36,7 +40,7 @@ static const struct DescribeFlags kPersonalityFlags[] = {
{UNAME26, "UNAME26"}, //
};
const char *(DescribePersonalityFlags)(char buf[128], int x) {
const char *DescribePersonalityFlags(char buf[128], int x) {
return DescribeFlags(buf, 128, kPersonalityFlags, ARRAYLEN(kPersonalityFlags),
"", x);
}

View file

@ -21,7 +21,11 @@
#include "libc/nt/enum/filemapflags.h"
#include "libc/sysv/consts/poll.h"
const char *(DescribePollFlags)(char buf[64], int x) {
#ifdef DescribePollFlags
#undef DescribePollFlags
#endif
const char *DescribePollFlags(char buf[64], int x) {
const struct DescribeFlags kPollFlags[] = {
{POLLIN, "IN"}, // order matters
{POLLOUT, "OUT"}, // order matters

View file

@ -20,12 +20,16 @@
#include "libc/macros.internal.h"
#include "libc/sysv/consts/prot.h"
#ifdef DescribeProtFlags
#undef DescribeProtFlags
#endif
static const struct DescribeFlags kProtFlags[] = {
{PROT_READ, "READ"}, //
{PROT_WRITE, "WRITE"}, //
{PROT_EXEC, "EXEC"}, //
};
const char *(DescribeProtFlags)(char buf[48], int x) {
const char *DescribeProtFlags(char buf[48], int x) {
return DescribeFlags(buf, 48, kProtFlags, ARRAYLEN(kProtFlags), "PROT_", x);
}

View file

@ -20,7 +20,11 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/sysv/consts/ptrace.h"
const char *(DescribePtrace)(char buf[12], int x) {
#ifdef DescribePtrace
#undef DescribePtrace
#endif
const char *DescribePtrace(char buf[12], int x) {
if (x == -1) return "-1";
if (x == PTRACE_TRACEME) return "PTRACE_TRACEME";
if (x == PTRACE_PEEKDATA) return "PTRACE_PEEKDATA";

View file

@ -20,7 +20,11 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/sysv/consts/ptrace.h"
const char *(DescribePtraceEvent)(char buf[32], int x) {
#ifdef DescribePtraceEvent
#undef DescribePtraceEvent
#endif
const char *DescribePtraceEvent(char buf[32], int x) {
if (x == PTRACE_EVENT_FORK) return "PTRACE_EVENT_FORK";
if (x == PTRACE_EVENT_VFORK) return "PTRACE_EVENT_VFORK";
if (x == PTRACE_EVENT_CLONE) return "PTRACE_EVENT_CLONE";

View file

@ -20,12 +20,16 @@
#include "libc/macros.internal.h"
#include "libc/sysv/consts/mremap.h"
#ifdef DescribeRemapFlags
#undef DescribeRemapFlags
#endif
static const struct DescribeFlags kRemapFlags[] = {
{MREMAP_MAYMOVE, "MAYMOVE"}, //
{MREMAP_FIXED, "FIXED"}, //
};
const char *(DescribeRemapFlags)(char buf[48], int x) {
const char *DescribeRemapFlags(char buf[48], int x) {
return DescribeFlags(buf, 48, kRemapFlags, ARRAYLEN(kRemapFlags), "MREMAP_",
x);
}

View file

@ -19,10 +19,14 @@
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/describeflags.internal.h"
#ifdef DescribeRlimitName
#undef DescribeRlimitName
#endif
/**
* Describes setrlimit() / getrlimit() argument.
*/
const char *(DescribeRlimitName)(char buf[20], int x) {
const char *DescribeRlimitName(char buf[20], int x) {
if (x == 127) return "n/a";
return DescribeMagnum(buf, kRlimitNames, "RLIMIT_", x);
}

View file

@ -21,10 +21,14 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/str/str.h"
#ifdef DescribeSchedParam
#undef DescribeSchedParam
#endif
/**
* Describes clock_gettime() clock argument.
*/
const char *(DescribeSchedParam)(char buf[32], const struct sched_param *x) {
const char *DescribeSchedParam(char buf[32], const struct sched_param *x) {
char *p;
if (!x) return "0";
p = buf;

View file

@ -23,10 +23,14 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/sched.h"
#ifdef DescribeSchedPolicy
#undef DescribeSchedPolicy
#endif
/**
* Describes clock_gettime() clock argument.
*/
const char *(DescribeSchedPolicy)(char buf[48], int x) {
const char *DescribeSchedPolicy(char buf[48], int x) {
char *p = buf;
if (x == -1) {
goto DoNumber;

View file

@ -22,6 +22,10 @@
#include "libc/sysv/consts/sicode.h"
#include "libc/sysv/consts/sig.h"
#ifdef DescribeSiCode
#undef DescribeSiCode
#endif
static bool IsSiUser(int si_code) {
if (!IsOpenbsd()) {
return si_code == SI_USER;
@ -38,7 +42,7 @@ static void NameIt(char p[17], const char *s, int si_code) {
/**
* Returns symbolic name for siginfo::si_code value.
*/
const char *(DescribeSiCode)(char b[17], int sig, int si_code) {
const char *DescribeSiCode(char b[17], int sig, int si_code) {
NameIt(b, "SI_", si_code);
if (si_code == SI_QUEUE) {
strcpy(b + 3, "QUEUE"); /* sent by sigqueue(2) */

View file

@ -27,6 +27,10 @@
#include "libc/mem/alloca.h"
#include "libc/sysv/consts/sa.h"
#ifdef DescribeSigaction
#undef DescribeSigaction
#endif
static const char *DescribeSigHandler(char buf[64], void f(int)) {
if (f == SIG_ERR) return "SIG_ERR";
if (f == SIG_DFL) return "SIG_DFL";
@ -54,8 +58,7 @@ static const char *DescribeSigFlags(char buf[64], int x) {
#define append(...) o += ksnprintf(buf + o, N - o, __VA_ARGS__)
const char *(DescribeSigaction)(char buf[N], int rc,
const struct sigaction *sa) {
const char *DescribeSigaction(char buf[N], int rc, const struct sigaction *sa) {
int o = 0;
char b64[64];

View file

@ -22,8 +22,12 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
const char *(DescribeSigaltstk)(char buf[128], int rc,
const struct sigaltstack *ss) {
#ifdef DescribeSigaltstk
#undef DescribeSigaltstk
#endif
const char *DescribeSigaltstk(char buf[128], int rc,
const struct sigaltstack *ss) {
if (rc == -1) return "n/a";
if (!ss) return "NULL";
if ((!IsAsan() && kisdangerous(ss)) ||

View file

@ -26,11 +26,15 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/sig.h"
#ifdef DescribeSiginfo
#undef DescribeSiginfo
#endif
#define N 300
#define append(...) i += ksnprintf(buf + i, N - i, __VA_ARGS__)
const char *(DescribeSiginfo)(char buf[N], int rc, const siginfo_t *si) {
const char *DescribeSiginfo(char buf[N], int rc, const siginfo_t *si) {
int i = 0;
if (rc == -1) return "n/a";

View file

@ -26,11 +26,15 @@
#include "libc/sysv/consts/limits.h"
#include "libc/sysv/consts/sig.h"
#ifdef DescribeSigset
#undef DescribeSigset
#endif
#define N 128
#define append(...) o += ksnprintf(buf + o, N - o, __VA_ARGS__)
const char *(DescribeSigset)(char buf[N], int rc, const sigset_t *ss) {
const char *DescribeSigset(char buf[N], int rc, const sigset_t *ss) {
bool gotsome;
const char *s;
int sig, o = 0;

View file

@ -21,10 +21,14 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/sysv/consts/timer.h"
#ifdef DescribeSleepFlags
#undef DescribeSleepFlags
#endif
/**
* Describes clock_nanosleep() flags argument.
*/
const char *(DescribeSleepFlags)(char buf[16], int x) {
const char *DescribeSleepFlags(char buf[16], int x) {
switch (x) {
case 0:
return "0";

View file

@ -20,7 +20,11 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/sysv/consts/af.h"
const char *(DescribeSocketFamily)(char buf[12], int family) {
#ifdef DescribeSocketFamily
#undef DescribeSocketFamily
#endif
const char *DescribeSocketFamily(char buf[12], int family) {
if (family == AF_UNIX) return "AF_UNIX";
if (family == AF_INET) return "AF_INET";
if (family == AF_INET6) return "AF_INET6";

View file

@ -20,7 +20,11 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/sysv/consts/ipproto.h"
const char *(DescribeSocketProtocol)(char buf[12], int family) {
#ifdef DescribeSocketProtocol
#undef DescribeSocketProtocol
#endif
const char *DescribeSocketProtocol(char buf[12], int family) {
if (family == IPPROTO_IP) return "IPPROTO_IP";
if (family == IPPROTO_ICMP) return "IPPROTO_ICMP";
if (family == IPPROTO_TCP) return "IPPROTO_TCP";

View file

@ -21,7 +21,11 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/sock.h"
const char *(DescribeSocketType)(char buf[64], int type) {
#ifdef DescribeSocketType
#undef DescribeSocketType
#endif
const char *DescribeSocketType(char buf[64], int type) {
int x;
char *p;
p = buf;

View file

@ -20,10 +20,14 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/sysv/consts/sol.h"
#ifdef DescribeSockLevel
#undef DescribeSockLevel
#endif
/**
* Describes setsockopt() level arguments.
*/
const char *(DescribeSockLevel)(char buf[12], int x) {
const char *DescribeSockLevel(char buf[12], int x) {
if (x == SOL_IP) return "SOL_IP";
if (x == SOL_TCP) return "SOL_TCP";
if (x == SOL_UDP) return "SOL_UDP";

View file

@ -22,10 +22,14 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/sol.h"
#ifdef DescribeSockOptname
#undef DescribeSockOptname
#endif
/**
* Describes setsockopt() optname arguments.
*/
const char *(DescribeSockOptname)(char buf[32], int l, int x) {
const char *DescribeSockOptname(char buf[32], int l, int x) {
int i;
char *s, *p;
const struct MagnumStr *ms;

View file

@ -22,11 +22,15 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/kprintf.h"
#ifdef DescribeStat
#undef DescribeStat
#endif
#define N 300
#define append(...) o += ksnprintf(buf + o, N - o, __VA_ARGS__)
const char *(DescribeStat)(char buf[N], int rc, const struct stat *st) {
const char *DescribeStat(char buf[N], int rc, const struct stat *st) {
int o = 0;
if (rc == -1) return "n/a";

View file

@ -24,11 +24,15 @@
#include "libc/intrin/kprintf.h"
#include "libc/sysv/consts/st.h"
#ifdef DescribeStatfs
#undef DescribeStatfs
#endif
#define N 300
#define append(...) i += ksnprintf(buf + i, N - i, __VA_ARGS__)
const char *(DescribeStatfs)(char buf[N], int rc, const struct statfs *f) {
const char *DescribeStatfs(char buf[N], int rc, const struct statfs *f) {
int i = 0;
char ibuf[21];
int64_t flags;

View file

@ -20,7 +20,11 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/str/str.h"
const char *(DescribeStdioState)(char buf[12], int x) {
#ifdef DescribeStdioState
#undef DescribeStdioState
#endif
const char *DescribeStdioState(char buf[12], int x) {
if (!x) return "";
if (x == -1) return "EOF";
if (x > 0) return _strerrno(x);

View file

@ -21,11 +21,15 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#ifdef DescribeStringList
#undef DescribeStringList
#endif
#define N 300
#define append(...) o += ksnprintf(buf + o, N - o, __VA_ARGS__)
const char *(DescribeStringList)(char buf[N], char *const list[]) {
const char *DescribeStringList(char buf[N], char *const list[]) {
int i, o = 0;
if (!list) return "NULL";

View file

@ -23,8 +23,11 @@
#include "libc/intrin/kprintf.h"
#include "libc/str/str.h"
const char *(DescribeTimespec)(char buf[45], int rc,
const struct timespec *ts) {
#ifdef DescribeTimespec
#undef DescribeTimespec
#endif
const char *DescribeTimespec(char buf[45], int rc, const struct timespec *ts) {
if (rc == -1) return "n/a";
if (!ts) return "NULL";
if ((!IsAsan() && kisdangerous(ts)) ||

View file

@ -20,7 +20,11 @@
#include "libc/fmt/itoa.h"
#include "libc/intrin/describeflags.internal.h"
const char *(DescribeWhence)(char buf[12], int whence) {
#ifdef DescribeWhence
#undef DescribeWhence
#endif
const char *DescribeWhence(char buf[12], int whence) {
if (whence == SEEK_SET) return "SEEK_SET";
if (whence == SEEK_CUR) return "SEEK_CUR";
if (whence == SEEK_END) return "SEEK_END";

View file

@ -20,7 +20,11 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/sysv/consts/prio.h"
const char *(DescribeWhichPrio)(char buf[12], int x) {
#ifdef DescribeWhichPrio
#undef DescribeWhichPrio
#endif
const char *DescribeWhichPrio(char buf[12], int x) {
if (x == PRIO_PROCESS) return "PRIO_PROCESS";
if (x == PRIO_PGRP) return "PRIO_PGRP";
if (x == PRIO_USER) return "PRIO_USER";

View file

@ -20,11 +20,19 @@
#include "libc/str/str.h"
#include "libc/thread/thread.h"
void(__fds_lock)(void) {
#ifdef __fds_lock
#undef __fds_lock
#endif
#ifdef __fds_unlock
#undef __fds_unlock
#endif
void __fds_lock(void) {
pthread_mutex_lock(&__fds_lock_obj);
}
void(__fds_unlock)(void) {
void __fds_unlock(void) {
pthread_mutex_unlock(&__fds_lock_obj);
}

View file

@ -20,14 +20,22 @@
#include "libc/str/str.h"
#include "libc/thread/thread.h"
#ifdef __mmi_lock
#undef __mmi_lock
#endif
#ifdef __mmi_unlock
#undef __mmi_unlock
#endif
// this lock currently needs to be (1) recursive and (2) not nsync
extern pthread_mutex_t __mmi_lock_obj;
void(__mmi_lock)(void) {
void __mmi_lock(void) {
pthread_mutex_lock(&__mmi_lock_obj);
}
void(__mmi_unlock)(void) {
void __mmi_unlock(void) {
pthread_mutex_unlock(&__mmi_lock_obj);
}

View file

@ -18,13 +18,17 @@
*/
#include "libc/intrin/psrad.h"
#ifdef psradv
#undef psradv
#endif
/**
* Divides shorts by two powers.
*
* @note arithmetic shift right will sign extend negatives
* @mayalias
*/
void(psradv)(int32_t a[4], const int32_t b[4], const uint64_t c[2]) {
void psradv(int32_t a[4], const int32_t b[4], const uint64_t c[2]) {
unsigned i;
unsigned char k;
k = c[0] > 31 ? 31 : c[0];

View file

@ -21,6 +21,10 @@
#include "libc/macros.internal.h"
#include "libc/str/str.h"
#ifdef psubusb
#undef psubusb
#endif
/**
* Subtracts unsigned 8-bit integers w/ saturation.
*
@ -29,7 +33,7 @@
* @param 𝑐 [r/o] supplies second input vector
* @mayalias
*/
void(psubusb)(uint8_t a[16], const uint8_t b[16], const uint8_t c[16]) {
void psubusb(uint8_t a[16], const uint8_t b[16], const uint8_t c[16]) {
unsigned i;
uint8_t r[16];
for (i = 0; i < 16; ++i) {

View file

@ -4,7 +4,7 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void(psubw)(int16_t[8], const int16_t[8], const int16_t[8]);
void psubw(int16_t[8], const int16_t[8], const int16_t[8]);
#define psubw(A, B, C) \
INTRIN_SSEVEX_X_X_X_(psubw, SSE2, "psubw", INTRIN_NONCOMMUTATIVE, A, B, C)

View file

@ -21,7 +21,11 @@
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
void _pthread_cleanup_pop(struct _pthread_cleanup_buffer *cb, int execute) {
#ifdef pthread_cleanup_pop
#undef pthread_cleanup_pop
#endif
void pthread_cleanup_pop(struct _pthread_cleanup_buffer *cb, int execute) {
struct PosixThread *pt;
if (__tls_enabled && (pt = (struct PosixThread *)__get_tls()->tib_pthread)) {
_unassert(cb == pt->cleanup);

View file

@ -20,8 +20,12 @@
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
void _pthread_cleanup_push(struct _pthread_cleanup_buffer *cb,
void (*routine)(void *), void *arg) {
#ifdef pthread_cleanup_push
#undef pthread_cleanup_push
#endif
void pthread_cleanup_push(struct _pthread_cleanup_buffer *cb,
void (*routine)(void *), void *arg) {
struct PosixThread *pt;
cb->__routine = routine;
cb->__arg = arg;

View file

@ -18,6 +18,7 @@
*/
#include "libc/assert.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/strace.internal.h"
#include "libc/thread/thread.h"
#ifdef pthread_spin_lock
@ -44,10 +45,22 @@
*/
errno_t pthread_spin_lock(pthread_spinlock_t *spin) {
int x;
#if defined(SYSDEBUG) && _LOCKTRACE
for (;;) {
x = atomic_exchange_explicit(&spin->_lock, 1, memory_order_acquire);
if (!x) {
LOCKTRACE("pthread_spin_lock(%t)", spin);
break;
}
_unassert(x == 1);
LOCKTRACE("pthread_spin_lock(%t) trying...", spin);
}
#else
for (;;) {
x = atomic_exchange_explicit(&spin->_lock, 1, memory_order_acquire);
if (!x) break;
_unassert(x == 1);
}
#endif
return 0;
}

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/atomic.h"
#include "libc/intrin/strace.internal.h"
#include "libc/thread/thread.h"
#ifdef pthread_spin_unlock
@ -33,6 +34,7 @@
* @see pthread_spin_lock
*/
errno_t pthread_spin_unlock(pthread_spinlock_t *spin) {
LOCKTRACE("pthread_spin_unlock(%t)", spin);
atomic_store_explicit(&spin->_lock, 0, memory_order_release);
return 0;
}

View file

@ -297,12 +297,12 @@ static wontreturn relegated noinstrument void __minicrash(int sig,
* @vforksafe
*/
relegated void __oncrash(int sig, struct siginfo *si, ucontext_t *ctx) {
bool bZero;
int bZero;
intptr_t rip;
int me, owner;
int gdbpid, err;
static atomic_int once;
static atomic_bool once2;
static atomic_int once2;
STRACE("__oncrash rip %x", ctx->uc_mcontext.rip);
ftrace_enabled(-1);
strace_enabled(-1);

View file

@ -608,7 +608,7 @@ errno_t clone(void *func, void *stk, size_t stksz, int flags, void *arg,
}
STRACE("clone(%t, %p, %'zu, %#x, %p, %p, %p, %p) → %s", func, stk, stksz,
flags, arg, ptid, tls, ctid, DescribeErrnoResult(rc));
flags, arg, ptid, tls, ctid, DescribeErrno(rc));
return rc;
}

View file

@ -92,9 +92,9 @@ int posix_spawn(int *pid, const char *path,
posix_spawnattr_getsigmask(attrp, &sigmask);
sigprocmask(SIG_SETMASK, &sigmask, 0);
}
if (flags & POSIX_SPAWN_RESETIDS) {
setuid(getuid());
setgid(getgid());
if ((flags & POSIX_SPAWN_RESETIDS) &&
(setgid(getgid()) || setuid(getuid()))) {
_Exit(127);
}
if (flags & POSIX_SPAWN_SETSIGDEF) {
for (s = 1; s < 32; s++) {

View file

@ -135,6 +135,7 @@ static void FixIrregularFds(void) {
}
if (IsGenuineCosmo()) {
// TODO(jart): Fix Blinkenlights poll() / close()
free(pfds);
return;
}
if (poll(pfds, maxfds, 0) != -1) {

View file

@ -78,7 +78,6 @@ struct PosixThread {
nsync_dll_element_ list; // list of threads
jmp_buf exiter; // for pthread_exit
pthread_attr_t attr;
sigset_t sigmask;
struct _pthread_cleanup_buffer *cleanup;
};

View file

@ -16,10 +16,22 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/blockcancel.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/clock_gettime.internal.h"
#include "libc/errno.h"
#include "libc/macros.internal.h"
#include "libc/sysv/consts/clock.h"
#include "libc/str/str.h"
#include "libc/thread/thread2.h"
/**
* Gets signal mask on thread attributes object.
*
* @param attr is the thread attributes object
* @param sigmask will receive the output signal mask on success, or
* null if a simple presence check is desired
* @return 0 on success, errno on error, or `PTHREAD_ATTR_NO_SIGMASK_NP`
* if there wasn't any signal mask present in `attr`
*/
errno_t pthread_attr_getsigmask_np(const pthread_attr_t *attr,
sigset_t *sigmask) {
_Static_assert(sizeof(attr->__sigmask) == sizeof(*sigmask), "");
if (!attr->__havesigmask) return PTHREAD_ATTR_NO_SIGMASK_NP;
if (sigmask) memcpy(sigmask, attr->__sigmask, sizeof(*sigmask));
return 0;
}

View file

@ -42,7 +42,6 @@
*/
errno_t pthread_attr_setschedparam(pthread_attr_t *attr,
const struct sched_param *param) {
if (!param) return EINVAL;
attr->__schedparam = param->sched_priority;
return 0;
}

View file

@ -16,13 +16,25 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/str/str.h"
#include "libc/thread/thread2.h"
const char *(DescribeErrno)(char buf[12], int x) {
const char *s;
if ((s = _strerrno(x))) return s;
FormatInt32(buf, x);
return buf;
/**
* Sets signal mask on thread attributes object.
*
* @param attr is the thread attributes object
* @param sigmask will be copied into attributes, or if it's null, then
* the existing signal mask presence on the object will be cleared
* @return 0 on success, or errno on error
*/
errno_t pthread_attr_setsigmask_np(pthread_attr_t *attr,
const sigset_t *sigmask) {
_Static_assert(sizeof(attr->__sigmask) == sizeof(*sigmask), "");
if (sigmask) {
attr->__havesigmask = true;
memcpy(attr->__sigmask, sigmask, sizeof(*sigmask));
} else {
attr->__havesigmask = false;
}
return 0;
}

View file

@ -32,9 +32,11 @@
#include "libc/runtime/clone.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/clone.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/ss.h"
#include "libc/thread/posixthread.internal.h"
#include "libc/thread/spawn.h"
@ -84,7 +86,7 @@ static int PosixThread(void *arg, int tid) {
// set long jump handler so pthread_exit can bring control back here
if (!setjmp(pt->exiter)) {
__get_tls()->tib_pthread = (pthread_t)pt;
_sigsetmask(pt->sigmask);
_npassert(!sigprocmask(SIG_SETMASK, (sigset_t *)pt->attr.__sigmask, 0));
rc = pt->start(pt->arg);
// ensure pthread_cleanup_pop(), and pthread_exit() popped cleanup
_npassert(!pt->cleanup);
@ -224,6 +226,10 @@ static errno_t pthread_create_impl(pthread_t *thread,
}
// set initial status
if (!pt->attr.__havesigmask) {
pt->attr.__havesigmask = true;
memcpy(pt->attr.__sigmask, &oldsigs, sizeof(oldsigs));
}
switch (pt->attr.__detachstate) {
case PTHREAD_CREATE_JOINABLE:
atomic_store_explicit(&pt->status, kPosixThreadJoinable,
@ -246,7 +252,6 @@ static errno_t pthread_create_impl(pthread_t *thread,
pthread_spin_unlock(&_pthread_lock);
// launch PosixThread(pt) in new thread
pt->sigmask = oldsigs;
if ((rc = clone(PosixThread, pt->attr.__stackaddr,
pt->attr.__stacksize - (IsOpenbsd() ? 16 : 0),
CLONE_VM | CLONE_THREAD | CLONE_FS | CLONE_FILES |
@ -260,9 +265,7 @@ static errno_t pthread_create_impl(pthread_t *thread,
return rc;
}
if (thread) {
*thread = (pthread_t)pt;
}
*thread = (pthread_t)pt;
return 0;
}

View file

@ -71,6 +71,6 @@ errno_t pthread_getaffinity_np(pthread_t thread, size_t size,
}
STRACE("pthread_getaffinity_np(%d, %'zu, %p) → %s", tid, size, bitset,
DescribeErrnoResult(rc));
DescribeErrno(rc));
return rc;
}

View file

@ -16,13 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/thread/posixthread.internal.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#include "libc/thread/wait0.internal.h"
#include "libc/thread/thread2.h"
/**
* Waits for thread to terminate.
@ -44,24 +38,5 @@
* @threadsafe
*/
errno_t pthread_join(pthread_t thread, void **value_ptr) {
errno_t rc;
struct PosixThread *pt;
enum PosixThreadStatus status;
pt = (struct PosixThread *)thread;
status = atomic_load_explicit(&pt->status, memory_order_acquire);
// "The behavior is undefined if the value specified by the thread
// argument to pthread_join() does not refer to a joinable thread."
// ──Quoth POSIX.1-2017
_unassert(status == kPosixThreadJoinable || status == kPosixThreadTerminated);
if (!(rc = _wait0(&pt->tib->tib_tid))) {
pthread_spin_lock(&_pthread_lock);
_pthread_list = nsync_dll_remove_(_pthread_list, &pt->list);
pthread_spin_unlock(&_pthread_lock);
if (value_ptr) {
*value_ptr = pt->rc;
}
_pthread_free(pt);
pthread_decimate_np();
}
return 0;
return pthread_timedjoin_np(thread, value_ptr, 0);
}

View file

@ -22,7 +22,7 @@
/**
* Returns true if calling thread is the only thread.
*/
bool pthread_orphan_np(void) {
int pthread_orphan_np(void) {
bool res;
pthread_spin_lock(&_pthread_lock);
res = _pthread_list == _pthread_list->prev &&

View file

@ -74,6 +74,6 @@ errno_t pthread_setaffinity_np(pthread_t thread, size_t size,
}
}
STRACE("pthread_setaffinity_np(%d, %'zu, %p) → %s", tid, size, bitset,
DescribeErrnoResult(rc));
DescribeErrno(rc));
return rc;
}

View file

@ -44,7 +44,6 @@
errno_t pthread_setschedparam(pthread_t thread, int policy,
const struct sched_param *param) {
struct PosixThread *pt = (struct PosixThread *)thread;
if (!param) return EINVAL;
pt->attr.__schedpolicy = policy;
pt->attr.__schedparam = param->sched_priority;
return _pthread_reschedule(pt);

View file

@ -0,0 +1,72 @@
/*-*- 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/assert.h"
#include "libc/calls/struct/timespec.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/thread/posixthread.internal.h"
#include "libc/thread/thread2.h"
#include "libc/thread/tls.h"
#include "libc/thread/wait0.internal.h"
/**
* Waits for thread to terminate.
*
* Multiple threads joining the same thread is undefined behavior. If a
* deferred or masked cancellation happens to the calling thread either
* before or during the waiting process then the target thread will not
* be joined. Calling pthread_join() on a non-joinable thread, e.g. one
* that's been detached, is undefined behavior. If a thread attempts to
* join itself, then the behavior is undefined.
*
* @param value_ptr if non-null will receive pthread_exit() argument
* if the thread called pthread_exit(), or `PTHREAD_CANCELED` if
* pthread_cancel() destroyed the thread instead
* @param abstime specifies an absolute deadline or the timestamp of
* when we'll stop waiting; if this is null we will wait forever
* @return 0 on success, or errno on error
* @raise ECANCELED if calling thread was cancelled in masked mode
* @raise EBUSY if `abstime` deadline elapsed
* @cancellationpoint
* @returnserrno
* @threadsafe
*/
errno_t pthread_timedjoin_np(pthread_t thread, void **value_ptr,
struct timespec *abstime) {
errno_t rc;
struct PosixThread *pt;
enum PosixThreadStatus status;
pt = (struct PosixThread *)thread;
status = atomic_load_explicit(&pt->status, memory_order_acquire);
// "The behavior is undefined if the value specified by the thread
// argument to pthread_join() does not refer to a joinable thread."
// ──Quoth POSIX.1-2017
_unassert(status == kPosixThreadJoinable || status == kPosixThreadTerminated);
if (!(rc = _wait0(&pt->tib->tib_tid, abstime))) {
pthread_spin_lock(&_pthread_lock);
_pthread_list = nsync_dll_remove_(_pthread_list, &pt->list);
pthread_spin_unlock(&_pthread_lock);
if (value_ptr) {
*value_ptr = pt->rc;
}
_pthread_free(pt);
pthread_decimate_np();
}
return 0;
}

View file

@ -0,0 +1,42 @@
/*-*- 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/thread2.h"
/**
* Joins thread if it's already terminated.
*
* Multiple threads joining the same thread is undefined behavior. If a
* deferred or masked cancellation happens to the calling thread either
* before or during the waiting process then the target thread will not
* be joined. Calling pthread_join() on a non-joinable thread, e.g. one
* that's been detached, is undefined behavior. If a thread attempts to
* join itself, then the behavior is undefined.
*
* @param value_ptr if non-null will receive pthread_exit() argument
* if the thread called pthread_exit(), or `PTHREAD_CANCELED` if
* pthread_cancel() destroyed the thread instead
* @return 0 on success, or errno on error
* @raise ECANCELED if calling thread was cancelled in masked mode
* @cancellationpoint
* @returnserrno
* @threadsafe
*/
errno_t pthread_tryjoin_np(pthread_t thread, void **value_ptr) {
return pthread_timedjoin_np(thread, value_ptr, &timespec_zero);
}

View file

@ -34,7 +34,7 @@
int sem_post(sem_t *sem) {
int rc, old, wakeups;
_unassert(sem->sem_pshared || sem->sem_pid == getpid());
old = atomic_fetch_add_explicit(&sem->sem_value, 1, memory_order_relaxed);
old = atomic_fetch_add_explicit(&sem->sem_value, 1, memory_order_acq_rel);
_unassert(old > INT_MIN);
if (old >= 0) {
wakeups = nsync_futex_wake_(&sem->sem_value, 1, sem->sem_pshared);

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/macros.internal.h"
@ -148,7 +149,7 @@ int _join(struct spawn *th) {
int rc;
if (th->tib) {
// wait for ctid to become zero
_wait0(&th->tib->tib_tid);
_npassert(!_wait0(&th->tib->tib_tid, 0));
// free thread memory
free(th->tls);
rc = munmap(th->stk, GetStackSize());

View file

@ -35,6 +35,8 @@
#define PTHREAD_SCOPE_SYSTEM 0
#define PTHREAD_SCOPE_PROCESS 1
#define PTHREAD_ATTR_NO_SIGMASK_NP -1
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@ -58,7 +60,7 @@ typedef struct pthread_once_s {
} pthread_once_t;
typedef struct pthread_spinlock_s {
_Atomic(char) _lock;
_Atomic(int) _lock;
} pthread_spinlock_t;
typedef struct pthread_mutex_s {
@ -91,11 +93,13 @@ typedef struct pthread_barrier_s {
typedef struct pthread_attr_s {
char __detachstate;
char __inheritsched;
char __havesigmask;
int __schedparam;
int __schedpolicy;
int __contentionscope;
unsigned __guardsize;
unsigned __stacksize;
uint32_t __sigmask[4];
char *__stackaddr;
} pthread_attr_t;
@ -106,108 +110,109 @@ struct _pthread_cleanup_buffer {
struct _pthread_cleanup_buffer *__prev;
};
int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *),
void *);
/* clang-format off */
int pthread_yield(void);
bool pthread_orphan_np(void);
void pthread_testcancel(void);
void pthread_decimate_np(void);
int pthread_testcancel_np(void);
void pthread_exit(void *) wontreturn;
pthread_t pthread_self(void) pureconst;
int pthread_print_np(int, const char *, ...);
pthread_id_np_t pthread_getthreadid_np(void);
int pthread_getunique_np(pthread_t, pthread_id_np_t *);
int pthread_setname_np(pthread_t, const char *);
int pthread_getname_np(pthread_t, char *, size_t);
int pthread_getattr_np(pthread_t, pthread_attr_t *);
int pthread_attr_init(pthread_attr_t *);
int pthread_attr_destroy(pthread_attr_t *);
int pthread_attr_getdetachstate(const pthread_attr_t *, int *);
int pthread_attr_setdetachstate(pthread_attr_t *, int);
int pthread_attr_getguardsize(const pthread_attr_t *, size_t *);
int pthread_attr_setguardsize(pthread_attr_t *, size_t);
int pthread_attr_getinheritsched(const pthread_attr_t *, int *);
int pthread_attr_setinheritsched(pthread_attr_t *, int);
int pthread_attr_getschedpolicy(const pthread_attr_t *, int *);
int pthread_attr_setschedpolicy(pthread_attr_t *, int);
int pthread_attr_getscope(const pthread_attr_t *, int *);
int pthread_attr_setscope(pthread_attr_t *, int);
int pthread_attr_getstack(const pthread_attr_t *, void **, size_t *);
int pthread_attr_setstack(pthread_attr_t *, void *, size_t);
int pthread_attr_getstacksize(const pthread_attr_t *, size_t *);
int pthread_attr_setstacksize(pthread_attr_t *, size_t);
int pthread_detach(pthread_t);
int pthread_kill(pthread_t, int);
int pthread_cancel(pthread_t);
int pthread_setcanceltype(int, int *);
int pthread_setcancelstate(int, int *);
int pthread_setschedprio(pthread_t, int);
int pthread_join(pthread_t, void **);
int pthread_equal(pthread_t, pthread_t);
int pthread_once(pthread_once_t *, void (*)(void));
int pthread_spin_init(pthread_spinlock_t *, int);
int pthread_spin_destroy(pthread_spinlock_t *);
int pthread_spin_lock(pthread_spinlock_t *);
int pthread_spin_unlock(pthread_spinlock_t *);
int pthread_spin_trylock(pthread_spinlock_t *);
int pthread_mutexattr_init(pthread_mutexattr_t *);
int pthread_mutexattr_destroy(pthread_mutexattr_t *);
int pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *);
int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *, int *);
int pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
int pthread_mutex_lock(pthread_mutex_t *);
int pthread_mutex_unlock(pthread_mutex_t *);
int pthread_mutex_trylock(pthread_mutex_t *);
int pthread_mutex_destroy(pthread_mutex_t *);
int pthread_mutex_consistent(pthread_mutex_t *);
int pthread_condattr_init(pthread_condattr_t *);
int pthread_condattr_destroy(pthread_condattr_t *);
int pthread_condattr_setpshared(pthread_condattr_t *, int);
int pthread_condattr_getpshared(const pthread_condattr_t *, int *);
int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
int pthread_cond_destroy(pthread_cond_t *);
int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
int pthread_cond_broadcast(pthread_cond_t *);
int pthread_cond_signal(pthread_cond_t *);
int pthread_rwlockattr_init(pthread_rwlockattr_t *);
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, int *);
int pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *);
int pthread_rwlock_destroy(pthread_rwlock_t *);
int pthread_rwlock_rdlock(pthread_rwlock_t *);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
int pthread_rwlock_wrlock(pthread_rwlock_t *);
int pthread_rwlock_trywrlock(pthread_rwlock_t *);
int pthread_rwlock_unlock(pthread_rwlock_t *);
int pthread_key_create(pthread_key_t *, pthread_key_dtor);
int pthread_attr_destroy(pthread_attr_t *) paramsnonnull();
int pthread_attr_getdetachstate(const pthread_attr_t *, int *) paramsnonnull();
int pthread_attr_getguardsize(const pthread_attr_t *, size_t *) paramsnonnull();
int pthread_attr_getinheritsched(const pthread_attr_t *, int *) paramsnonnull();
int pthread_attr_getschedpolicy(const pthread_attr_t *, int *) paramsnonnull();
int pthread_attr_getscope(const pthread_attr_t *, int *) paramsnonnull();
int pthread_attr_getstack(const pthread_attr_t *, void **, size_t *) paramsnonnull();
int pthread_attr_getstacksize(const pthread_attr_t *, size_t *) paramsnonnull();
int pthread_attr_init(pthread_attr_t *) paramsnonnull();
int pthread_attr_setdetachstate(pthread_attr_t *, int) paramsnonnull();
int pthread_attr_setguardsize(pthread_attr_t *, size_t) paramsnonnull();
int pthread_attr_setinheritsched(pthread_attr_t *, int) paramsnonnull();
int pthread_attr_setschedpolicy(pthread_attr_t *, int) paramsnonnull();
int pthread_attr_setscope(pthread_attr_t *, int) paramsnonnull();
int pthread_attr_setstack(pthread_attr_t *, void *, size_t) paramsnonnull((1));
int pthread_attr_setstacksize(pthread_attr_t *, size_t) paramsnonnull();
int pthread_barrier_destroy(pthread_barrier_t *) paramsnonnull();
int pthread_barrier_init(pthread_barrier_t *, const pthread_barrierattr_t *, unsigned) paramsnonnull((1));
int pthread_barrier_wait(pthread_barrier_t *) paramsnonnull();
int pthread_barrierattr_destroy(pthread_barrierattr_t *) paramsnonnull();
int pthread_barrierattr_getpshared(const pthread_barrierattr_t *, int *) paramsnonnull();
int pthread_barrierattr_init(pthread_barrierattr_t *) paramsnonnull();
int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int) paramsnonnull();
int pthread_cancel(pthread_t);
int pthread_cond_broadcast(pthread_cond_t *) paramsnonnull();
int pthread_cond_destroy(pthread_cond_t *) paramsnonnull();
int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *) paramsnonnull((1));
int pthread_cond_signal(pthread_cond_t *) paramsnonnull();
int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *) paramsnonnull();
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_detach(pthread_t);
int pthread_equal(pthread_t, pthread_t);
int pthread_getattr_np(pthread_t, pthread_attr_t *) paramsnonnull();
int pthread_getname_np(pthread_t, char *, size_t) paramsnonnull();
int pthread_getunique_np(pthread_t, pthread_id_np_t *) paramsnonnull();
int pthread_join(pthread_t, void **);
int pthread_key_create(pthread_key_t *, pthread_key_dtor) paramsnonnull((1));
int pthread_key_delete(pthread_key_t);
int pthread_kill(pthread_t, int);
int pthread_mutex_consistent(pthread_mutex_t *) paramsnonnull();
int pthread_mutex_destroy(pthread_mutex_t *) paramsnonnull();
int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *) paramsnonnull((1));
int pthread_mutex_lock(pthread_mutex_t *) paramsnonnull();
int pthread_mutex_trylock(pthread_mutex_t *) paramsnonnull();
int pthread_mutex_unlock(pthread_mutex_t *) paramsnonnull();
int pthread_mutexattr_destroy(pthread_mutexattr_t *) paramsnonnull();
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *, int *) paramsnonnull();
int pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *) paramsnonnull();
int pthread_mutexattr_init(pthread_mutexattr_t *) paramsnonnull();
int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int) paramsnonnull();
int pthread_mutexattr_settype(pthread_mutexattr_t *, int) paramsnonnull();
int pthread_once(pthread_once_t *, void (*)(void)) paramsnonnull();
int pthread_orphan_np(void);
int pthread_print_np(int, const char *, ...);
int pthread_rwlock_destroy(pthread_rwlock_t *) paramsnonnull();
int pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *) paramsnonnull((1));
int pthread_rwlock_rdlock(pthread_rwlock_t *) paramsnonnull();
int pthread_rwlock_tryrdlock(pthread_rwlock_t *) paramsnonnull();
int pthread_rwlock_trywrlock(pthread_rwlock_t *) paramsnonnull();
int pthread_rwlock_unlock(pthread_rwlock_t *) paramsnonnull();
int pthread_rwlock_wrlock(pthread_rwlock_t *) paramsnonnull();
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *) paramsnonnull();
int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, int *) paramsnonnull();
int pthread_rwlockattr_init(pthread_rwlockattr_t *) paramsnonnull();
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int) paramsnonnull();
int pthread_setcancelstate(int, int *);
int pthread_setcanceltype(int, int *);
int pthread_setname_np(pthread_t, const char *) paramsnonnull();
int pthread_setschedprio(pthread_t, int);
int pthread_setspecific(pthread_key_t, const void *);
int pthread_spin_destroy(pthread_spinlock_t *) paramsnonnull();
int pthread_spin_init(pthread_spinlock_t *, int) paramsnonnull();
int pthread_spin_lock(pthread_spinlock_t *) paramsnonnull();
int pthread_spin_trylock(pthread_spinlock_t *) paramsnonnull();
int pthread_spin_unlock(pthread_spinlock_t *) paramsnonnull();
int pthread_testcancel_np(void);
int pthread_tryjoin_np(pthread_t, void **);
int pthread_yield(void);
pthread_id_np_t pthread_getthreadid_np(void);
pthread_t pthread_self(void) pureconst;
void *pthread_getspecific(pthread_key_t);
int pthread_barrierattr_init(pthread_barrierattr_t *);
int pthread_barrierattr_destroy(pthread_barrierattr_t *);
int pthread_barrierattr_getpshared(const pthread_barrierattr_t *, int *);
int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int);
int pthread_barrier_wait(pthread_barrier_t *);
int pthread_barrier_destroy(pthread_barrier_t *);
int pthread_barrier_init(pthread_barrier_t *, const pthread_barrierattr_t *,
unsigned);
void _pthread_cleanup_pop(struct _pthread_cleanup_buffer *, int);
void _pthread_cleanup_push(struct _pthread_cleanup_buffer *, void (*)(void *),
void *);
void pthread_cleanup_pop(struct _pthread_cleanup_buffer *, int) paramsnonnull();
void pthread_cleanup_push(struct _pthread_cleanup_buffer *, void (*)(void *), void *) paramsnonnull((1));
void pthread_decimate_np(void);
void pthread_exit(void *) wontreturn;
void pthread_testcancel(void);
/* clang-format on */
#define pthread_cleanup_push(routine, arg) \
{ \
struct _pthread_cleanup_buffer _buffer; \
_pthread_cleanup_push(&_buffer, (routine), (arg));
pthread_cleanup_push(&_buffer, (routine), (arg));
#define pthread_cleanup_pop(execute) \
_pthread_cleanup_pop(&_buffer, (execute)); \
#define pthread_cleanup_pop(execute) \
pthread_cleanup_pop(&_buffer, (execute)); \
}
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 && \

View file

@ -2,21 +2,26 @@
#define COSMOPOLITAN_LIBC_INTRIN_PTHREAD2_H_
#include "libc/calls/struct/cpuset.h"
#include "libc/calls/struct/sched_param.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/timespec.h"
#include "libc/runtime/stack.h"
#include "libc/thread/thread.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/* clang-format off */
int pthread_attr_getschedparam(const pthread_attr_t *, struct sched_param *);
int pthread_attr_setschedparam(pthread_attr_t *, const struct sched_param *);
int pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *,
const struct timespec *);
int pthread_setaffinity_np(pthread_t, size_t, const cpu_set_t *);
int pthread_getaffinity_np(pthread_t, size_t, cpu_set_t *);
int pthread_setschedparam(pthread_t, int, const struct sched_param *);
int pthread_getschedparam(pthread_t, int *, struct sched_param *);
int pthread_attr_getschedparam(const pthread_attr_t *, struct sched_param *) paramsnonnull();
int pthread_attr_getsigmask_np(const pthread_attr_t *, sigset_t *) paramsnonnull((1));
int pthread_attr_setschedparam(pthread_attr_t *, const struct sched_param *) paramsnonnull();
int pthread_attr_setsigmask_np(pthread_attr_t *, const sigset_t *) paramsnonnull((1));
int pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *, const struct timespec *) paramsnonnull((1, 2));
int pthread_getaffinity_np(pthread_t, size_t, cpu_set_t *) paramsnonnull();
int pthread_getschedparam(pthread_t, int *, struct sched_param *) paramsnonnull();
int pthread_setaffinity_np(pthread_t, size_t, const cpu_set_t *) paramsnonnull();
int pthread_setschedparam(pthread_t, int, const struct sched_param *) paramsnonnull();
int pthread_timedjoin_np(pthread_t, void **, struct timespec *);
/* clang-format off */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_INTRIN_PTHREAD2_H_ */

View file

@ -18,6 +18,7 @@
*/
#include "libc/assert.h"
#include "libc/calls/cp.internal.h"
#include "libc/calls/struct/timespec.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
@ -37,9 +38,10 @@
*
* @return 0 on success, or errno on error
* @raise ECANCELED if calling thread was cancelled in masked mode
* @raise EBUSY if `abstime` was specified and deadline expired
* @cancellationpoint
*/
errno_t _wait0(const atomic_int *ctid) {
errno_t _wait0(const atomic_int *ctid, struct timespec *abstime) {
int x, rc = 0;
// "The behavior is undefined if the value specified by the thread
// argument to pthread_join() refers to the calling thread."
@ -50,9 +52,13 @@ errno_t _wait0(const atomic_int *ctid) {
if (!(rc = pthread_testcancel_np())) {
BEGIN_CANCELLATION_POINT;
while ((x = atomic_load_explicit(ctid, memory_order_acquire))) {
if (nsync_futex_wait_(ctid, x, !IsWindows(), 0) == -ECANCELED) {
rc = nsync_futex_wait_(ctid, x, !IsWindows(), abstime);
if (rc == -ECANCELED) {
rc = ECANCELED;
break;
} else if (rc == -ETIMEDOUT) {
rc = EBUSY;
break;
}
}
END_CANCELLATION_POINT;

View file

@ -1,10 +1,11 @@
#ifndef COSMOPOLITAN_LIBC_INTRIN_WAIT0_H_
#define COSMOPOLITAN_LIBC_INTRIN_WAIT0_H_
#include "libc/atomic.h"
#include "libc/calls/struct/timespec.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
errno_t _wait0(const atomic_int *) _Hide;
errno_t _wait0(const atomic_int *, struct timespec *) _Hide;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -42,6 +42,7 @@ static const struct ContentTypeExtension {
{"css", "text/css"}, //
{"csv", "text/csv"}, //
{"diff", "text/plain"}, //
{"diff", "text/plain"}, //
{"doc", "application/msword"}, //
{"epub", "application/epub+zip"}, //
{"gif", "image/gif"}, //
@ -71,6 +72,7 @@ static const struct ContentTypeExtension {
{"ogv", "video/ogg"}, //
{"ogx", "application/ogg"}, //
{"otf", "font/otf"}, //
{"patch", "text/plain"}, //
{"pdf", "application/pdf"}, //
{"png", "image/png"}, //
{"rar", "application/vnd.rar"}, //

Some files were not shown because too many files have changed in this diff Show more