* gc.h, gc.c (scm_gc_sweep): Issue deprecation warning when
[bpt/guile.git] / libguile / continuations.c
index 5ef2219..efc96de 100644 (file)
@@ -1,4 +1,4 @@
-/*     Copyright (C) 1995,1996,1998, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1998,2000,2001 Free Software Foundation, Inc.
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * whether to permit this exception to apply to your modifications.
  * If you do not wish that, delete this exception notice.  */
 
-/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
-   gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
 
 \f
 
-#include <stdio.h>
+#include <string.h>
+
 #include "libguile/_scm.h"
 #include "libguile/root.h"
 #include "libguile/stackchk.h"
@@ -57,6 +56,7 @@
 #include "libguile/debug.h"
 #endif
 
+#include "libguile/validate.h"
 #include "libguile/continuations.h"
 
 \f
 /* {Continuations}
  */
 
-scm_bits_t scm_tc16_continuation;
+scm_t_bits scm_tc16_continuation;
 
-static SCM continuation_mark (SCM obj)
+static SCM
+continuation_mark (SCM obj)
 {
-  scm_contregs *continuation = SCM_CONTREGS (obj);
+  scm_t_contregs *continuation = SCM_CONTREGS (obj);
 
   scm_gc_mark (continuation->throw_value);
   scm_mark_locations (continuation->stack, continuation->num_stack_items);
+#ifdef __ia64__
+  if (continuation->backing_store)
+    scm_mark_locations (continuation->backing_store, 
+                        continuation->backing_store_size / 
+                        sizeof (SCM_STACKITEM));
+#endif /* __ia64__ */
   return continuation->dynenv;
 }
 
-static scm_sizet continuation_free (SCM obj)
+static size_t
+continuation_free (SCM obj)
 {
-  scm_contregs *continuation = SCM_CONTREGS (obj);
+  scm_t_contregs *continuation = SCM_CONTREGS (obj);
   /* stack array size is 1 if num_stack_items is 0 (rootcont).  */
-  scm_sizet extra_items = (continuation->num_stack_items > 0)
+  size_t extra_items = (continuation->num_stack_items > 0)
     ? (continuation->num_stack_items - 1)
     : 0;
-  scm_sizet bytes_free = sizeof (scm_contregs)
+  size_t bytes_free = sizeof (scm_t_contregs)
     + extra_items * sizeof (SCM_STACKITEM);
-  
-  scm_must_free (continuation);
-  return bytes_free;
+
+#ifdef __ia64__
+  scm_gc_free (continuation->backing_store, continuation->backing_store_size,
+              "continuation backing store");
+#endif /* __ia64__ */ 
+  scm_gc_free (continuation, bytes_free, "continuation");
+  return 0;
 }
 
-static int continuation_print (SCM obj, SCM port, scm_print_state *state)
+static int
+continuation_print (SCM obj, SCM port, scm_print_state *state SCM_UNUSED)
 {
-  scm_contregs *continuation = SCM_CONTREGS (obj);
+  scm_t_contregs *continuation = SCM_CONTREGS (obj);
 
   scm_puts ("#<continuation ", port);
   scm_intprint (continuation->num_stack_items, 10, port);
@@ -101,6 +114,19 @@ static int continuation_print (SCM obj, SCM port, scm_print_state *state)
   return 1;
 }
 
+#ifdef __ia64__
+/* Extern declaration of getcontext()/setcontext() in order to redefine
+   getcontext() since on ia64-linux the second return value indicates whether
+   it returned from getcontext() itself or by running setcontext(). */
+struct rv
+{
+  long retval;
+  long first_return;
+};
+extern struct rv getcontext (ucontext_t *);
+extern int setcontext (ucontext_t *);
+#endif /* __ia64__ */
+
 /* this may return more than once: the first time with the escape
    procedure, then subsequently with the value to be passed to the
    continuation.  */
