1.0.41.15: gencgc: Implement object pinning for non-x86oids.
[sbcl.git] / src / runtime / interrupt.c
index 4f33522..123a576 100644 (file)
@@ -1242,6 +1242,12 @@ sig_stop_for_gc_handler(int signal, siginfo_t *info, os_context_t *context)
     set_thread_state(thread,STATE_SUSPENDED);
     FSHOW_SIGNAL((stderr,"suspended\n"));
 
+    /* While waiting for gc to finish occupy ourselves with zeroing
+     * the unused portion of the control stack to reduce conservatism.
+     * On hypothetic platforms with threads and exact gc it is
+     * actually a must. */
+    scrub_control_stack();
+
     wait_for_thread_state_change(thread, STATE_SUSPENDED);
     FSHOW_SIGNAL((stderr,"resumed\n"));
 
@@ -1265,7 +1271,7 @@ interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context)
         || (signal == SIGEMT)
 #endif
         )
-        corruption_warning_and_maybe_lose("Signal %d recieved", signal);
+        corruption_warning_and_maybe_lose("Signal %d received", signal);
 #endif
     interrupt_handle_now(signal, info, context);
     RESTORE_ERRNO;
@@ -1479,6 +1485,37 @@ undefined_alien_function(void)
     funcall0(StaticSymbolFunction(UNDEFINED_ALIEN_FUNCTION_ERROR));
 }
 
+void lower_thread_control_stack_guard_page(struct thread *th)
+{
+    protect_control_stack_guard_page(0, th);
+    protect_control_stack_return_guard_page(1, th);
+    th->control_stack_guard_page_protected = NIL;
+    fprintf(stderr, "INFO: Control stack guard page unprotected\n");
+}
+
+void reset_thread_control_stack_guard_page(struct thread *th)
+{
+    memset(CONTROL_STACK_GUARD_PAGE(th), 0, os_vm_page_size);
+    protect_control_stack_guard_page(1, th);
+    protect_control_stack_return_guard_page(0, th);
+    th->control_stack_guard_page_protected = T;
+    fprintf(stderr, "INFO: Control stack guard page reprotected\n");
+}
+
+/* Called from the REPL, too. */
+void reset_control_stack_guard_page(void)
+{
+    struct thread *th=arch_os_get_current_thread();
+    if (th->control_stack_guard_page_protected == NIL) {
+        reset_thread_control_stack_guard_page(th);
+    }
+}
+
+void lower_control_stack_guard_page(void)
+{
+    lower_thread_control_stack_guard_page(arch_os_get_current_thread());
+}
+
 boolean
 handle_guard_page_triggered(os_context_t *context,os_vm_address_t addr)
 {
@@ -1494,10 +1531,9 @@ handle_guard_page_triggered(os_context_t *context,os_vm_address_t addr)
          * protection so the error handler has some headroom, protect the
          * previous page so that we can catch returns from the guard page
          * and restore it. */
-        protect_control_stack_guard_page(0, NULL);
-        protect_control_stack_return_guard_page(1, NULL);
-        fprintf(stderr, "INFO: Control stack guard page unprotected\n");
-
+        if (th->control_stack_guard_page_protected == NIL)
+            lose("control_stack_guard_page_protected NIL");
+        lower_control_stack_guard_page();
 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
         /* For the unfortunate case, when the control stack is
          * exhausted in a signal handler. */
@@ -1513,9 +1549,9 @@ handle_guard_page_triggered(os_context_t *context,os_vm_address_t addr)
          * unprotect this one. This works even if we somehow missed
          * the return-guard-page, and hit it on our way to new
          * exhaustion instead. */
-        protect_control_stack_guard_page(1, NULL);
-        protect_control_stack_return_guard_page(0, NULL);
-        fprintf(stderr, "INFO: Control stack guard page reprotected\n");
+        if (th->control_stack_guard_page_protected != NIL)
+            lose("control_stack_guard_page_protected not NIL");
+        reset_control_stack_guard_page();
         return 1;
     }
     else if(addr >= BINDING_STACK_HARD_GUARD_PAGE(th) &&