0.9.1.33:
authorGabor Melis <mega@hotpop.com>
Thu, 9 Jun 2005 08:32:29 +0000 (08:32 +0000)
committerGabor Melis <mega@hotpop.com>
Thu, 9 Jun 2005 08:32:29 +0000 (08:32 +0000)
        * gencgc: don't flood the system with gc interrupts if not
          absolutely necessary
        * fix compilation on freebsd

src/code/gc.lisp
src/compiler/x86-64/parms.lisp
src/compiler/x86/parms.lisp
src/runtime/gencgc.c
src/runtime/interrupt.c
version.lisp-expr

index af6a759..f90150f 100644 (file)
@@ -210,6 +210,9 @@ environment these hooks may run in any thread.")
 (defun sub-gc (&key (gen 0))
   (unless (eql (sb!thread:current-thread-id)
               (sb!thread::mutex-value *already-in-gc*))
+    ;; With gencgc, unless *NEED-TO-COLLECT-GARBAGE* every allocation
+    ;; in this function triggers another gc, potentially exceeding
+    ;; maximum interrupt nesting.
     (setf *need-to-collect-garbage* t)
     (when (zerop *gc-inhibit*)
       (sb!thread:with-mutex (*already-in-gc*)
@@ -234,7 +237,9 @@ environment these hooks may run in any thread.")
            (when (plusp freed)
              (incf *n-bytes-freed-or-purified* freed)))
          (sb!thread::reap-dead-threads)))
-      ;; Outside the mutex, these may cause another GC.
+      ;; Outside the mutex, these may cause another GC. FIXME: it can
+      ;; potentially exceed maximum interrupt nesting by triggering
+      ;; GCs.
       (run-pending-finalizers)
       (dolist (hook *after-gc-hooks*)
        (handler-case
index 740c173..d03dc9b 100644 (file)
     *control-stack-start*
     *control-stack-end*
 
+    *need-to-collect-garbage*
+
     ;; the floating point constants
     *fp-constant-0d0*
     *fp-constant-1d0*
index a380896..6c8850e 100644 (file)
     *control-stack-start*
     *control-stack-end*
 
+    *need-to-collect-garbage*
+
     ;; the floating point constants
     *fp-constant-0d0*
     *fp-constant-1d0*
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);
index d23df7b..aa2a23f 100644 (file)
@@ -106,9 +106,9 @@ inline static void check_blockables_blocked_or_lose()
 {
     /* Get the current sigmask, by blocking the empty set. */
     sigset_t empty,current;
+    int i;
     sigemptyset(&empty);
     sigprocmask(SIG_BLOCK, &empty, &current);
-    int i;
     for(i=0;i<NSIG;i++) {
         if (sigismember(&blockable_sigset, i) && !sigismember(&current, i))
             lose("blockable signal %d not blocked",i);
index 9a399b6..e5890b6 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.9.1.32"
+"0.9.1.33"