mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-30 08:18:30 +00:00
parent
95f54eeb40
commit
c1d99676c4
1421 changed files with 5556 additions and 2198 deletions
|
@ -23,6 +23,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/msr.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/runtime/interruptiblecall.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -164,12 +165,36 @@ static privileged dontinline int arch_prctl_openbsd(int code, int64_t addr) {
|
|||
}
|
||||
|
||||
static char g_fsgs_once;
|
||||
static struct InterruptibleCall g_fsgs_icall;
|
||||
|
||||
/**
|
||||
* Don't bother.
|
||||
*/
|
||||
int arch_prctl(int code, int64_t addr) {
|
||||
void *fn = arch_prctl_fsgsbase;
|
||||
|
||||
#if 0
|
||||
if (!g_fsgs_once) {
|
||||
g_fsgs_once = true;
|
||||
if (X86_HAVE(FSGSBASE)) {
|
||||
g_fsgs_icall.sig = SIGILL;
|
||||
if (interruptiblecall(&g_fsgs_icall, fn, code, addr, 0, 0) != -1 &&
|
||||
g_fsgs_icall.returnval != -1) {
|
||||
/* ivybridge+ (2012) lets us change segment registers without
|
||||
needing a 700ns system call. cpuid and /proc/cpuinfo will both
|
||||
report it's available; unfortunately, operating systems have an
|
||||
added ability to restrict this feature in %cr4, which we're not
|
||||
even allowed to read lool */
|
||||
g_fsgs_once = 2;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (g_fsgs_once == 2) {
|
||||
return arch_prctl_fsgsbase(code, addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (__hostos) {
|
||||
case METAL:
|
||||
return arch_prctl_msr(code, addr);
|
||||
|
|
74
libc/runtime/interruptiblecall.c
Normal file
74
libc/runtime/interruptiblecall.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*-*- 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 2020 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/bits/safemacros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/interruptiblecall.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
STATIC_YOINK("_init_onntconsoleevent");
|
||||
|
||||
static struct InterruptibleCall *g_interruptiblecall;
|
||||
|
||||
wontreturn static void interruptcall(int sig) {
|
||||
longjmp(g_interruptiblecall->jb, 1);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls function that may be cancelled by a signal.
|
||||
*
|
||||
* @param state is allocated and zero'd by the caller; state→sig and
|
||||
* state→sa_new.sa_mask may be set; it may be re-used w/o
|
||||
* reinitializing; it may be static or heap memory; it may be stack
|
||||
* memory if re-entrant behavior isn't needed
|
||||
* @return the value returned by callback or -1 on interrupt; they may
|
||||
* be differentiated using the state→returnval filed, which is only
|
||||
* modified by this function when callbacks succeed
|
||||
*/
|
||||
intptr_t interruptiblecall(struct InterruptibleCall *icall,
|
||||
intptr_t callback(intptr_t p1, intptr_t p2,
|
||||
intptr_t p3, intptr_t p4),
|
||||
intptr_t p1, intptr_t p2, intptr_t p3, intptr_t p4) {
|
||||
intptr_t rc;
|
||||
if (!icall->sig) icall->sig = SIGINT;
|
||||
icall->sa_new.sa_handler = interruptcall;
|
||||
icall->sa_new.sa_flags |= SA_RESTART | SA_RESETHAND;
|
||||
if ((rc = (sigaction)(icall->sig, &icall->sa_new, &icall->sa_old)) != -1) {
|
||||
icall->prev = g_interruptiblecall;
|
||||
g_interruptiblecall = icall;
|
||||
if (!setjmp(icall->jb)) {
|
||||
icall->returnval = rc = callback(p1, p2, p3, p4);
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
asm volatile("" ::: "memory");
|
||||
struct InterruptibleCall *unwind;
|
||||
for (;;) {
|
||||
unwind = g_interruptiblecall;
|
||||
(sigaction)(unwind->sig, &unwind->sa_old, NULL);
|
||||
g_interruptiblecall = unwind->prev;
|
||||
if (unwind == icall) break;
|
||||
free_s(&unwind);
|
||||
}
|
||||
icall->prev = NULL;
|
||||
}
|
||||
return rc;
|
||||
}
|
26
libc/runtime/interruptiblecall.h
Normal file
26
libc/runtime/interruptiblecall.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_INTERRUPTIBLECALL_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_INTERRUPTIBLECALL_H_
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct InterruptibleCall {
|
||||
struct InterruptibleCall *prev;
|
||||
intptr_t returnval;
|
||||
int sig;
|
||||
int flags;
|
||||
jmp_buf jb;
|
||||
struct sigaction sa_new;
|
||||
struct sigaction sa_old;
|
||||
};
|
||||
|
||||
intptr_t interruptiblecall(struct InterruptibleCall *state,
|
||||
intptr_t callback(intptr_t p1, intptr_t p2,
|
||||
intptr_t p3, intptr_t p4),
|
||||
intptr_t p1, intptr_t p2, intptr_t p3, intptr_t p4);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_RUNTIME_INTERRUPTIBLECALL_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue