ensure-directories-exist: Signal an error when trying to create a
[sbcl.git] / src / runtime / gc-common.c
index ede964d..d9810fa 100644 (file)
@@ -2740,12 +2740,13 @@ scrub_control_stack(void)
     struct thread *th = arch_os_get_current_thread();
     os_vm_address_t guard_page_address = CONTROL_STACK_GUARD_PAGE(th);
     os_vm_address_t hard_guard_page_address = CONTROL_STACK_HARD_GUARD_PAGE(th);
-    lispobj *sp;
 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
-    sp = (lispobj *)&sp - 1;
+    /* On these targets scrubbing from C is a bad idea, so we punt to
+     * a routine in $ARCH-assem.S. */
+    extern void arch_scrub_control_stack(struct thread *, os_vm_address_t, os_vm_address_t);
+    arch_scrub_control_stack(th, guard_page_address, hard_guard_page_address);
 #else
-    sp = access_control_stack_pointer(th);
-#endif
+    lispobj *sp = access_control_stack_pointer(th);
  scrub:
     if ((((os_vm_address_t)sp < (hard_guard_page_address + os_vm_page_size)) &&
          ((os_vm_address_t)sp >= hard_guard_page_address)) ||
@@ -2774,10 +2775,57 @@ scrub_control_stack(void)
             goto scrub;
     } while (((unsigned long)++sp) & (BYTES_ZERO_BEFORE_END - 1));
 #endif
+#endif /* LISP_FEATURE_C_STACK_IS_CONTROL_STACK */
 }
 \f
 #if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
 
+void
+scavenge_control_stack(struct thread *th)
+{
+    lispobj *object_ptr;
+
+    /* In order to properly support dynamic-extent allocation of
+     * non-CONS objects, the control stack requires special handling.
+     * Rather than calling scavenge() directly, grovel over it fixing
+     * broken hearts, scavenging pointers to oldspace, and pitching a
+     * fit when encountering unboxed data.  This prevents stray object
+     * headers from causing the scavenger to blow past the end of the
+     * stack (an error case checked in scavenge()).  We don't worry
+     * about treating unboxed words as boxed or vice versa, because
+     * the compiler isn't allowed to store unboxed objects on the
+     * control stack.  -- AB, 2011-Dec-02 */
+
+    for (object_ptr = th->control_stack_start;
+         object_ptr < access_control_stack_pointer(th);
+         object_ptr++) {
+
+        lispobj object = *object_ptr;
+#ifdef LISP_FEATURE_GENCGC
+        if (forwarding_pointer_p(object_ptr))
+            lose("unexpected forwarding pointer in scavenge_control_stack: %p, start=%p, end=%p\n",
+                 object_ptr, th->control_stack_start, access_control_stack_pointer(th));
+#endif
+        if (is_lisp_pointer(object) && from_space_p(object)) {
+            /* It currently points to old space. Check for a
+             * forwarding pointer. */
+            lispobj *ptr = native_pointer(object);
+            if (forwarding_pointer_p(ptr)) {
+                /* Yes, there's a forwarding pointer. */
+                *object_ptr = LOW_WORD(forwarding_pointer_value(ptr));
+            } else {
+                /* Scavenge that pointer. */
+                long n_words_scavenged =
+                    (scavtab[widetag_of(object)])(object_ptr, object);
+                gc_assert(n_words_scavenged == 1);
+            }
+        } else if (scavtab[widetag_of(object)] == scav_lose) {
+            lose("unboxed object in scavenge_control_stack: %p->%x, start=%p, end=%p\n",
+                 object_ptr, object, th->control_stack_start, access_control_stack_pointer(th));
+        }
+    }
+}
+
 /* Scavenging Interrupt Contexts */
 
 static int boxed_registers[] = BOXED_REGISTERS;