summaryrefslogtreecommitdiff
path: root/libguile/continuations.c
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2018-06-17 13:03:39 +0200
committerAndy Wingo <wingo@pobox.com>2018-06-17 13:41:03 +0200
commitf84ce5442e2602b6a41c48f596728d32d0aa8e47 (patch)
tree0679134bc6d2581d3eb7ddab8c009dcf7c0fa300 /libguile/continuations.c
parent574f67d1b6e3b89171c7df8f043fc3891bd8a870 (diff)
downloadguile-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.c90
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