diff options
author | Andy Wingo <wingo@pobox.com> | 2018-06-17 13:03:39 +0200 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2018-06-17 13:41:03 +0200 |
commit | f84ce5442e2602b6a41c48f596728d32d0aa8e47 (patch) | |
tree | 0679134bc6d2581d3eb7ddab8c009dcf7c0fa300 /libguile/continuations.c | |
parent | 574f67d1b6e3b89171c7df8f043fc3891bd8a870 (diff) | |
download | guile-f84ce5442e2602b6a41c48f596728d32d0aa8e47.tar.gz |
Refactor handling of auxiliary stacks and setjmp/longjmp
* libguile/__scm.h (scm_i_jmp_buf): Remove definition, which was a shim
for ia64. Instead, always use setjmp/longjmp and jmp_buf.
* libguile/_scm.h (SCM_I_SETJMP, SCM_I_LONGJMP): Remove; instead use
setjmp and longjmp.
* libguile/continuations.c (capture_auxiliary_stack):
(restore_auxiliary_stack): New helpers.
(scm_i_make_continuation): Use capture_auxiliary_stack.
(copy_stack_and_call): Use restore_auxiliary_stack. No need to stash
the aux stack on the thread, either.
* libguile/continuations.h (scm_t_contregs): Use
SCM_HAVE_AUXILIARY_STACK to flag when to have an auxiliary_stack
member.
* libguile/control.h:
* libguile/control.c (reify_partial_continuation, scm_c_abort):
(scm_suspendable_continuation_p): Adapt to use setjmp/longjmp
directly.
* libguile/deprecated.h: Add deprecated scm_i_jmp_buf define.
* libguile/dynstack.h:
* libguile/dynstack.c (PROMPT_JMPBUF):
(scm_dynstack_push_prompt, scm_dynstack_find_prompt):
(scm_dynstack_wind_prompt): Adapt to jmp_buf type.
* libguile/eval.c (eval): Use jmp_buf and setjmp directly.
* libguile/gc-malloc.c: No need for ia64-specific things.
* libguile/gc.c: No need for ia64-specific things.
* libguile/gc.h: No need to declare scm_ia64_ar_bsp.
* libguile/init.c: Remove typedef of setjmp_type for Cray, unused.
* libguile/threads.c (guilify_self_1): No more pending_rbs_continuation
in scm_i_thread, and register_backing_store_base is handled by libgc.
(scm_ia64_ar_bsp): Remove definitions; inlined into continuations.c's
capture_auxiliary_stack.
* libguile/threads.h (scm_i_thread): jmpbuf member is plain jmp_buf.
* libguile/throw.c (catch): Just use jmp_buf and setjmp.
* libguile/vm-engine.c (VM_NAME): Adapt prototype to take jmp_buf
pointer.
* libguile/vm.c (vm_abort): Adapt jmp_buf types.
(scm_call_n): Use setjmp.
Diffstat (limited to 'libguile/continuations.c')
-rw-r--r-- | libguile/continuations.c | 90 |
1 files changed, 52 insertions, 38 deletions
diff --git a/libguile/continuations.c b/libguile/continuations.c index b917f6097..84cd2ee67 100644 --- a/libguile/continuations.c +++ b/libguile/continuations.c @@ -26,6 +26,10 @@ #include <string.h> #include <stdio.h> +#if SCM_HAVE_AUXILIARY_STACK +#include <ucontext.h> +#endif + #include "libguile/_scm.h" #include "libguile/async.h" #include "libguile/backtrace.h" @@ -112,6 +116,49 @@ continuation_print (SCM obj, SCM port, scm_print_state *state SCM_UNUSED) # define SCM_FLUSH_REGISTER_WINDOWS /* empty */ #endif +static void +capture_auxiliary_stack (scm_i_thread *thread, scm_t_contregs *continuation) +{ +#if SCM_HAVE_AUXILIARY_STACK +# ifndef __ia64__ +# error missing auxiliary stack implementation for architecture +# endif + char *top; + ucontext_t ctx; + + if (getcontext (&ctx) != 0) + abort (); + +#if defined __hpux + __uc_get_ar_bsp (ctx, (uint64_t *) &top); +#elif defined linux + top = (char *) ctx->uc_mcontext.sc_ar_bsp; +#elif defined __FreeBSD__ + top = (char *)(ctx->uc_mcontext.mc_special.bspstore + + ctx->uc_mcontext.mc_special.ndirty); +#else +#error missing auxiliary stack implementation for ia64 on this OS +#endif + + continuation->auxiliary_stack_size = + top - (char *) thread->auxiliary_stack_base; + continuation->auxiliary_stack = + scm_gc_malloc (continuation->auxiliary_stack_size, + "continuation auxiliary stack"); + memcpy (continuation->auxiliary_stack, thread->auxiliary_stack_base, + continuation->auxiliary_stack_size); +#endif /* SCM_HAVE_AUXILIARY_STACK */ +} + +static void +restore_auxiliary_stack (scm_i_thread *thread, scm_t_contregs *continuation) +{ +#if SCM_HAVE_AUXILIARY_STACK + memcpy (thread->auxiliary_stack_base, continuation->auxiliary_stack, + continuation->auxiliary_stack_size); +#endif +} + /* this may return more than once: the first time with the escape procedure, then subsequently with SCM_UNDEFINED (the vals already having been placed on the VM stack). */ @@ -142,27 +189,13 @@ scm_i_make_continuation (int *first, struct scm_vm *vp, SCM vm_cont) continuation->vp = vp; continuation->vm_cont = vm_cont; saved_cookie = vp->resumable_prompt_cookie; + capture_auxiliary_stack (thread, continuation); SCM_NEWSMOB (cont, tc16_continuation, continuation); - *first = !SCM_I_SETJMP (continuation->jmpbuf); + *first = !setjmp (continuation->jmpbuf); if (*first) - { -#ifdef __ia64__ - continuation->backing_store_size = - (char *) scm_ia64_ar_bsp(&continuation->jmpbuf.ctx) - - - (char *) thread->register_backing_store_base; - continuation->backing_store = NULL; - continuation->backing_store = - scm_gc_malloc (continuation->backing_store_size, - "continuation backing store"); - memcpy (continuation->backing_store, - (void *) thread->register_backing_store_base, - continuation->backing_store_size); -#endif /* __ia64__ */ - return make_continuation_trampoline (cont); - } + return make_continuation_trampoline (cont); else { vp->resumable_prompt_cookie = saved_cookie; @@ -264,31 +297,12 @@ copy_stack_and_call (scm_t_contregs *continuation, memcpy (dst, continuation->stack, sizeof (SCM_STACKITEM) * continuation->num_stack_items); -#ifdef __ia64__ - thread->pending_rbs_continuation = continuation; -#endif + restore_auxiliary_stack (thread, continuation); scm_dynstack_wind (&thread->dynstack, joint); - SCM_I_LONGJMP (continuation->jmpbuf, 1); -} - -#ifdef __ia64__ -void -scm_ia64_longjmp (scm_i_jmp_buf *JB, int VAL) -{ - scm_i_thread *t = SCM_I_CURRENT_THREAD; - - if (t->pending_rbs_continuation) - { - memcpy (t->register_backing_store_base, - t->pending_rbs_continuation->backing_store, - t->pending_rbs_continuation->backing_store_size); - t->pending_rbs_continuation = NULL; - } - setcontext (&JB->ctx); + longjmp (continuation->jmpbuf, 1); } -#endif /* Call grow_stack until the stack space is large enough, then, as the current * stack frame might get overwritten, let copy_stack_and_call perform the |