#include "globals.h"
#include "lispregs.h"
#include "validate.h"
+#include "interr.h"
#include "gc.h"
#include "alloc.h"
#include "dynbind.h"
-#include "interr.h"
#include "pseudo-atomic.h"
#include "genesis/fdefn.h"
#include "genesis/simple-fun.h"
set_thread_state(thread,STATE_SUSPENDED);
FSHOW_SIGNAL((stderr,"suspended\n"));
+ /* While waiting for gc to finish occupy ourselves with zeroing
+ * the unused portion of the control stack to reduce conservatism.
+ * On hypothetic platforms with threads and exact gc it is
+ * actually a must. */
+ scrub_control_stack();
+
wait_for_thread_state_change(thread, STATE_SUSPENDED);
FSHOW_SIGNAL((stderr,"resumed\n"));
|| (signal == SIGEMT)
#endif
)
- corruption_warning_and_maybe_lose("Signal %d recieved", signal);
+ corruption_warning_and_maybe_lose("Signal %d received", signal);
#endif
interrupt_handle_now(signal, info, context);
RESTORE_ERRNO;
funcall0(StaticSymbolFunction(UNDEFINED_ALIEN_FUNCTION_ERROR));
}
+void lower_thread_control_stack_guard_page(struct thread *th)
+{
+ protect_control_stack_guard_page(0, th);
+ protect_control_stack_return_guard_page(1, th);
+ th->control_stack_guard_page_protected = NIL;
+ fprintf(stderr, "INFO: Control stack guard page unprotected\n");
+}
+
+void reset_thread_control_stack_guard_page(struct thread *th)
+{
+ memset(CONTROL_STACK_GUARD_PAGE(th), 0, os_vm_page_size);
+ protect_control_stack_guard_page(1, th);
+ protect_control_stack_return_guard_page(0, th);
+ th->control_stack_guard_page_protected = T;
+ fprintf(stderr, "INFO: Control stack guard page reprotected\n");
+}
+
+/* Called from the REPL, too. */
+void reset_control_stack_guard_page(void)
+{
+ struct thread *th=arch_os_get_current_thread();
+ if (th->control_stack_guard_page_protected == NIL) {
+ reset_thread_control_stack_guard_page(th);
+ }
+}
+
+void lower_control_stack_guard_page(void)
+{
+ lower_thread_control_stack_guard_page(arch_os_get_current_thread());
+}
+
boolean
handle_guard_page_triggered(os_context_t *context,os_vm_address_t addr)
{
* protection so the error handler has some headroom, protect the
* previous page so that we can catch returns from the guard page
* and restore it. */
- protect_control_stack_guard_page(0, NULL);
- protect_control_stack_return_guard_page(1, NULL);
- fprintf(stderr, "INFO: Control stack guard page unprotected\n");
-
+ if (th->control_stack_guard_page_protected == NIL)
+ lose("control_stack_guard_page_protected NIL");
+ lower_control_stack_guard_page();
#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
/* For the unfortunate case, when the control stack is
* exhausted in a signal handler. */
* unprotect this one. This works even if we somehow missed
* the return-guard-page, and hit it on our way to new
* exhaustion instead. */
- protect_control_stack_guard_page(1, NULL);
- protect_control_stack_return_guard_page(0, NULL);
- fprintf(stderr, "INFO: Control stack guard page reprotected\n");
+ if (th->control_stack_guard_page_protected != NIL)
+ lose("control_stack_guard_page_protected not NIL");
+ reset_control_stack_guard_page();
return 1;
}
else if(addr >= BINDING_STACK_HARD_GUARD_PAGE(th) &&