Revert "wip: use only one jmp_buf; add NockStackSnapshot"

This reverts commit 1980ca7fd6.
This commit is contained in:
Matthew LeVan 2024-02-15 14:32:17 -05:00
parent 1980ca7fd6
commit 8bcbf6adca
4 changed files with 66 additions and 43 deletions

View File

@ -65,8 +65,8 @@ impl<'closure> CCallback<'closure> {
} }
pub fn call_with_guard<F: FnMut() -> Result>( pub fn call_with_guard<F: FnMut() -> Result>(
stack_pp: *const *mut u64, stack_pp: *const *const u64,
alloc_pp: *const *mut u64, alloc_pp: *const *const u64,
closure: &mut F, closure: &mut F,
) -> Result { ) -> Result {
let cb = CCallback::new(closure); let cb = CCallback::new(closure);
@ -100,7 +100,8 @@ pub fn call_with_guard<F: FnMut() -> Result>(
} }
pub fn interpret_with_guard(context: &mut Context, eve: Noun, lyf: Noun) -> Result { pub fn interpret_with_guard(context: &mut Context, eve: Noun, lyf: Noun) -> Result {
let stack_pp = context.stack.get_stack_pointer_pointer() as *const *mut u64; let stack_pp = context.stack.get_stack_pointer_pointer() as *const *const u64;
let alloc_pp = context.stack.get_alloc_pointer_pointer() as *const *mut u64; let alloc_pp = context.stack.get_alloc_pointer_pointer() as *const *const u64;
call_with_guard(stack_pp, alloc_pp, &mut || interpret(context, eve, lyf)) call_with_guard(stack_pp, alloc_pp, &mut || interpret(context, eve, lyf))
} }

View File

@ -32,13 +32,6 @@ fn indirect_raw_size(atom: IndirectAtom) -> usize {
atom.size() + 2 atom.size() + 2
} }
#[allow(dead_code)]
pub struct NockStackSnapshot {
frame_pointer: *mut u64,
stack_pointer: *mut u64,
alloc_pointer: *mut u64,
}
/** A stack for Nock computation, which supports stack allocation and delimited copying collection /** A stack for Nock computation, which supports stack allocation and delimited copying collection
* for returned nouns * for returned nouns
*/ */
@ -94,20 +87,6 @@ impl NockStack {
} }
} }
pub fn save(&self) -> NockStackSnapshot {
NockStackSnapshot {
frame_pointer: self.frame_pointer,
stack_pointer: self.stack_pointer,
alloc_pointer: self.alloc_pointer,
}
}
pub fn restore(&mut self, saved: &NockStackSnapshot) {
self.frame_pointer = saved.frame_pointer;
self.stack_pointer = saved.stack_pointer;
self.alloc_pointer = saved.alloc_pointer;
}
/** Resets the NockStack but flipping the top-frame polarity and unsetting PC. Sets the alloc /** Resets the NockStack but flipping the top-frame polarity and unsetting PC. Sets the alloc
* pointer to the "previous" alloc pointer stored in the top frame to keep things "preserved" * pointer to the "previous" alloc pointer stored in the top frame to keep things "preserved"
* from the top frame. This allows us to do a copying GC on the top frame without erroneously * from the top frame. This allows us to do a copying GC on the top frame without erroneously

View File

@ -18,7 +18,7 @@
static uintptr_t guard_p = 0; static uintptr_t guard_p = 0;
static const uintptr_t *stack_pp = NULL; static const uintptr_t *stack_pp = NULL;
static const uintptr_t *alloc_pp = NULL; static const uintptr_t *alloc_pp = NULL;
static jmp_buf env_buffer; static BufListNode *buffer_list = NULL;
static struct sigaction prev_sa; static struct sigaction prev_sa;
static int32_t static int32_t
@ -113,7 +113,7 @@ _signal_handler(int sig, siginfo_t *si, void *unused)
if (sig != SIGSEGV) { if (sig != SIGSEGV) {
fprintf(stderr, "guard: sig_handle: invalid signal\r\n"); fprintf(stderr, "guard: sig_handle: invalid signal\r\n");
// XX: do we even want to jump? if this is fatal error, maybe just die now // XX: do we even want to jump? if this is fatal error, maybe just die now
siglongjmp(env_buffer, guard_signal); siglongjmp(buffer_list->buffer, guard_signal);
} }
sig_addr = (uintptr_t)si->si_addr; sig_addr = (uintptr_t)si->si_addr;
@ -126,7 +126,7 @@ _signal_handler(int sig, siginfo_t *si, void *unused)
err = _focus_guard(); err = _focus_guard();
if (err) { if (err) {
fprintf(stderr, "guard: sig_handle: focus error\r\n"); fprintf(stderr, "guard: sig_handle: focus error\r\n");
siglongjmp(env_buffer, err); siglongjmp(buffer_list->buffer, err);
} }
} }
else { else {
@ -173,10 +173,11 @@ int32_t
guard( guard(
callback f, callback f,
void *closure, void *closure,
const uintptr_t *s_pp, const uintptr_t *const s_pp,
const uintptr_t *a_pp, const uintptr_t *const a_pp,
void ** ret void ** ret
) { ) {
BufListNode *new_buffer;
int32_t err = 0; int32_t err = 0;
int32_t td_err = 0; int32_t td_err = 0;
@ -184,6 +185,8 @@ guard(
fprintf(stderr, "guard: setup: alloc pointer at %p\r\n", (void *)(*a_pp)); fprintf(stderr, "guard: setup: alloc pointer at %p\r\n", (void *)(*a_pp));
if (guard_p == 0) { if (guard_p == 0) {
assert(buffer_list == NULL);
stack_pp = s_pp; stack_pp = s_pp;
alloc_pp = a_pp; alloc_pp = a_pp;
@ -198,26 +201,58 @@ guard(
fprintf(stderr, "guard: setup _register_handler error\r\n"); fprintf(stderr, "guard: setup _register_handler error\r\n");
goto clean; goto clean;
} }
} else {
assert(buffer_list != NULL);
} }
// Setup new longjmp buffer
new_buffer = (BufListNode *)malloc(sizeof(BufListNode));
if (new_buffer == NULL) {
fprintf(stderr, "guard: malloc error\r\n");
fprintf(stderr, "%s\r\n", strerror(errno));
err = guard_malloc | errno;
goto skip;
}
new_buffer->next = buffer_list;
buffer_list = new_buffer;
// Run given closure // Run given closure
fprintf(stderr, "guard: run\r\n"); fprintf(stderr, "guard: run\r\n");
if (!(err = sigsetjmp(env_buffer, 1))) { if (!(err = sigsetjmp(buffer_list->buffer, 1))) {
*ret = f(closure); *ret = f(closure);
} }
clean: // Restore previous longjmp buffer
// Unmark guard page buffer_list = buffer_list->next;
assert(guard_p != 0); free((void *)new_buffer);
td_err = _unmark_page((void *)guard_p);
if (td_err) { skip:
fprintf(stderr, "guard: unmark error\r\n"); // If no more guarded closures, then...
fprintf(stderr, "%s\r\n", strerror(errno)); if (buffer_list == NULL) {
if (!err) { // Remove new signal handler
err = td_err; if (sigaction(SIGSEGV, &prev_sa, NULL)) {
fprintf(stderr, "guard: sigaction error\r\n");
fprintf(stderr, "%s\r\n", strerror(errno));
td_err = guard_sigaction | errno;
if (!err) {
err = td_err;
}
} }
clean:
// Unmark guard page
assert(guard_p != 0);
td_err = _unmark_page((void *)guard_p);
if (td_err) {
fprintf(stderr, "guard: unmark error\r\n");
fprintf(stderr, "%s\r\n", strerror(errno));
if (!err) {
err = td_err;
}
}
guard_p = 0;
} }
guard_p = 0;
exit: exit:
fprintf(stderr, "guard: return\r\n"); fprintf(stderr, "guard: return\r\n");

View File

@ -4,6 +4,14 @@
#include <setjmp.h> #include <setjmp.h>
#include <stdint.h> #include <stdint.h>
/**
*
*/
typedef struct _buf_list_node {
jmp_buf buffer;
struct _buf_list_node *next;
} BufListNode;
/** /**
* Error codes and flags. * Error codes and flags.
* *
@ -52,8 +60,8 @@ int32_t
guard( guard(
callback f, callback f,
void *closure, void *closure,
const uintptr_t *s_pp, const uintptr_t *const s_pp,
const uintptr_t *a_pp, const uintptr_t *const a_pp,
void **ret void **ret
); );