cosmopolitan/libc/runtime/missioncritical.h

144 lines
7.1 KiB
C

#ifndef COSMOPOLITAN_LIBC_INTERNAL_MISSIONCRITICAL_H_
#define COSMOPOLITAN_LIBC_INTERNAL_MISSIONCRITICAL_H_
#include "libc/bits/bits.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/nexgen32e/nexgen32e.h"
#include "libc/nt/console.h"
#include "libc/nt/enum/version.h"
#include "libc/nt/ntdll.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/teb.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/nr.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
/**
* @fileoverview Mission critical system calls.
*/
#define PRINT(STR) __print(STR, tinystrlen(STR))
#define NT_HAVE_IMPORT(SLOT) \
((void *)*SLOT && *SLOT != (void *)&missingno /* see libc/crt/crt.S */)
#define _EXIT(rc) \
({ \
int ExitAx; \
asm volatile("syscall" \
: "=a"(ExitAx) \
: "0"(__NR_exit), "D"(rc) \
: "rcx", "r11", "cc", "memory"); \
ExitAx; \
})
#define GETPID() \
({ \
int Res; \
asm("syscall" : "=a"(Res) : "0"(__NR_getpid) : "rcx", "r11", "cc"); \
Res; \
})
#define KILL(pid, sig) \
({ \
int KillAx; \
unsigned char Cf; \
asm volatile(CFLAG_ASM("clc\n\t" \
"syscall") \
: CFLAG_CONSTRAINT(Cf), "=a"(KillAx) \
: "1"(__NR_kill), "D"(pid), "S"(sig) \
: "rcx", "r11", "cc", "memory"); \
Cf ? -KillAx : KillAx; \
})
#define RAISE(SIG) \
({ \
int RaiseAx = -1; \
int Sig = (SIG); \
if (Sig == SIGTRAP) { \
DebugBreak(); \
} else if (!IsWindows()) { \
RaiseAx = KILL(GETPID(), Sig); \
} else { \
switch (Sig) { \
case SIGINT: \
GenerateConsoleCtrlEvent(kNtCtrlCEvent, 0); \
break; \
case SIGHUP: \
GenerateConsoleCtrlEvent(kNtCtrlCloseEvent, 0); \
break; \
case SIGQUIT: \
GenerateConsoleCtrlEvent(kNtCtrlBreakEvent, 0); \
break; \
default: \
for (;;) TerminateProcess(GetCurrentProcess(), 128 + Sig); \
} \
} \
RaiseAx; \
})
#define SCHED_YIELD() \
({ \
int64_t SyAx; \
if (!IsWindows()) { \
asm volatile("syscall" \
: "=a"(SyAx) \
: "0"(__NR_sched_yield) \
: "rcx", "r11", "cc", "memory"); \
} else { \
NtYieldExecution(); \
} \
0; \
})
#define WAIT4(PID, OPT_OUT_WSTATUS, OPTIONS, OPT_OUT_RUSAGE) \
({ \
int64_t WaAx; \
if (!IsWindows()) { \
register void *Reg10 asm("r10") = (OPT_OUT_RUSAGE); \
asm volatile("syscall" \
: "=a"(WaAx) \
: "0"(__NR_wait4), "D"(PID), "S"(OPT_OUT_WSTATUS), \
"d"(OPTIONS), "r"(Reg10) \
: "rcx", "r11", "cc", "memory"); \
} else { \
WaAx = wait4$nt(PID, OPT_OUT_WSTATUS, OPTIONS, OPT_OUT_RUSAGE); \
} \
WaAx; \
})
#if 0
/**
* Exits on Windows the hard way.
*/
#endif
#define NT_TERMINATE_PROCESS() \
do \
if (NtGetVersion() < kNtVersionFuture) { \
int64_t ax, cx; \
do \
asm volatile( \
"syscall" /* hook THIS system call */ \
: "=a"(ax), "=c"(cx) \
: "0"(NtGetVersion() < kNtVersionWindows8 \
? 0x0029 \
: NtGetVersion() < kNtVersionWindows81 \
? 0x002a \
: NtGetVersion() < kNtVersionWindows10 ? 0x002b \
: 0x002c), \
"1"(-1L /* GetCurrentProcess() */), "d"(42) \
: "r11", "cc", "memory"); \
while (!ax); \
} \
while (0)
interruptfn void __print(const void *, size_t);
#define LOAD_DEFAULT_RBX() /* disabled for now b/c clang */
#define RESTORE_RBX() /* disabled for now b/c clang */
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_INTERNAL_MISSIONCRITICAL_H_ */