0.9.1.33:
[sbcl.git] / src / runtime / gencgc.c
index b7666e7..45a3a1e 100644 (file)
@@ -4142,24 +4142,33 @@ alloc(long nbytes)
      * we should GC in the near future
      */
     if (auto_gc_trigger && bytes_allocated > auto_gc_trigger) {
-       /* set things up so that GC happens when we finish the PA
-        * section.  We only do this if there wasn't a pending handler
-        * already, in case it was a gc.  If it wasn't a GC, the next
-        * allocation will get us back to this point anyway, so no harm done
-        */
-       sigset_t new_mask,old_mask;
-       sigemptyset(&new_mask);
-       sigaddset_blockable(&new_mask);
-       sigprocmask(SIG_BLOCK,&new_mask,&old_mask);
-
-       struct interrupt_data *data=th->interrupt_data;
-       if((!data->pending_handler) &&
-           maybe_defer_handler(interrupt_maybe_gc_int,data,0,0,0)) {
-            /* Leave the signals blocked just as if it was deferred
-             * the normal way and set the pending_mask. */
-            sigcopyset(&(data->pending_mask),&old_mask);
-        } else {
-            sigprocmask(SIG_SETMASK,&old_mask,0);
+        struct thread *thread=arch_os_get_current_thread();
+        /* Don't flood the system with interrupts if the need to gc is
+         * already noted. This can happen for example when SUB-GC
+         * allocates or after a gc triggered in a WITHOUT-GCING. */
+        if (SymbolValue(NEED_TO_COLLECT_GARBAGE,thread) == NIL) {
+            /* set things up so that GC happens when we finish the PA
+             * section.  We only do this if there wasn't a pending
+             * handler already, in case it was a gc.  If it wasn't a
+             * GC, the next allocation will get us back to this point
+             * anyway, so no harm done
+             */
+            sigset_t new_mask,old_mask;
+            sigemptyset(&new_mask);
+            sigaddset_blockable(&new_mask);
+            sigprocmask(SIG_BLOCK,&new_mask,&old_mask);
+
+            struct interrupt_data *data=th->interrupt_data;
+            if((!data->pending_handler) &&
+               maybe_defer_handler(interrupt_maybe_gc_int,data,0,0,0)) {
+                /* Leave the signals blocked just as if it was
+                 * deferred the normal way and set the
+                 * pending_mask. */
+                sigcopyset(&(data->pending_mask),&old_mask);
+                SetSymbolValue(NEED_TO_COLLECT_GARBAGE,T,thread);
+            } else {
+                sigprocmask(SIG_SETMASK,&old_mask,0);
+            }
         }
     }
     new_obj = gc_alloc_with_region(nbytes,0,region,0);