#include "genesis/simple-fun.h"
#include "genesis/cons.h"
+/* Under Linux on some architectures, we appear to have to restore the
+ * FPU control word from the context, as after the signal is delivered
+ * we appear to have a null FPU control word. */
+#if defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
+#define RESTORE_FP_CONTROL_WORD(context,void_context) \
+ os_context_t *context = arch_os_get_context(&void_context); \
+ os_restore_fp_control(context);
+#else
+#define RESTORE_FP_CONTROL_WORD(context,void_context) \
+ os_context_t *context = arch_os_get_context(&void_context);
+#endif
+
/* These are to be used in signal handlers. Currently all handlers are
* called from one of:
*
* low_level_maybe_now_maybe_later
* low_level_unblock_me_trampoline
*/
-#define SAVE_ERRNO() \
+#define SAVE_ERRNO(context,void_context) \
{ \
int _saved_errno = errno; \
+ RESTORE_FP_CONTROL_WORD(context,void_context); \
{
#define RESTORE_ERRNO \
check_interrupts_enabled_or_lose(context);
#endif
-#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
- /* Under Linux on some architectures, we appear to have to restore
- the FPU control word from the context, as after the signal is
- delivered we appear to have a null FPU control word. */
- os_restore_fp_control(context);
-#endif
-
handler = interrupt_handlers[signal];
if (ARE_SAME_HANDLER(handler.c, SIG_IGN)) {
static void
maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context)
{
- SAVE_ERRNO();
- os_context_t *context = arch_os_get_context(&void_context);
+ SAVE_ERRNO(context,void_context);
struct thread *thread = arch_os_get_current_thread();
struct interrupt_data *data = thread->interrupt_data;
-#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
- os_restore_fp_control(context);
-#endif
-
if(!maybe_defer_handler(interrupt_handle_now,data,signal,info,context))
interrupt_handle_now(signal, info, context);
RESTORE_ERRNO;
static void
low_level_maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context)
{
- SAVE_ERRNO();
- os_context_t *context = arch_os_get_context(&void_context);
+ SAVE_ERRNO(context,void_context);
struct thread *thread = arch_os_get_current_thread();
struct interrupt_data *data = thread->interrupt_data;
-#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
- os_restore_fp_control(context);
-#endif
-
if(!maybe_defer_handler(low_level_interrupt_handle_now,data,
signal,info,context))
low_level_interrupt_handle_now(signal, info, context);
void
interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context)
{
- SAVE_ERRNO();
- os_context_t *context = arch_os_get_context(&void_context);
-#if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
- os_restore_fp_control(context);
+ SAVE_ERRNO(context,void_context);
#ifndef LISP_FEATURE_WIN32
if ((signal == SIGILL) || (signal == SIGBUS)
#ifndef LISP_FEATURE_LINUX
)
corruption_warning_and_maybe_lose("Signal %d recieved", signal);
#endif
-#endif
interrupt_handle_now(signal, info, context);
RESTORE_ERRNO;
}
/* Build a stack frame showing `interrupted' so that the
* user's backtrace makes (as much) sense (as usual) */
- /* FIXME: what about restoring fp state? */
+ /* fp state is saved and restored by call_into_lisp */
/* FIXME: errno is not restored, but since current uses of this
* function only call Lisp code that signals an error, it's not
* much of a problem. In other words, running out of the control
* previous page so that we can catch returns from the guard page
* and restore it. */
corruption_warning_and_maybe_lose("Control stack exhausted");
- protect_control_stack_guard_page(0);
- protect_control_stack_return_guard_page(1);
+ protect_control_stack_guard_page(0, NULL);
+ protect_control_stack_return_guard_page(1, NULL);
#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
/* For the unfortunate case, when the control stack is
* the return-guard-page, and hit it on our way to new
* exhaustion instead. */
fprintf(stderr, "INFO: Control stack guard page reprotected\n");
- protect_control_stack_guard_page(1);
- protect_control_stack_return_guard_page(0);
+ protect_control_stack_guard_page(1, NULL);
+ protect_control_stack_return_guard_page(0, NULL);
+ return 1;
+ }
+ else if(addr >= BINDING_STACK_GUARD_PAGE(th) &&
+ addr < BINDING_STACK_GUARD_PAGE(th) + os_vm_page_size) {
+ corruption_warning_and_maybe_lose("Binding stack exhausted");
+ protect_binding_stack_guard_page(0, NULL);
+ protect_binding_stack_return_guard_page(1, NULL);
+
+ /* For the unfortunate case, when the binding stack is
+ * exhausted in a signal handler. */
+ unblock_signals_in_context_and_maybe_warn(context);
+ arrange_return_to_lisp_function
+ (context, StaticSymbolFunction(BINDING_STACK_EXHAUSTED_ERROR));
+ return 1;
+ }
+ else if(addr >= BINDING_STACK_RETURN_GUARD_PAGE(th) &&
+ addr < BINDING_STACK_RETURN_GUARD_PAGE(th) + os_vm_page_size) {
+ fprintf(stderr, "INFO: Binding stack guard page reprotected\n");
+ protect_binding_stack_guard_page(1, NULL);
+ protect_binding_stack_return_guard_page(0, NULL);
+ return 1;
+ }
+ else if(addr >= ALIEN_STACK_GUARD_PAGE(th) &&
+ addr < ALIEN_STACK_GUARD_PAGE(th) + os_vm_page_size) {
+ corruption_warning_and_maybe_lose("Alien stack exhausted");
+ protect_alien_stack_guard_page(0, NULL);
+ protect_alien_stack_return_guard_page(1, NULL);
+
+ /* For the unfortunate case, when the alien stack is
+ * exhausted in a signal handler. */
+ unblock_signals_in_context_and_maybe_warn(context);
+ arrange_return_to_lisp_function
+ (context, StaticSymbolFunction(ALIEN_STACK_EXHAUSTED_ERROR));
+ return 1;
+ }
+ else if(addr >= ALIEN_STACK_RETURN_GUARD_PAGE(th) &&
+ addr < ALIEN_STACK_RETURN_GUARD_PAGE(th) + os_vm_page_size) {
+ fprintf(stderr, "INFO: Alien stack guard page reprotected\n");
+ protect_alien_stack_guard_page(1, NULL);
+ protect_alien_stack_return_guard_page(0, NULL);
return 1;
}
else if (addr >= undefined_alien_address &&
static void
unblock_me_trampoline(int signal, siginfo_t *info, void *void_context)
{
- SAVE_ERRNO();
- os_context_t *context = arch_os_get_context(&void_context);
+ SAVE_ERRNO(context,void_context);
sigset_t unblock;
sigemptyset(&unblock);
static void
low_level_unblock_me_trampoline(int signal, siginfo_t *info, void *void_context)
{
- SAVE_ERRNO();
+ SAVE_ERRNO(context,void_context);
sigset_t unblock;
sigemptyset(&unblock);
static void
low_level_handle_now_handler(int signal, siginfo_t *info, void *void_context)
{
- SAVE_ERRNO();
+ SAVE_ERRNO(context,void_context);
(*interrupt_low_level_handlers[signal])(signal, info, void_context);
RESTORE_ERRNO;
}
*/
current_memory_fault_address = addr;
/* To allow debugging memory faults in signal handlers and such. */
- corruption_warning_and_maybe_lose("Memory fault");
+ corruption_warning_and_maybe_lose("Memory fault at %x", addr);
unblock_signals_in_context_and_maybe_warn(context);
+#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
arrange_return_to_lisp_function(context,
StaticSymbolFunction(MEMORY_FAULT_ERROR));
+#else
+ funcall0(StaticSymbolFunction(MEMORY_FAULT_ERROR));
+#endif
}
#endif