mirror of
https://github.com/urbit/ares.git
synced 2024-12-23 13:25:03 +03:00
wip: sts. vincent and anastasius
This commit is contained in:
parent
f7fcffc429
commit
cb73bcd8ca
@ -15,11 +15,13 @@ use crate::noun::{Atom, Cell, IndirectAtom, Noun, Slots, D, T};
|
||||
use crate::serf::TERMINATOR;
|
||||
use crate::trace::{write_nock_trace, TraceInfo, TraceStack};
|
||||
use crate::unifying_equality::unifying_equality;
|
||||
use ares_guard::guard;
|
||||
use ares_guard::{guard, guard_err};
|
||||
use ares_macros::tas;
|
||||
use assert_no_alloc::{assert_no_alloc, ensure_alloc_counters};
|
||||
use bitvec::prelude::{BitSlice, Lsb0};
|
||||
use bitvec::ptr::null_mut;
|
||||
use either::Either::*;
|
||||
use std::ffi::c_void;
|
||||
use std::result;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
@ -317,6 +319,14 @@ pub enum Error {
|
||||
NonDeterministic(Noun), // trace
|
||||
}
|
||||
|
||||
pub enum GuardError {
|
||||
GuardSound = 0,
|
||||
GuardArmor = 1,
|
||||
GuardWeird = 2,
|
||||
GuardSpent = 3,
|
||||
GuardErupt = 4,
|
||||
}
|
||||
|
||||
impl Preserve for Error {
|
||||
unsafe fn preserve(&mut self, stack: &mut NockStack) {
|
||||
match self {
|
||||
@ -358,6 +368,51 @@ fn debug_assertions(stack: &mut NockStack, noun: Noun) {
|
||||
assert_no_junior_pointers!(stack, noun);
|
||||
}
|
||||
|
||||
extern "C" fn rust_callback(arg: *mut c_void) -> *mut c_void {
|
||||
let closure: &mut Box<dyn FnMut() -> *mut c_void> =
|
||||
unsafe { &mut *(arg as *mut Box<dyn FnMut() -> *mut c_void>) };
|
||||
closure()
|
||||
}
|
||||
|
||||
pub fn call_with_guard<F: FnMut() -> Result>(
|
||||
f: F,
|
||||
stack: *mut *mut c_void,
|
||||
alloc: *mut *mut c_void,
|
||||
ret: *mut *mut c_void,
|
||||
) -> Result {
|
||||
let boxed_f = Box::new(f);
|
||||
|
||||
unsafe {
|
||||
let result: *mut c_void = std::ptr::null_mut();
|
||||
let raw_f = Box::into_raw(Box::new(boxed_f));
|
||||
|
||||
guard(
|
||||
Some(rust_callback),
|
||||
raw_f as *mut c_void,
|
||||
stack,
|
||||
alloc,
|
||||
ret,
|
||||
);
|
||||
|
||||
let _ = Box::from_raw(raw_f);
|
||||
|
||||
if !result.is_null() {
|
||||
let err = *(result as *const guard_err);
|
||||
match err {
|
||||
0 => { // sound
|
||||
let res = result as *mut Result;
|
||||
*res
|
||||
},
|
||||
// TODO: handle other errors explicitly.
|
||||
_ => Err(Error::Deterministic(D(0))),
|
||||
}
|
||||
}
|
||||
else {
|
||||
(Box::from_raw(raw_f))()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Interpret nock */
|
||||
pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Result {
|
||||
let terminator = Arc::clone(&TERMINATOR);
|
||||
@ -390,7 +445,10 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res
|
||||
//
|
||||
// (See https://docs.rs/assert_no_alloc/latest/assert_no_alloc/#advanced-use)
|
||||
let nock = assert_no_alloc(|| {
|
||||
ensure_alloc_counters(|| unsafe {
|
||||
ensure_alloc_counters(|| {
|
||||
let stack_p = context.stack.get_stack_pointer();
|
||||
let alloc_p = context.stack.get_alloc_pointer();
|
||||
call_with_guard(|| unsafe {
|
||||
push_formula(&mut context.stack, formula, true)?;
|
||||
|
||||
loop {
|
||||
@ -929,6 +987,11 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
stack_p as *mut *mut c_void,
|
||||
alloc_p as *mut *mut c_void,
|
||||
std::ptr::null_mut() as *mut *mut c_void,
|
||||
)
|
||||
})
|
||||
});
|
||||
|
||||
|
@ -14,19 +14,11 @@ static void *guard_p = NULL;
|
||||
static void *stack_p = NULL;
|
||||
static void *alloc_p = NULL;
|
||||
|
||||
typedef enum {
|
||||
guard_sound = 0, // job's done
|
||||
guard_armor = 1, // mprotect
|
||||
guard_weird = 2, // strange state
|
||||
guard_spent = 3, // out of memory (bail:meme)
|
||||
guard_erupt = 4, // sigint
|
||||
} guard_error;
|
||||
|
||||
volatile sig_atomic_t guard_err = guard_sound;
|
||||
volatile sig_atomic_t err = guard_sound;
|
||||
|
||||
|
||||
// Center the guard page.
|
||||
guard_error _focus_guard() {
|
||||
guard_err _focus_guard() {
|
||||
// Check for strange situations.
|
||||
if (stack_p == NULL || alloc_p == NULL) {
|
||||
return guard_weird;
|
||||
@ -62,7 +54,7 @@ guard_error _focus_guard() {
|
||||
return guard_sound;
|
||||
}
|
||||
|
||||
guard_error _slash_guard(void *si_addr) {
|
||||
guard_err _slash_guard(void *si_addr) {
|
||||
if (si_addr >= guard_p && si_addr < guard_p + GD_PAGESIZE) {
|
||||
return _focus_guard();
|
||||
}
|
||||
@ -73,17 +65,17 @@ guard_error _slash_guard(void *si_addr) {
|
||||
void _signal_handler(int sig, siginfo_t *si, void *unused) {
|
||||
switch (sig) {
|
||||
case SIGSEGV:
|
||||
guard_err = _slash_guard(si->si_addr);
|
||||
err = _slash_guard(si->si_addr);
|
||||
break;
|
||||
case SIGINT:
|
||||
guard_err = guard_erupt;
|
||||
err = guard_erupt;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
guard_error _register_handler() {
|
||||
guard_err _register_handler() {
|
||||
struct sigaction sa;
|
||||
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
@ -97,28 +89,28 @@ guard_error _register_handler() {
|
||||
return guard_sound;
|
||||
}
|
||||
|
||||
void guard(void *(*f)(void *), void *arg, void **stack, void **alloc, void **ret) {
|
||||
void guard(void *(*f)(void *), void *arg, void *const *const stack, void *const *const alloc, void **ret) {
|
||||
stack_p = *stack;
|
||||
alloc_p = *alloc;
|
||||
|
||||
if (_register_handler() != guard_sound) {
|
||||
guard_err = guard_weird;
|
||||
err = guard_weird;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (guard_p == NULL && (guard_err = _focus_guard()) != guard_sound) {
|
||||
if (guard_p == NULL && (err = _focus_guard()) != guard_sound) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*ret = f(arg);
|
||||
|
||||
if (guard_err != guard_sound) {
|
||||
if (err != guard_sound) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
*ret = (void *) &guard_err;
|
||||
*ret = (void *) &err;
|
||||
return;
|
||||
}
|
||||
|
@ -30,6 +30,15 @@
|
||||
* error will be written to the `ret` pointer. The caller is then responsible
|
||||
* for handling this error and aborting with a `bail:meme`.
|
||||
*/
|
||||
void guard(void *(*f)(void *), void *arg, void **stack, void **alloc, void **ret);
|
||||
void guard(void *(*f)(void *), void *arg, void *const *const stack, void *const *const alloc, void **ret);
|
||||
|
||||
typedef enum {
|
||||
guard_sound = 0, // job's done
|
||||
guard_armor = 1, // mprotect
|
||||
guard_weird = 2, // strange state
|
||||
guard_spent = 3, // out of memory (bail:meme)
|
||||
guard_erupt = 4, // sigint
|
||||
} guard_err;
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user