Fix deadlocks in GC on Windows.
[sbcl.git] / src / runtime / gc-common.c
index 9dfc18f..7add951 100644 (file)
@@ -121,12 +121,8 @@ scavenge(lispobj *start, sword_t n_words)
 {
     lispobj *end = start + n_words;
     lispobj *object_ptr;
-    sword_t n_words_scavenged;
-
-    for (object_ptr = start;
-         object_ptr < end;
-         object_ptr += n_words_scavenged) {
 
+    for (object_ptr = start; object_ptr < end;) {
         lispobj object = *object_ptr;
 #ifdef LISP_FEATURE_GENCGC
         if (forwarding_pointer_p(object_ptr))
@@ -141,16 +137,16 @@ scavenge(lispobj *start, sword_t n_words)
                 if (forwarding_pointer_p(ptr)) {
                     /* Yes, there's a forwarding pointer. */
                     *object_ptr = LOW_WORD(forwarding_pointer_value(ptr));
-                    n_words_scavenged = 1;
+                    object_ptr++;
                 } else {
                     /* Scavenge that pointer. */
-                    n_words_scavenged =
+                    object_ptr +=
                         (scavtab[widetag_of(object)])(object_ptr, object);
                 }
             } else {
                 /* It points somewhere other than oldspace. Leave it
                  * alone. */
-                n_words_scavenged = 1;
+                object_ptr++;
             }
         }
 #if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
@@ -166,7 +162,6 @@ scavenge(lispobj *start, sword_t n_words)
                checking a single word and it's anything other than a
                pointer, just hush it up */
             int widetag = widetag_of(object);
-            n_words_scavenged = 1;
 
             if ((scavtab[widetag] == scav_lose) ||
                 (((sizetab[widetag])(object_ptr)) > 1)) {
@@ -176,15 +171,15 @@ If you can reproduce this warning, please send a bug report\n\
 (see manual page for details).\n",
                         object, object_ptr);
             }
+            object_ptr++;
         }
 #endif
         else if (fixnump(object)) {
             /* It's a fixnum: really easy.. */
-            n_words_scavenged = 1;
+            object_ptr++;
         } else {
             /* It's some sort of header object or another. */
-            n_words_scavenged =
-                (scavtab[widetag_of(object)])(object_ptr, object);
+            object_ptr += (scavtab[widetag_of(object)])(object_ptr, object);
         }
     }
     gc_assert_verbose(object_ptr == end, "Final object pointer %p, start %p, end %p\n",
@@ -2666,8 +2661,24 @@ maybe_gc(os_context_t *context)
      * we may even be in a WITHOUT-INTERRUPTS. */
     gc_happened = funcall0(StaticSymbolFunction(SUB_GC));
     FSHOW((stderr, "/maybe_gc: gc_happened=%s\n",
-           (gc_happened == NIL) ? "NIL" : "T"));
-    if ((gc_happened != NIL) &&
+           (gc_happened == NIL)
+           ? "NIL"
+           : ((gc_happened == T)
+              ? "T"
+              : "0")));
+    /* gc_happened can take three values: T, NIL, 0.
+     *
+     * T means that the thread managed to trigger a GC, and post-gc
+     * must be called.
+     *
+     * NIL means that the thread is within without-gcing, and no GC
+     * has occurred.
+     *
+     * Finally, 0 means that *a* GC has occurred, but it wasn't
+     * triggered by this thread; success, but post-gc doesn't have
+     * to be called.
+     */
+    if ((gc_happened == T) &&
         /* See if interrupts are enabled or it's possible to enable
          * them. POST-GC has a similar check, but we don't want to
          * unlock deferrables in that case and get a pending interrupt