continuations.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /* Copyright (C) 1995,1996,1998, 2000, 2002 Free Software Foundation, Inc.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2, or (at your option)
  6. * any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; see the file COPYING. If not, write to
  15. * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. * Boston, MA 02111-1307 USA
  17. *
  18. * As a special exception, the Free Software Foundation gives permission
  19. * for additional uses of the text contained in its release of GUILE.
  20. *
  21. * The exception is that, if you link the GUILE library with other files
  22. * to produce an executable, this does not by itself cause the
  23. * resulting executable to be covered by the GNU General Public License.
  24. * Your use of that executable is in no way restricted on account of
  25. * linking the GUILE library code into it.
  26. *
  27. * This exception does not however invalidate any other reasons why
  28. * the executable file might be covered by the GNU General Public License.
  29. *
  30. * This exception applies only to the code released by the
  31. * Free Software Foundation under the name GUILE. If you copy
  32. * code from other Free Software Foundation releases into a copy of
  33. * GUILE, as the General Public License permits, the exception does
  34. * not apply to the code that you add in this way. To avoid misleading
  35. * anyone as to the status of such modified files, you must delete
  36. * this exception notice from them.
  37. *
  38. * If you write modifications of your own for GUILE, it is your choice
  39. * whether to permit this exception to apply to your modifications.
  40. * If you do not wish that, delete this exception notice. */
  41. #include <stdio.h>
  42. #include "libguile/_scm.h"
  43. #include "libguile/root.h"
  44. #include "libguile/stackchk.h"
  45. #ifdef DEBUG_EXTENSIONS
  46. #include "libguile/debug.h"
  47. #endif
  48. #include "libguile/dynwind.h"
  49. #include "libguile/continuations.h"
  50. /* {Continuations}
  51. */
  52. static char s_cont[] = "continuation";
  53. static void scm_dynthrow (SCM, SCM);
  54. #ifndef CHEAP_CONTINUATIONS
  55. SCM
  56. scm_make_cont (SCM *answer)
  57. {
  58. long j;
  59. SCM cont;
  60. SCM_STACKITEM * src;
  61. SCM_STACKITEM * dst;
  62. SCM_NEWCELL (cont);
  63. *answer = cont;
  64. SCM_ENTER_A_SECTION;
  65. SCM_FLUSH_REGISTER_WINDOWS;
  66. j = scm_stack_size (SCM_BASE (scm_rootcont));
  67. SCM_SET_CONTREGS (cont,
  68. scm_must_malloc (sizeof (scm_contregs)
  69. + j * sizeof (SCM_STACKITEM),
  70. s_cont));
  71. SCM_DYNENV (cont) = scm_dynwinds;
  72. SCM_THROW_VALUE (cont) = SCM_EOL;
  73. src = SCM_BASE (cont) = SCM_BASE (scm_rootcont);
  74. SCM_SEQ (cont) = SCM_SEQ (scm_rootcont);
  75. SCM_SETLENGTH (cont, j, scm_tc7_contin);
  76. SCM_EXIT_A_SECTION;
  77. #ifndef SCM_STACK_GROWS_UP
  78. src -= SCM_LENGTH (cont);
  79. #endif /* ndef SCM_STACK_GROWS_UP */
  80. dst = (SCM_STACKITEM *) (SCM_CHARS (cont) + sizeof (scm_contregs));
  81. /* memcpy should be safe: src and dst will never overlap */
  82. memcpy (dst, src, sizeof (SCM_STACKITEM) * SCM_LENGTH (cont));
  83. #ifdef DEBUG_EXTENSIONS
  84. SCM_DFRAME (cont) = scm_last_debug_frame;
  85. #endif
  86. return cont;
  87. }
  88. /* Grow the stack by a fixed amount to provide space to copy in the
  89. * continuation. Possibly this function has to be called several times
  90. * recursively before enough space is available. Make sure the compiler does
  91. * not optimize the growth array away by storing it's address into a global
  92. * variable.
  93. */
  94. scm_bits_t scm_i_dummy;
  95. static void
  96. grow_stack (SCM cont, SCM val)
  97. {
  98. scm_bits_t growth[100];
  99. scm_i_dummy = (scm_bits_t) growth;
  100. scm_dynthrow (cont, val);
  101. }
  102. /* Copy the continuation stack into the current stack. Calling functions from
  103. * within this function is safe, since only stack frames below this function's
  104. * own frame are overwritten. Thus, memcpy can be used for best performance.
  105. */
  106. static void
  107. copy_stack_and_call (SCM cont, SCM val,
  108. SCM_STACKITEM * src, SCM_STACKITEM * dst)
  109. {
  110. /* memcpy should be safe: src and dst will never overlap */
  111. memcpy (dst, src, sizeof (SCM_STACKITEM) * SCM_LENGTH (cont));
  112. #ifdef DEBUG_EXTENSIONS
  113. scm_last_debug_frame = SCM_DFRAME (cont);
  114. #endif
  115. SCM_THROW_VALUE (cont) = val;
  116. longjmp (SCM_JMPBUF (cont), 1);
  117. }
  118. /* Call grow_stack until the stack space is large enough, then, as the current
  119. * stack frame might get overwritten, let copy_stack_and_call perform the
  120. * actual copying and continuation calling.
  121. */
  122. static void
  123. scm_dynthrow (SCM cont, SCM val)
  124. {
  125. SCM_STACKITEM * src;
  126. SCM_STACKITEM * dst = SCM_BASE (scm_rootcont);
  127. SCM_STACKITEM stack_top_element;
  128. #ifdef SCM_STACK_GROWS_UP
  129. if (SCM_PTR_GE (dst + SCM_LENGTH (cont), & stack_top_element))
  130. grow_stack (cont, val);
  131. #else
  132. dst -= SCM_LENGTH (cont);
  133. if (SCM_PTR_LE (dst, & stack_top_element))
  134. grow_stack (cont, val);
  135. #endif /* def SCM_STACK_GROWS_UP */
  136. SCM_FLUSH_REGISTER_WINDOWS;
  137. src = (SCM_STACKITEM *) (SCM_CHARS (cont) + sizeof (scm_contregs));
  138. copy_stack_and_call (cont, val, src, dst);
  139. }
  140. #else /* ifndef CHEAP_CONTINUATIONS */
  141. /* Dirk:FIXME:: It seems that nobody has ever tried to use this code, since it
  142. * contains syntactic errors and thus would not have compiled anyway.
  143. */
  144. SCM
  145. scm_make_cont (SCM *answer)
  146. {
  147. SCM cont;
  148. SCM_NEWCELL (cont);
  149. *answer = cont;
  150. SCM_ENTER_A_SECTION;
  151. SCM_SET_CONTREGS (cont, scm_must_malloc (sizeof (scm_contregs), s_cont));
  152. SCM_DYNENV (cont) = scm_dynwinds;
  153. SCM_THROW_VALUE = SCM_EOL;
  154. SCM_BASE (cont) = SCM_BASE (rootcont);
  155. SCM_SEQ (cont) = SCM_SEQ (rootcont);
  156. SCM_SETCAR (cont, scm_tc7_contin);
  157. SCM_EXIT_A_SECTION;
  158. #ifdef DEBUG_EXTENSIONS
  159. SCM_DFRAME (cont) = scm_last_debug_frame;
  160. #endif
  161. return cont;
  162. }
  163. static void
  164. scm_dynthrow (SCM cont, SCM val)
  165. {
  166. #ifdef DEBUG_EXTENSIONS
  167. scm_last_debug_frame = SCM_DFRAME (cont);
  168. #endif
  169. SCM_THROW_VALUE (cont) = val;
  170. longjmp (SCM_JMPBUF (cont), 1);
  171. }
  172. #endif
  173. SCM
  174. scm_call_continuation (SCM cont, SCM val)
  175. {
  176. if ((SCM_SEQ (cont) != SCM_SEQ (scm_rootcont))
  177. || (SCM_BASE (cont) != SCM_BASE (scm_rootcont)))
  178. /* base compare not needed */
  179. scm_wta (cont, "continuation from wrong top level", s_cont);
  180. scm_dowinds (SCM_DYNENV (cont),
  181. scm_ilength (scm_dynwinds) - scm_ilength (SCM_DYNENV (cont)));
  182. scm_dynthrow (cont, val);
  183. return SCM_UNSPECIFIED; /* not reached */
  184. }
  185. void
  186. scm_init_continuations ()
  187. {
  188. #include "libguile/continuations.x"
  189. }
  190. /*
  191. Local Variables:
  192. c-file-style: "gnu"
  193. End:
  194. */