@@ -108,18 +134,21 @@ static int continuation_print (SCM obj, SCM port, scm_print_state *state)
 SCM 
 scm_make_continuation (int *first)
 {
-  SCM cont;
-  scm_contregs *continuation;
-  scm_contregs *rootcont = SCM_CONTREGS (scm_rootcont);
+  volatile SCM cont;
+  scm_t_contregs *continuation;
+  scm_t_contregs *rootcont = SCM_CONTREGS (scm_rootcont);
   long stack_size;
   SCM_STACKITEM * src;
+#ifdef __ia64__
+  struct rv rv;
+#endif /* __ia64__ */
 
   SCM_ENTER_A_SECTION;
   SCM_FLUSH_REGISTER_WINDOWS;
   stack_size = scm_stack_size (rootcont->base);
-  continuation = scm_must_malloc (sizeof (scm_contregs)
-                                 + (stack_size - 1) * sizeof (SCM_STACKITEM),
-                                 FUNC_NAME);
+  continuation = scm_gc_malloc (sizeof (scm_t_contregs)
+                               + (stack_size - 1) * sizeof (SCM_STACKITEM),
+                               "continuation");
   continuation->num_stack_items = stack_size;
   continuation->dynenv = scm_dynwinds;
   continuation->throw_value = SCM_EOL;
@@ -136,16 +165,44 @@ scm_make_continuation (int *first)
 #endif
   memcpy (continuation->stack, src, sizeof (SCM_STACKITEM) * stack_size);
 
+#ifdef __ia64__
+  rv = getcontext (&continuation->ctx);
+  if (rv.first_return)
+    {
+      continuation->backing_store_size = 
+        continuation->ctx.uc_mcontext.sc_ar_bsp - 
+        (unsigned long) __libc_ia64_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 *) __libc_ia64_register_backing_store_base, 
+              continuation->backing_store_size);
+      *first = 1;
+      return cont;
+    }
+  else
+    {
+      SCM ret = continuation->throw_value;
+      *first = 0;
+      continuation->throw_value = SCM_BOOL_F;
+      return ret;
+    }
+#else /* !__ia64__ */
   if (setjmp (continuation->jmpbuf))
     {
+      SCM ret = continuation->throw_value;
       *first = 0;
-      return continuation->throw_value;
+      continuation->throw_value = SCM_BOOL_F;
+      return ret;
     }
   else
     {
       *first = 1;
       return cont;
     }
+#endif /* !__ia64__ */
 }
 #undef FUNC_NAME
 
@@ -158,14 +215,14 @@ static void scm_dynthrow (SCM, SCM);
  * variable.
  */
 
-scm_bits_t scm_i_dummy;
+scm_t_bits scm_i_dummy;
 
 static void 
 grow_stack (SCM cont, SCM val)
 {
-  scm_bits_t growth[100];
+  scm_t_bits growth[100];
 
-  scm_i_dummy = (scm_bits_t) growth;
+  scm_i_dummy = (scm_t_bits) growth;
   scm_dynthrow (cont, val);
 }
 
@@ -175,7 +232,7 @@ grow_stack (SCM cont, SCM val)
  * own frame are overwritten.  Thus, memcpy can be used for best performance.
  */
 static void
-copy_stack_and_call (scm_contregs *continuation, SCM val, 
+copy_stack_and_call (scm_t_contregs *continuation, SCM val, 
                     SCM_STACKITEM * dst)
 {
   memcpy (dst, continuation->stack,
@@ -186,7 +243,14 @@ copy_stack_and_call (scm_contregs *continuation, SCM val,
 #endif
 
   continuation->throw_value = val;
+#ifdef __ia64__
+  memcpy ((void *) __libc_ia64_register_backing_store_base,
+          continuation->backing_store,
+          continuation->backing_store_size);
+  setcontext (&continuation->ctx);
+#else
   longjmp (continuation->jmpbuf, 1);
+#endif
 }
 
 
@@ -197,7 +261,7 @@ copy_stack_and_call (scm_contregs *continuation, SCM val,
 static void 
 scm_dynthrow (SCM cont, SCM val)
 {
-  scm_contregs *continuation = SCM_CONTREGS (cont);
+  scm_t_contregs *continuation = SCM_CONTREGS (cont);
   SCM_STACKITEM * dst = SCM_BASE (scm_rootcont);
   SCM_STACKITEM stack_top_element;
 
@@ -214,27 +278,32 @@ scm_dynthrow (SCM cont, SCM val)
   copy_stack_and_call (continuation, val, dst);
 }
 
+
+static SCM
+continuation_apply (SCM cont, SCM args)
 #define FUNC_NAME "continuation_apply"
-static SCM continuation_apply (SCM cont, SCM args)
 {
-  scm_contregs *continuation = SCM_CONTREGS (cont);
-  scm_contregs *rootcont = SCM_CONTREGS (scm_rootcont);
+  scm_t_contregs *continuation = SCM_CONTREGS (cont);
+  scm_t_contregs *rootcont = SCM_CONTREGS (scm_rootcont);
 
   if (continuation->seq != rootcont->seq
       /* this base comparison isn't needed */
       || continuation->base != rootcont->base)
     {
-      scm_wta (cont, "continuation from wrong top level", FUNC_NAME);
+      SCM_MISC_ERROR ("continuation from wrong top level: ~S", 
+                     scm_list_1 (cont));
     }
   
   scm_dowinds (continuation->dynenv,
-              scm_ilength (scm_dynwinds) - continuation->dynenv);
+              scm_ilength (scm_dynwinds)
+              - scm_ilength (continuation->dynenv));
   
   scm_dynthrow (cont, scm_values (args));
   return SCM_UNSPECIFIED; /* not reached */
 }
 #undef FUNC_NAME
 
+
 void
 scm_init_continuations ()
 {
@@ -243,7 +312,6 @@ scm_init_continuations ()
   scm_set_smob_free (scm_tc16_continuation, continuation_free);
   scm_set_smob_print (scm_tc16_continuation, continuation_print);
   scm_set_smob_apply (scm_tc16_continuation, continuation_apply, 0, 0, 1);
-  
 #ifndef SCM_MAGIC_SNARFER
 #include "libguile/continuations.x"
 #endif