1.0.26.7: use a signal for SIG_STOP_FOR_GC > SIGSEGV on Linux
[sbcl.git] / src / runtime / gencgc.c
index 5d687f4..3353425 100644 (file)
@@ -41,6 +41,7 @@
 #include "gc.h"
 #include "gc-internal.h"
 #include "thread.h"
+#include "pseudo-atomic.h"
 #include "alloc.h"
 #include "genesis/vector.h"
 #include "genesis/weak-pointer.h"
@@ -1171,7 +1172,9 @@ gc_heap_exhausted_error_or_lose (long available, long requested)
         fprintf(stderr, "GC control variables:\n");
         fprintf(stderr, "          *GC-INHIBIT* = %s\n          *GC-PENDING* = %s\n",
                 SymbolValue(GC_INHIBIT,thread)==NIL ? "false" : "true",
-                SymbolValue(GC_PENDING,thread)==NIL ? "false" : "true");
+                (SymbolValue(GC_PENDING, thread) == T) ?
+                "true" : ((SymbolValue(GC_PENDING, thread) == NIL) ?
+                  "false" : "in progress"));
 #ifdef LISP_FEATURE_SB_THREAD
         fprintf(stderr, " *STOP-FOR-GC-PENDING* = %s\n",
                 SymbolValue(STOP_FOR_GC_PENDING,thread)==NIL ? "false" : "true");
@@ -4720,8 +4723,17 @@ general_alloc_internal(long nbytes, int page_type_flag, struct alloc_region *reg
             /* set things up so that GC happens when we finish the PA
              * section */
             SetSymbolValue(GC_PENDING,T,thread);
-            if (SymbolValue(GC_INHIBIT,thread) == NIL)
-              set_pseudo_atomic_interrupted(thread);
+            if (SymbolValue(GC_INHIBIT,thread) == NIL) {
+                set_pseudo_atomic_interrupted(thread);
+#ifdef LISP_FEATURE_PPC
+                /* PPC calls alloc() from a trap, look up the most
+                 * recent one and frob that. */
+                maybe_save_gc_mask_and_block_deferrables
+                    (get_interrupt_context_for_thread(thread));
+#else
+                maybe_save_gc_mask_and_block_deferrables(NULL);
+#endif
+            }
         }
     }
     new_obj = gc_alloc_with_region(nbytes, page_type_flag, region, 0);
@@ -4731,7 +4743,7 @@ general_alloc_internal(long nbytes, int page_type_flag, struct alloc_region *reg
     if ((alloc_signal & FIXNUM_TAG_MASK) == 0) {
         if ((signed long) alloc_signal <= 0) {
             SetSymbolValue(ALLOC_SIGNAL, T, thread);
-            thread_kill(thread->os_thread, SIGPROF);
+            raise(SIGPROF);
         } else {
             SetSymbolValue(ALLOC_SIGNAL,
                            alloc_signal - (1 << N_FIXNUM_TAG_BITS),
@@ -4812,6 +4824,9 @@ gencgc_handle_wp_violation(void* fault_addr)
         return 0;
 
     } else {
+        int ret;
+        ret = thread_mutex_lock(&free_pages_lock);
+        gc_assert(ret == 0);
         if (page_table[page_index].write_protected) {
             /* Unprotect the page. */
             os_protect(page_address(page_index), PAGE_BYTES, OS_VM_PROT_ALL);
@@ -4829,6 +4844,8 @@ gencgc_handle_wp_violation(void* fault_addr)
                      page_index, boxed_region.first_page,
                      boxed_region.last_page);
         }
+        ret = thread_mutex_unlock(&free_pages_lock);
+        gc_assert(ret == 0);
         /* Don't worry, we can handle it. */
         return 1;
     }