1.0.4.13: refactor trap handling
[sbcl.git] / src / runtime / interrupt.c
1 /*
2  * interrupt-handling magic
3  */
4
5 /*
6  * This software is part of the SBCL system. See the README file for
7  * more information.
8  *
9  * This software is derived from the CMU CL system, which was
10  * written at Carnegie Mellon University and released into the
11  * public domain. The software is in the public domain and is
12  * provided with absolutely no warranty. See the COPYING and CREDITS
13  * files for more information.
14  */
15
16
17 /* As far as I can tell, what's going on here is:
18  *
19  * In the case of most signals, when Lisp asks us to handle the
20  * signal, the outermost handler (the one actually passed to UNIX) is
21  * either interrupt_handle_now(..) or maybe_now_maybe_later(..).
22  * In that case, the Lisp-level handler is stored in interrupt_handlers[..]
23  * and interrupt_low_level_handlers[..] is cleared.
24  *
25  * However, some signals need special handling, e.g.
26  *
27  * o the SIGSEGV (for e.g. Linux) or SIGBUS (for e.g. FreeBSD) used by the
28  *   garbage collector to detect violations of write protection,
29  *   because some cases of such signals (e.g. GC-related violations of
30  *   write protection) are handled at C level and never passed on to
31  *   Lisp. For such signals, we still store any Lisp-level handler
32  *   in interrupt_handlers[..], but for the outermost handle we use
33  *   the value from interrupt_low_level_handlers[..], instead of the
34  *   ordinary interrupt_handle_now(..) or interrupt_handle_later(..).
35  *
36  * o the SIGTRAP (Linux/Alpha) which Lisp code uses to handle breakpoints,
37  *   pseudo-atomic sections, and some classes of error (e.g. "function
38  *   not defined").  This never goes anywhere near the Lisp handlers at all.
39  *   See runtime/alpha-arch.c and code/signal.lisp
40  *
41  * - WHN 20000728, dan 20010128 */
42
43 #include "sbcl.h"
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <signal.h>
49 #include <sys/types.h>
50 #ifndef LISP_FEATURE_WIN32
51 #include <sys/wait.h>
52 #endif
53 #include <errno.h>
54
55 #include "runtime.h"
56 #include "arch.h"
57 #include "os.h"
58 #include "interrupt.h"
59 #include "globals.h"
60 #include "lispregs.h"
61 #include "validate.h"
62 #include "gc.h"
63 #include "alloc.h"
64 #include "dynbind.h"
65 #include "interr.h"
66 #include "genesis/fdefn.h"
67 #include "genesis/simple-fun.h"
68 #include "genesis/cons.h"
69
70 static void run_deferred_handler(struct interrupt_data *data, void *v_context);
71 #ifndef LISP_FEATURE_WIN32
72 static void store_signal_data_for_later (struct interrupt_data *data,
73                                          void *handler, int signal,
74                                          siginfo_t *info,
75                                          os_context_t *context);
76 boolean interrupt_maybe_gc_int(int signal, siginfo_t *info, void *v_context);
77
78 void
79 sigaddset_deferrable(sigset_t *s)
80 {
81     sigaddset(s, SIGHUP);
82     sigaddset(s, SIGINT);
83     sigaddset(s, SIGQUIT);
84     sigaddset(s, SIGPIPE);
85     sigaddset(s, SIGALRM);
86     sigaddset(s, SIGURG);
87     sigaddset(s, SIGTSTP);
88     sigaddset(s, SIGCHLD);
89     sigaddset(s, SIGIO);
90     sigaddset(s, SIGXCPU);
91     sigaddset(s, SIGXFSZ);
92     sigaddset(s, SIGVTALRM);
93     sigaddset(s, SIGPROF);
94     sigaddset(s, SIGWINCH);
95
96 #if !((defined(LISP_FEATURE_DARWIN) || defined(LISP_FEATURE_FREEBSD)) && defined(LISP_FEATURE_SB_THREAD))
97     sigaddset(s, SIGUSR1);
98     sigaddset(s, SIGUSR2);
99 #endif
100
101 #ifdef LISP_FEATURE_SB_THREAD
102     sigaddset(s, SIG_INTERRUPT_THREAD);
103 #endif
104 }
105
106 void
107 sigaddset_blockable(sigset_t *s)
108 {
109     sigaddset_deferrable(s);
110 #ifdef LISP_FEATURE_SB_THREAD
111 #ifdef SIG_RESUME_FROM_GC
112     sigaddset(s, SIG_RESUME_FROM_GC);
113 #endif
114     sigaddset(s, SIG_STOP_FOR_GC);
115 #endif
116 }
117
118 /* initialized in interrupt_init */
119 static sigset_t deferrable_sigset;
120 static sigset_t blockable_sigset;
121 #endif
122
123 void
124 check_blockables_blocked_or_lose(void)
125 {
126 #if !defined(LISP_FEATURE_WIN32)
127     /* Get the current sigmask, by blocking the empty set. */
128     sigset_t empty,current;
129     int i;
130     sigemptyset(&empty);
131     thread_sigmask(SIG_BLOCK, &empty, &current);
132     for(i = 1; i < NSIG; i++) {
133         if (sigismember(&blockable_sigset, i) && !sigismember(&current, i))
134             lose("blockable signal %d not blocked\n",i);
135     }
136 #endif
137 }
138
139 void
140 check_gc_signals_unblocked_or_lose(void)
141 {
142 #ifdef LISP_FEATURE_SB_THREAD
143 # if !defined(LISP_FEATURE_WIN32)
144     /* Get the current sigmask, by blocking the empty set. */
145     sigset_t empty,current;
146     sigemptyset(&empty);
147     thread_sigmask(SIG_BLOCK, &empty, &current);
148     if (sigismember(&current, SIG_STOP_FOR_GC))
149         lose("SIG_STOP_FOR_GC blocked in thread %p at a bad place\n",
150              arch_os_get_current_thread());
151 #  if defined(SIG_RESUME_FROM_GC)
152     if (sigismember(&current, SIG_RESUME_FROM_GC))
153         lose("SIG_RESUME_FROM_GC blocked in thread %p at a bad place\n",
154              arch_os_get_current_thread());
155 #  endif
156 # endif
157 #endif
158 }
159
160 void
161 unblock_gc_signals(void)
162 {
163 #ifdef LISP_FEATURE_SB_THREAD
164     sigset_t new;
165     sigemptyset(&new);
166 #if defined(SIG_RESUME_FROM_GC)
167     sigaddset(&new,SIG_RESUME_FROM_GC);
168 #endif
169     sigaddset(&new,SIG_STOP_FOR_GC);
170     thread_sigmask(SIG_UNBLOCK,&new,0);
171 #endif
172 }
173
174 inline static void
175 check_interrupts_enabled_or_lose(os_context_t *context)
176 {
177     struct thread *thread=arch_os_get_current_thread();
178     if (SymbolValue(INTERRUPTS_ENABLED,thread) == NIL)
179         lose("interrupts not enabled\n");
180     if (
181 #if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
182         (!foreign_function_call_active) &&
183 #endif
184         arch_pseudo_atomic_atomic(context))
185         lose ("in pseudo atomic section\n");
186 }
187
188 /* When we catch an internal error, should we pass it back to Lisp to
189  * be handled in a high-level way? (Early in cold init, the answer is
190  * 'no', because Lisp is still too brain-dead to handle anything.
191  * After sufficient initialization has been completed, the answer
192  * becomes 'yes'.) */
193 boolean internal_errors_enabled = 0;
194
195 #ifndef LISP_FEATURE_WIN32
196 static void (*interrupt_low_level_handlers[NSIG]) (int, siginfo_t*, void*);
197 #endif
198 union interrupt_handler interrupt_handlers[NSIG];
199
200 /* At the toplevel repl we routinely call this function.  The signal
201  * mask ought to be clear anyway most of the time, but may be non-zero
202  * if we were interrupted e.g. while waiting for a queue.  */
203
204 void
205 reset_signal_mask(void)
206 {
207 #ifndef LISP_FEATURE_WIN32
208     sigset_t new;
209     sigemptyset(&new);
210     thread_sigmask(SIG_SETMASK,&new,0);
211 #endif
212 }
213
214 void
215 block_blockable_signals(void)
216 {
217 #ifndef LISP_FEATURE_WIN32
218     thread_sigmask(SIG_BLOCK, &blockable_sigset, 0);
219 #endif
220 }
221
222 void
223 block_deferrable_signals(void)
224 {
225 #ifndef LISP_FEATURE_WIN32
226     thread_sigmask(SIG_BLOCK, &deferrable_sigset, 0);
227 #endif
228 }
229
230 \f
231 /*
232  * utility routines used by various signal handlers
233  */
234
235 static void
236 build_fake_control_stack_frames(struct thread *th,os_context_t *context)
237 {
238 #ifndef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
239
240     lispobj oldcont;
241
242     /* Build a fake stack frame or frames */
243
244     current_control_frame_pointer =
245         (lispobj *)(unsigned long)
246             (*os_context_register_addr(context, reg_CSP));
247     if ((lispobj *)(unsigned long)
248             (*os_context_register_addr(context, reg_CFP))
249         == current_control_frame_pointer) {
250         /* There is a small window during call where the callee's
251          * frame isn't built yet. */
252         if (lowtag_of(*os_context_register_addr(context, reg_CODE))
253             == FUN_POINTER_LOWTAG) {
254             /* We have called, but not built the new frame, so
255              * build it for them. */
256             current_control_frame_pointer[0] =
257                 *os_context_register_addr(context, reg_OCFP);
258             current_control_frame_pointer[1] =
259                 *os_context_register_addr(context, reg_LRA);
260             current_control_frame_pointer += 8;
261             /* Build our frame on top of it. */
262             oldcont = (lispobj)(*os_context_register_addr(context, reg_CFP));
263         }
264         else {
265             /* We haven't yet called, build our frame as if the
266              * partial frame wasn't there. */
267             oldcont = (lispobj)(*os_context_register_addr(context, reg_OCFP));
268         }
269     }
270     /* We can't tell whether we are still in the caller if it had to
271      * allocate a stack frame due to stack arguments. */
272     /* This observation provoked some past CMUCL maintainer to ask
273      * "Can anything strange happen during return?" */
274     else {
275         /* normal case */
276         oldcont = (lispobj)(*os_context_register_addr(context, reg_CFP));
277     }
278
279     current_control_stack_pointer = current_control_frame_pointer + 8;
280
281     current_control_frame_pointer[0] = oldcont;
282     current_control_frame_pointer[1] = NIL;
283     current_control_frame_pointer[2] =
284         (lispobj)(*os_context_register_addr(context, reg_CODE));
285 #endif
286 }
287
288 /* Stores the context for gc to scavange and builds fake stack
289  * frames. */
290 void
291 fake_foreign_function_call(os_context_t *context)
292 {
293     int context_index;
294     struct thread *thread=arch_os_get_current_thread();
295
296     /* context_index incrementing must not be interrupted */
297     check_blockables_blocked_or_lose();
298
299     /* Get current Lisp state from context. */
300 #ifdef reg_ALLOC
301     dynamic_space_free_pointer =
302         (lispobj *)(unsigned long)
303             (*os_context_register_addr(context, reg_ALLOC));
304     /* fprintf(stderr,"dynamic_space_free_pointer: %p\n", dynamic_space_free_pointer); */
305 #if defined(LISP_FEATURE_ALPHA)
306     if ((long)dynamic_space_free_pointer & 1) {
307         lose("dead in fake_foreign_function_call, context = %x\n", context);
308     }
309 #endif
310 #endif
311 #ifdef reg_BSP
312     current_binding_stack_pointer =
313         (lispobj *)(unsigned long)
314             (*os_context_register_addr(context, reg_BSP));
315 #endif
316
317     build_fake_control_stack_frames(thread,context);
318
319     /* Do dynamic binding of the active interrupt context index
320      * and save the context in the context array. */
321     context_index =
322         fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX,thread));
323
324     if (context_index >= MAX_INTERRUPTS) {
325         lose("maximum interrupt nesting depth (%d) exceeded\n", MAX_INTERRUPTS);
326     }
327
328     bind_variable(FREE_INTERRUPT_CONTEXT_INDEX,
329                   make_fixnum(context_index + 1),thread);
330
331     thread->interrupt_contexts[context_index] = context;
332
333     /* no longer in Lisp now */
334     foreign_function_call_active = 1;
335 }
336
337 /* blocks all blockable signals.  If you are calling from a signal handler,
338  * the usual signal mask will be restored from the context when the handler
339  * finishes.  Otherwise, be careful */
340 void
341 undo_fake_foreign_function_call(os_context_t *context)
342 {
343     struct thread *thread=arch_os_get_current_thread();
344     /* Block all blockable signals. */
345     block_blockable_signals();
346
347     /* going back into Lisp */
348     foreign_function_call_active = 0;
349
350     /* Undo dynamic binding of FREE_INTERRUPT_CONTEXT_INDEX */
351     unbind(thread);
352
353 #ifdef reg_ALLOC
354     /* Put the dynamic space free pointer back into the context. */
355     *os_context_register_addr(context, reg_ALLOC) =
356         (unsigned long) dynamic_space_free_pointer
357         | (*os_context_register_addr(context, reg_ALLOC)
358            & LOWTAG_MASK);
359     /*
360       ((unsigned long)(*os_context_register_addr(context, reg_ALLOC)) & ~LOWTAG_MASK)
361       | ((unsigned long) dynamic_space_free_pointer & LOWTAG_MASK);
362     */
363 #endif
364 }
365
366 /* a handler for the signal caused by execution of a trap opcode
367  * signalling an internal error */
368 void
369 interrupt_internal_error(os_context_t *context, boolean continuable)
370 {
371     lispobj context_sap;
372
373     fake_foreign_function_call(context);
374
375     if (!internal_errors_enabled) {
376         describe_internal_error(context);
377         /* There's no good way to recover from an internal error
378          * before the Lisp error handling mechanism is set up. */
379         lose("internal error too early in init, can't recover\n");
380     }
381
382     /* Allocate the SAP object while the interrupts are still
383      * disabled. */
384     context_sap = alloc_sap(context);
385
386 #ifndef LISP_FEATURE_WIN32
387     thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
388 #endif
389
390     SHOW("in interrupt_internal_error");
391 #ifdef QSHOW
392     /* Display some rudimentary debugging information about the
393      * error, so that even if the Lisp error handler gets badly
394      * confused, we have a chance to determine what's going on. */
395     describe_internal_error(context);
396 #endif
397     funcall2(SymbolFunction(INTERNAL_ERROR), context_sap,
398              continuable ? T : NIL);
399
400     undo_fake_foreign_function_call(context); /* blocks signals again */
401     if (continuable)
402         arch_skip_instruction(context);
403 }
404
405 void
406 interrupt_handle_pending(os_context_t *context)
407 {
408     struct thread *thread;
409     struct interrupt_data *data;
410
411     FSHOW_SIGNAL((stderr, "/entering interrupt_handle_pending\n"));
412
413     check_blockables_blocked_or_lose();
414     thread=arch_os_get_current_thread();
415     data=thread->interrupt_data;
416
417     /* If pseudo_atomic_interrupted is set then the interrupt is going
418      * to be handled now, ergo it's safe to clear it. */
419     arch_clear_pseudo_atomic_interrupted(context);
420
421     if (SymbolValue(GC_INHIBIT,thread)==NIL) {
422 #ifdef LISP_FEATURE_SB_THREAD
423         if (SymbolValue(STOP_FOR_GC_PENDING,thread) != NIL) {
424             /* another thread has already initiated a gc, this attempt
425              * might as well be cancelled */
426             SetSymbolValue(GC_PENDING,NIL,thread);
427             SetSymbolValue(STOP_FOR_GC_PENDING,NIL,thread);
428             sig_stop_for_gc_handler(SIG_STOP_FOR_GC,NULL,context);
429         } else
430 #endif
431         if (SymbolValue(GC_PENDING,thread) != NIL) {
432             /* GC_PENDING is cleared in SUB-GC, or if another thread
433              * is doing a gc already we will get a SIG_STOP_FOR_GC and
434              * that will clear it. */
435             interrupt_maybe_gc_int(0,NULL,context);
436         }
437         check_blockables_blocked_or_lose();
438     }
439
440     /* we may be here only to do the gc stuff, if interrupts are
441      * enabled run the pending handler */
442     if (!((SymbolValue(INTERRUPTS_ENABLED,thread) == NIL) ||
443           (
444 #if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
445            (!foreign_function_call_active) &&
446 #endif
447            arch_pseudo_atomic_atomic(context)))) {
448
449         /* There may be no pending handler, because it was only a gc
450          * that had to be executed or because pseudo atomic triggered
451          * twice for a single interrupt. For the interested reader,
452          * that may happen if an interrupt hits after the interrupted
453          * flag is cleared but before pseduo-atomic is set and a
454          * pseudo atomic is interrupted in that interrupt. */
455         if (data->pending_handler) {
456
457             /* If we're here as the result of a pseudo-atomic as opposed
458              * to WITHOUT-INTERRUPTS, then INTERRUPT_PENDING is already
459              * NIL, because maybe_defer_handler sets
460              * PSEUDO_ATOMIC_INTERRUPTED only if interrupts are enabled.*/
461             SetSymbolValue(INTERRUPT_PENDING, NIL,thread);
462
463 #ifndef LISP_FEATURE_WIN32
464             /* restore the saved signal mask from the original signal (the
465              * one that interrupted us during the critical section) into the
466              * os_context for the signal we're currently in the handler for.
467              * This should ensure that when we return from the handler the
468              * blocked signals are unblocked */
469             sigcopyset(os_context_sigmask_addr(context), &data->pending_mask);
470
471             sigemptyset(&data->pending_mask);
472 #endif
473             /* This will break on sparc linux: the deferred handler really wants
474              * to be called with a void_context */
475             run_deferred_handler(data,(void *)context);
476         }
477     }
478 }
479 \f
480 /*
481  * the two main signal handlers:
482  *   interrupt_handle_now(..)
483  *   maybe_now_maybe_later(..)
484  *
485  * to which we have added interrupt_handle_now_handler(..).  Why?
486  * Well, mostly because the SPARC/Linux platform doesn't quite do
487  * signals the way we want them done.  The third argument in the
488  * handler isn't filled in by the kernel properly, so we fix it up
489  * ourselves in the arch_os_get_context(..) function; however, we only
490  * want to do this when we first hit the handler, and not when
491  * interrupt_handle_now(..) is being called from some other handler
492  * (when the fixup will already have been done). -- CSR, 2002-07-23
493  */
494
495 void
496 interrupt_handle_now(int signal, siginfo_t *info, void *void_context)
497 {
498     os_context_t *context = (os_context_t*)void_context;
499 #if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
500     boolean were_in_lisp;
501 #endif
502     union interrupt_handler handler;
503
504     check_blockables_blocked_or_lose();
505
506
507 #ifndef LISP_FEATURE_WIN32
508     if (sigismember(&deferrable_sigset,signal))
509         check_interrupts_enabled_or_lose(context);
510 #endif
511
512 #if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
513     /* Under Linux on some architectures, we appear to have to restore
514        the FPU control word from the context, as after the signal is
515        delivered we appear to have a null FPU control word. */
516     os_restore_fp_control(context);
517 #endif
518
519
520     handler = interrupt_handlers[signal];
521
522     if (ARE_SAME_HANDLER(handler.c, SIG_IGN)) {
523         return;
524     }
525
526 #if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
527     were_in_lisp = !foreign_function_call_active;
528     if (were_in_lisp)
529 #endif
530     {
531         fake_foreign_function_call(context);
532     }
533
534     FSHOW_SIGNAL((stderr,
535                   "/entering interrupt_handle_now(%d, info, context)\n",
536                   signal));
537
538     if (ARE_SAME_HANDLER(handler.c, SIG_DFL)) {
539
540         /* This can happen if someone tries to ignore or default one
541          * of the signals we need for runtime support, and the runtime
542          * support decides to pass on it. */
543         lose("no handler for signal %d in interrupt_handle_now(..)\n", signal);
544
545     } else if (lowtag_of(handler.lisp) == FUN_POINTER_LOWTAG) {
546         /* Once we've decided what to do about contexts in a
547          * return-elsewhere world (the original context will no longer
548          * be available; should we copy it or was nobody using it anyway?)
549          * then we should convert this to return-elsewhere */
550
551         /* CMUCL comment said "Allocate the SAPs while the interrupts
552          * are still disabled.".  I (dan, 2003.08.21) assume this is
553          * because we're not in pseudoatomic and allocation shouldn't
554          * be interrupted.  In which case it's no longer an issue as
555          * all our allocation from C now goes through a PA wrapper,
556          * but still, doesn't hurt.
557          *
558          * Yeah, but non-gencgc platforms don't really wrap allocation
559          * in PA. MG - 2005-08-29  */
560
561         lispobj info_sap,context_sap = alloc_sap(context);
562         info_sap = alloc_sap(info);
563         /* Leave deferrable signals blocked, the handler itself will
564          * allow signals again when it sees fit. */
565 #ifdef LISP_FEATURE_SB_THREAD
566         {
567             sigset_t unblock;
568             sigemptyset(&unblock);
569             sigaddset(&unblock, SIG_STOP_FOR_GC);
570 #ifdef SIG_RESUME_FROM_GC
571             sigaddset(&unblock, SIG_RESUME_FROM_GC);
572 #endif
573             thread_sigmask(SIG_UNBLOCK, &unblock, 0);
574         }
575 #endif
576
577         FSHOW_SIGNAL((stderr,"/calling Lisp-level handler\n"));
578
579         funcall3(handler.lisp,
580                  make_fixnum(signal),
581                  info_sap,
582                  context_sap);
583     } else {
584
585         FSHOW_SIGNAL((stderr,"/calling C-level handler\n"));
586
587 #ifndef LISP_FEATURE_WIN32
588         /* Allow signals again. */
589         thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
590 #endif
591
592         (*handler.c)(signal, info, void_context);
593     }
594
595 #if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
596     if (were_in_lisp)
597 #endif
598     {
599         undo_fake_foreign_function_call(context); /* block signals again */
600     }
601
602     FSHOW_SIGNAL((stderr,
603                   "/returning from interrupt_handle_now(%d, info, context)\n",
604                   signal));
605 }
606
607 /* This is called at the end of a critical section if the indications
608  * are that some signal was deferred during the section.  Note that as
609  * far as C or the kernel is concerned we dealt with the signal
610  * already; we're just doing the Lisp-level processing now that we
611  * put off then */
612 static void
613 run_deferred_handler(struct interrupt_data *data, void *v_context) {
614     /* The pending_handler may enable interrupts and then another
615      * interrupt may hit, overwrite interrupt_data, so reset the
616      * pending handler before calling it. Trust the handler to finish
617      * with the siginfo before enabling interrupts. */
618     void (*pending_handler) (int, siginfo_t*, void*)=data->pending_handler;
619
620     data->pending_handler=0;
621     (*pending_handler)(data->pending_signal,&(data->pending_info), v_context);
622 }
623
624 #ifndef LISP_FEATURE_WIN32
625 boolean
626 maybe_defer_handler(void *handler, struct interrupt_data *data,
627                     int signal, siginfo_t *info, os_context_t *context)
628 {
629     struct thread *thread=arch_os_get_current_thread();
630
631     check_blockables_blocked_or_lose();
632
633     if (SymbolValue(INTERRUPT_PENDING,thread) != NIL)
634         lose("interrupt already pending\n");
635     /* If interrupts are disabled then INTERRUPT_PENDING is set and
636      * not PSEDUO_ATOMIC_INTERRUPTED. This is important for a pseudo
637      * atomic section inside a WITHOUT-INTERRUPTS.
638      */
639     if (SymbolValue(INTERRUPTS_ENABLED,thread) == NIL) {
640         store_signal_data_for_later(data,handler,signal,info,context);
641         SetSymbolValue(INTERRUPT_PENDING, T,thread);
642         FSHOW_SIGNAL((stderr,
643                       "/maybe_defer_handler(%x,%d),thread=%lu: deferred\n",
644                       (unsigned int)handler,signal,
645                       (unsigned long)thread->os_thread));
646         return 1;
647     }
648     /* a slightly confusing test.  arch_pseudo_atomic_atomic() doesn't
649      * actually use its argument for anything on x86, so this branch
650      * may succeed even when context is null (gencgc alloc()) */
651     if (
652 #if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)
653         /* FIXME: this foreign_function_call_active test is dubious at
654          * best. If a foreign call is made in a pseudo atomic section
655          * (?) or more likely a pseudo atomic section is in a foreign
656          * call then an interrupt is executed immediately. Maybe it
657          * has to do with C code not maintaining pseudo atomic
658          * properly. MG - 2005-08-10 */
659         (!foreign_function_call_active) &&
660 #endif
661         arch_pseudo_atomic_atomic(context)) {
662         store_signal_data_for_later(data,handler,signal,info,context);
663         arch_set_pseudo_atomic_interrupted(context);
664         FSHOW_SIGNAL((stderr,
665                       "/maybe_defer_handler(%x,%d),thread=%lu: deferred(PA)\n",
666                       (unsigned int)handler,signal,
667                       (unsigned long)thread->os_thread));
668         return 1;
669     }
670     FSHOW_SIGNAL((stderr,
671                   "/maybe_defer_handler(%x,%d),thread=%lu: not deferred\n",
672                   (unsigned int)handler,signal,
673                   (unsigned long)thread->os_thread));
674     return 0;
675 }
676
677 static void
678 store_signal_data_for_later (struct interrupt_data *data, void *handler,
679                              int signal,
680                              siginfo_t *info, os_context_t *context)
681 {
682     if (data->pending_handler)
683         lose("tried to overwrite pending interrupt handler %x with %x\n",
684              data->pending_handler, handler);
685     if (!handler)
686         lose("tried to defer null interrupt handler\n");
687     data->pending_handler = handler;
688     data->pending_signal = signal;
689     if(info)
690         memcpy(&(data->pending_info), info, sizeof(siginfo_t));
691
692     FSHOW_SIGNAL((stderr, "/store_signal_data_for_later: signal: %d\n", signal));
693
694     if(context) {
695         /* the signal mask in the context (from before we were
696          * interrupted) is copied to be restored when
697          * run_deferred_handler happens.  Then the usually-blocked
698          * signals are added to the mask in the context so that we are
699          * running with blocked signals when the handler returns */
700         sigcopyset(&(data->pending_mask),os_context_sigmask_addr(context));
701         sigaddset_deferrable(os_context_sigmask_addr(context));
702     }
703 }
704
705 static void
706 maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context)
707 {
708     os_context_t *context = arch_os_get_context(&void_context);
709
710     struct thread *thread;
711     struct interrupt_data *data;
712
713     thread=arch_os_get_current_thread();
714     data=thread->interrupt_data;
715
716 #if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
717     os_restore_fp_control(context);
718 #endif
719
720     if(maybe_defer_handler(interrupt_handle_now,data,signal,info,context))
721         return;
722     interrupt_handle_now(signal, info, context);
723 #ifdef LISP_FEATURE_DARWIN
724     /* Work around G5 bug */
725     DARWIN_FIX_CONTEXT(context);
726 #endif
727 }
728
729 static void
730 low_level_interrupt_handle_now(int signal, siginfo_t *info, void *void_context)
731 {
732     os_context_t *context = (os_context_t*)void_context;
733
734 #if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
735     os_restore_fp_control(context);
736 #endif
737
738     check_blockables_blocked_or_lose();
739     check_interrupts_enabled_or_lose(context);
740     interrupt_low_level_handlers[signal](signal, info, void_context);
741 #ifdef LISP_FEATURE_DARWIN
742     /* Work around G5 bug */
743     DARWIN_FIX_CONTEXT(context);
744 #endif
745 }
746
747 static void
748 low_level_maybe_now_maybe_later(int signal, siginfo_t *info, void *void_context)
749 {
750     os_context_t *context = arch_os_get_context(&void_context);
751     struct thread *thread;
752     struct interrupt_data *data;
753
754     thread=arch_os_get_current_thread();
755     data=thread->interrupt_data;
756
757 #if defined(LISP_FEATURE_LINUX) || defined(RESTORE_FP_CONTROL_FROM_CONTEXT)
758     os_restore_fp_control(context);
759 #endif
760
761     if(maybe_defer_handler(low_level_interrupt_handle_now,data,
762                            signal,info,context))
763         return;
764     low_level_interrupt_handle_now(signal, info, context);
765 #ifdef LISP_FEATURE_DARWIN
766     /* Work around G5 bug */
767     DARWIN_FIX_CONTEXT(context);
768 #endif
769 }
770 #endif
771
772 #ifdef LISP_FEATURE_SB_THREAD
773
774 void
775 sig_stop_for_gc_handler(int signal, siginfo_t *info, void *void_context)
776 {
777     os_context_t *context = arch_os_get_context(&void_context);
778
779     struct thread *thread=arch_os_get_current_thread();
780     sigset_t ss;
781
782     if ((arch_pseudo_atomic_atomic(context) ||
783          SymbolValue(GC_INHIBIT,thread) != NIL)) {
784         SetSymbolValue(STOP_FOR_GC_PENDING,T,thread);
785         if (SymbolValue(GC_INHIBIT,thread) == NIL)
786             arch_set_pseudo_atomic_interrupted(context);
787         FSHOW_SIGNAL((stderr,"thread=%lu sig_stop_for_gc deferred\n",
788                       thread->os_thread));
789     } else {
790         /* need the context stored so it can have registers scavenged */
791         fake_foreign_function_call(context);
792
793         sigfillset(&ss); /* Block everything. */
794         thread_sigmask(SIG_BLOCK,&ss,0);
795
796         if(thread->state!=STATE_RUNNING) {
797             lose("sig_stop_for_gc_handler: wrong thread state: %ld\n",
798                  fixnum_value(thread->state));
799         }
800         thread->state=STATE_SUSPENDED;
801         FSHOW_SIGNAL((stderr,"thread=%lu suspended\n",thread->os_thread));
802
803 #if defined(SIG_RESUME_FROM_GC)
804         sigemptyset(&ss); sigaddset(&ss,SIG_RESUME_FROM_GC);
805 #else
806         sigemptyset(&ss); sigaddset(&ss,SIG_STOP_FOR_GC);
807 #endif
808
809         /* It is possible to get SIGCONT (and probably other
810          * non-blockable signals) here. */
811 #ifdef SIG_RESUME_FROM_GC
812         {
813             int sigret;
814             do { sigwait(&ss, &sigret); }
815             while (sigret != SIG_RESUME_FROM_GC);
816         }
817 #else
818         while (sigwaitinfo(&ss,0) != SIG_STOP_FOR_GC);
819 #endif
820
821         FSHOW_SIGNAL((stderr,"thread=%lu resumed\n",thread->os_thread));
822         if(thread->state!=STATE_RUNNING) {
823             lose("sig_stop_for_gc_handler: wrong thread state on wakeup: %ld\n",
824                  fixnum_value(thread->state));
825         }
826
827         undo_fake_foreign_function_call(context);
828     }
829 }
830 #endif
831
832 void
833 interrupt_handle_now_handler(int signal, siginfo_t *info, void *void_context)
834 {
835     os_context_t *context = arch_os_get_context(&void_context);
836     interrupt_handle_now(signal, info, context);
837 #ifdef LISP_FEATURE_DARWIN
838     DARWIN_FIX_CONTEXT(context);
839 #endif
840 }
841
842 /*
843  * stuff to detect and handle hitting the GC trigger
844  */
845
846 #ifndef LISP_FEATURE_GENCGC
847 /* since GENCGC has its own way to record trigger */
848 static boolean
849 gc_trigger_hit(int signal, siginfo_t *info, os_context_t *context)
850 {
851     if (current_auto_gc_trigger == NULL)
852         return 0;
853     else{
854         void *badaddr=arch_get_bad_addr(signal,info,context);
855         return (badaddr >= (void *)current_auto_gc_trigger &&
856                 badaddr <((void *)current_dynamic_space + dynamic_space_size));
857     }
858 }
859 #endif
860
861 /* manipulate the signal context and stack such that when the handler
862  * returns, it will call function instead of whatever it was doing
863  * previously
864  */
865
866 #if (defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64))
867 extern int *context_eflags_addr(os_context_t *context);
868 #endif
869
870 extern lispobj call_into_lisp(lispobj fun, lispobj *args, int nargs);
871 extern void post_signal_tramp(void);
872 extern void call_into_lisp_tramp(void);
873 void
874 arrange_return_to_lisp_function(os_context_t *context, lispobj function)
875 {
876 #if !(defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64))
877     void * fun=native_pointer(function);
878     void *code = &(((struct simple_fun *) fun)->code);
879 #endif
880
881     /* Build a stack frame showing `interrupted' so that the
882      * user's backtrace makes (as much) sense (as usual) */
883
884     /* FIXME: what about restoring fp state? */
885     /* FIXME: what about restoring errno? */
886 #ifdef LISP_FEATURE_X86
887     /* Suppose the existence of some function that saved all
888      * registers, called call_into_lisp, then restored GP registers and
889      * returned.  It would look something like this:
890
891      push   ebp
892      mov    ebp esp
893      pushfl
894      pushal
895      push   $0
896      push   $0
897      pushl  {address of function to call}
898      call   0x8058db0 <call_into_lisp>
899      addl   $12,%esp
900      popal
901      popfl
902      leave
903      ret
904
905      * What we do here is set up the stack that call_into_lisp would
906      * expect to see if it had been called by this code, and frob the
907      * signal context so that signal return goes directly to call_into_lisp,
908      * and when that function (and the lisp function it invoked) returns,
909      * it returns to the second half of this imaginary function which
910      * restores all registers and returns to C
911
912      * For this to work, the latter part of the imaginary function
913      * must obviously exist in reality.  That would be post_signal_tramp
914      */
915
916     u32 *sp=(u32 *)*os_context_register_addr(context,reg_ESP);
917
918 #if defined(LISP_FEATURE_DARWIN)
919     u32 *register_save_area = (u32 *)os_validate(0, 0x40);
920
921     FSHOW_SIGNAL((stderr, "/arrange_return_to_lisp_function: preparing to go to function %x, sp: %x\n", function, sp));
922     FSHOW_SIGNAL((stderr, "/arrange_return_to_lisp_function: context: %x, &context %x\n", context, &context));
923
924     /* 1. os_validate (malloc/mmap) register_save_block
925      * 2. copy register state into register_save_block
926      * 3. put a pointer to register_save_block in a register in the context
927      * 4. set the context's EIP to point to a trampoline which:
928      *    a. builds the fake stack frame from the block
929      *    b. frees the block
930      *    c. calls the function
931      */
932
933     *register_save_area = *os_context_pc_addr(context);
934     *(register_save_area + 1) = function;
935     *(register_save_area + 2) = *os_context_register_addr(context,reg_EDI);
936     *(register_save_area + 3) = *os_context_register_addr(context,reg_ESI);
937     *(register_save_area + 4) = *os_context_register_addr(context,reg_EDX);
938     *(register_save_area + 5) = *os_context_register_addr(context,reg_ECX);
939     *(register_save_area + 6) = *os_context_register_addr(context,reg_EBX);
940     *(register_save_area + 7) = *os_context_register_addr(context,reg_EAX);
941     *(register_save_area + 8) = *context_eflags_addr(context);
942
943     *os_context_pc_addr(context) = call_into_lisp_tramp;
944     *os_context_register_addr(context,reg_ECX) = register_save_area;
945 #else
946
947     /* return address for call_into_lisp: */
948     *(sp-15) = (u32)post_signal_tramp;
949     *(sp-14) = function;        /* args for call_into_lisp : function*/
950     *(sp-13) = 0;               /*                           arg array */
951     *(sp-12) = 0;               /*                           no. args */
952     /* this order matches that used in POPAD */
953     *(sp-11)=*os_context_register_addr(context,reg_EDI);
954     *(sp-10)=*os_context_register_addr(context,reg_ESI);
955
956     *(sp-9)=*os_context_register_addr(context,reg_ESP)-8;
957     /* POPAD ignores the value of ESP:  */
958     *(sp-8)=0;
959     *(sp-7)=*os_context_register_addr(context,reg_EBX);
960
961     *(sp-6)=*os_context_register_addr(context,reg_EDX);
962     *(sp-5)=*os_context_register_addr(context,reg_ECX);
963     *(sp-4)=*os_context_register_addr(context,reg_EAX);
964     *(sp-3)=*context_eflags_addr(context);
965     *(sp-2)=*os_context_register_addr(context,reg_EBP);
966     *(sp-1)=*os_context_pc_addr(context);
967
968 #endif
969
970 #elif defined(LISP_FEATURE_X86_64)
971     u64 *sp=(u64 *)*os_context_register_addr(context,reg_RSP);
972
973     /* return address for call_into_lisp: */
974     *(sp-18) = (u64)post_signal_tramp;
975
976     *(sp-17)=*os_context_register_addr(context,reg_R15);
977     *(sp-16)=*os_context_register_addr(context,reg_R14);
978     *(sp-15)=*os_context_register_addr(context,reg_R13);
979     *(sp-14)=*os_context_register_addr(context,reg_R12);
980     *(sp-13)=*os_context_register_addr(context,reg_R11);
981     *(sp-12)=*os_context_register_addr(context,reg_R10);
982     *(sp-11)=*os_context_register_addr(context,reg_R9);
983     *(sp-10)=*os_context_register_addr(context,reg_R8);
984     *(sp-9)=*os_context_register_addr(context,reg_RDI);
985     *(sp-8)=*os_context_register_addr(context,reg_RSI);
986     /* skip RBP and RSP */
987     *(sp-7)=*os_context_register_addr(context,reg_RBX);
988     *(sp-6)=*os_context_register_addr(context,reg_RDX);
989     *(sp-5)=*os_context_register_addr(context,reg_RCX);
990     *(sp-4)=*os_context_register_addr(context,reg_RAX);
991     *(sp-3)=*context_eflags_addr(context);
992     *(sp-2)=*os_context_register_addr(context,reg_RBP);
993     *(sp-1)=*os_context_pc_addr(context);
994
995     *os_context_register_addr(context,reg_RDI) =
996         (os_context_register_t)function; /* function */
997     *os_context_register_addr(context,reg_RSI) = 0;        /* arg. array */
998     *os_context_register_addr(context,reg_RDX) = 0;        /* no. args */
999 #else
1000     struct thread *th=arch_os_get_current_thread();
1001     build_fake_control_stack_frames(th,context);
1002 #endif
1003
1004 #ifdef LISP_FEATURE_X86
1005
1006 #if !defined(LISP_FEATURE_DARWIN)
1007     *os_context_pc_addr(context) = (os_context_register_t)call_into_lisp;
1008     *os_context_register_addr(context,reg_ECX) = 0;
1009     *os_context_register_addr(context,reg_EBP) = (os_context_register_t)(sp-2);
1010 #ifdef __NetBSD__
1011     *os_context_register_addr(context,reg_UESP) =
1012         (os_context_register_t)(sp-15);
1013 #else
1014     *os_context_register_addr(context,reg_ESP) = (os_context_register_t)(sp-15);
1015 #endif /* __NETBSD__ */
1016 #endif /* LISP_FEATURE_DARWIN */
1017
1018 #elif defined(LISP_FEATURE_X86_64)
1019     *os_context_pc_addr(context) = (os_context_register_t)call_into_lisp;
1020     *os_context_register_addr(context,reg_RCX) = 0;
1021     *os_context_register_addr(context,reg_RBP) = (os_context_register_t)(sp-2);
1022     *os_context_register_addr(context,reg_RSP) = (os_context_register_t)(sp-18);
1023 #else
1024     /* this much of the calling convention is common to all
1025        non-x86 ports */
1026     *os_context_pc_addr(context) = (os_context_register_t)(unsigned long)code;
1027     *os_context_register_addr(context,reg_NARGS) = 0;
1028     *os_context_register_addr(context,reg_LIP) =
1029         (os_context_register_t)(unsigned long)code;
1030     *os_context_register_addr(context,reg_CFP) =
1031         (os_context_register_t)(unsigned long)current_control_frame_pointer;
1032 #endif
1033 #ifdef ARCH_HAS_NPC_REGISTER
1034     *os_context_npc_addr(context) =
1035         4 + *os_context_pc_addr(context);
1036 #endif
1037 #ifdef LISP_FEATURE_SPARC
1038     *os_context_register_addr(context,reg_CODE) =
1039         (os_context_register_t)(fun + FUN_POINTER_LOWTAG);
1040 #endif
1041 }
1042
1043 #ifdef LISP_FEATURE_SB_THREAD
1044
1045 /* FIXME: this function can go away when all lisp handlers are invoked
1046  * via arrange_return_to_lisp_function. */
1047 void
1048 interrupt_thread_handler(int num, siginfo_t *info, void *v_context)
1049 {
1050     os_context_t *context = (os_context_t*)arch_os_get_context(&v_context);
1051
1052     /* let the handler enable interrupts again when it sees fit */
1053     sigaddset_deferrable(os_context_sigmask_addr(context));
1054     arrange_return_to_lisp_function(context, SymbolFunction(RUN_INTERRUPTION));
1055 }
1056
1057 #endif
1058
1059 /* KLUDGE: Theoretically the approach we use for undefined alien
1060  * variables should work for functions as well, but on PPC/Darwin
1061  * we get bus error at bogus addresses instead, hence this workaround,
1062  * that has the added benefit of automatically discriminating between
1063  * functions and variables.
1064  */
1065 void
1066 undefined_alien_function() {
1067     funcall0(SymbolFunction(UNDEFINED_ALIEN_FUNCTION_ERROR));
1068 }
1069
1070 boolean
1071 handle_guard_page_triggered(os_context_t *context,os_vm_address_t addr)
1072 {
1073     struct thread *th=arch_os_get_current_thread();
1074
1075     /* note the os_context hackery here.  When the signal handler returns,
1076      * it won't go back to what it was doing ... */
1077     if(addr >= CONTROL_STACK_GUARD_PAGE(th) &&
1078        addr < CONTROL_STACK_GUARD_PAGE(th) + os_vm_page_size) {
1079         /* We hit the end of the control stack: disable guard page
1080          * protection so the error handler has some headroom, protect the
1081          * previous page so that we can catch returns from the guard page
1082          * and restore it. */
1083         protect_control_stack_guard_page(0);
1084         protect_control_stack_return_guard_page(1);
1085
1086         arrange_return_to_lisp_function
1087             (context, SymbolFunction(CONTROL_STACK_EXHAUSTED_ERROR));
1088         return 1;
1089     }
1090     else if(addr >= CONTROL_STACK_RETURN_GUARD_PAGE(th) &&
1091             addr < CONTROL_STACK_RETURN_GUARD_PAGE(th) + os_vm_page_size) {
1092         /* We're returning from the guard page: reprotect it, and
1093          * unprotect this one. This works even if we somehow missed
1094          * the return-guard-page, and hit it on our way to new
1095          * exhaustion instead. */
1096         protect_control_stack_guard_page(1);
1097         protect_control_stack_return_guard_page(0);
1098         return 1;
1099     }
1100     else if (addr >= undefined_alien_address &&
1101              addr < undefined_alien_address + os_vm_page_size) {
1102         arrange_return_to_lisp_function
1103           (context, SymbolFunction(UNDEFINED_ALIEN_VARIABLE_ERROR));
1104         return 1;
1105     }
1106     else return 0;
1107 }
1108
1109 #ifndef LISP_FEATURE_GENCGC
1110 /* This function gets called from the SIGSEGV (for e.g. Linux, NetBSD, &
1111  * OpenBSD) or SIGBUS (for e.g. FreeBSD) handler. Here we check
1112  * whether the signal was due to treading on the mprotect()ed zone -
1113  * and if so, arrange for a GC to happen. */
1114 extern unsigned long bytes_consed_between_gcs; /* gc-common.c */
1115
1116 boolean
1117 interrupt_maybe_gc(int signal, siginfo_t *info, void *void_context)
1118 {
1119     os_context_t *context=(os_context_t *) void_context;
1120
1121     if(!foreign_function_call_active && gc_trigger_hit(signal, info, context)){
1122         struct thread *thread=arch_os_get_current_thread();
1123         clear_auto_gc_trigger();
1124         /* Don't flood the system with interrupts if the need to gc is
1125          * already noted. This can happen for example when SUB-GC
1126          * allocates or after a gc triggered in a WITHOUT-GCING. */
1127         if (SymbolValue(GC_PENDING,thread) == NIL) {
1128             if (SymbolValue(GC_INHIBIT,thread) == NIL) {
1129                 if (arch_pseudo_atomic_atomic(context)) {
1130                     /* set things up so that GC happens when we finish
1131                      * the PA section */
1132                     SetSymbolValue(GC_PENDING,T,thread);
1133                     arch_set_pseudo_atomic_interrupted(context);
1134                 } else {
1135                     interrupt_maybe_gc_int(signal,info,void_context);
1136                 }
1137             } else {
1138                 SetSymbolValue(GC_PENDING,T,thread);
1139             }
1140         }
1141         return 1;
1142     }
1143     return 0;
1144 }
1145
1146 #endif
1147
1148 /* this is also used by gencgc, in alloc() */
1149 boolean
1150 interrupt_maybe_gc_int(int signal, siginfo_t *info, void *void_context)
1151 {
1152     os_context_t *context=(os_context_t *) void_context;
1153 #ifndef LISP_FEATURE_WIN32
1154     struct thread *thread=arch_os_get_current_thread();
1155 #endif
1156
1157     fake_foreign_function_call(context);
1158
1159     /* SUB-GC may return without GCing if *GC-INHIBIT* is set, in
1160      * which case we will be running with no gc trigger barrier
1161      * thing for a while.  But it shouldn't be long until the end
1162      * of WITHOUT-GCING.
1163      *
1164      * FIXME: It would be good to protect the end of dynamic space
1165      * and signal a storage condition from there.
1166      */
1167
1168     /* Restore the signal mask from the interrupted context before
1169      * calling into Lisp if interrupts are enabled. Why not always?
1170      *
1171      * Suppose there is a WITHOUT-INTERRUPTS block far, far out. If an
1172      * interrupt hits while in SUB-GC, it is deferred and the
1173      * os_context_sigmask of that interrupt is set to block further
1174      * deferrable interrupts (until the first one is
1175      * handled). Unfortunately, that context refers to this place and
1176      * when we return from here the signals will not be blocked.
1177      *
1178      * A kludgy alternative is to propagate the sigmask change to the
1179      * outer context.
1180      */
1181 #ifndef LISP_FEATURE_WIN32
1182     if(SymbolValue(INTERRUPTS_ENABLED,thread)!=NIL) {
1183         thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
1184         check_gc_signals_unblocked_or_lose();
1185     }
1186     else
1187         unblock_gc_signals();
1188 #endif
1189     funcall0(SymbolFunction(SUB_GC));
1190     undo_fake_foreign_function_call(context);
1191     return 1;
1192 }
1193
1194 \f
1195 /*
1196  * noise to install handlers
1197  */
1198
1199 #ifndef LISP_FEATURE_WIN32
1200 /* In Linux 2.4 synchronous signals (sigtrap & co) can be delivered if
1201  * they are blocked, in Linux 2.6 the default handler is invoked
1202  * instead that usually coredumps. One might hastily think that adding
1203  * SA_NODEFER helps, but until ~2.6.13 if SA_NODEFER is specified then
1204  * the whole sa_mask is ignored and instead of not adding the signal
1205  * in question to the mask. That means if it's not blockable the
1206  * signal must be unblocked at the beginning of signal handlers.
1207  *
1208  * It turns out that NetBSD's SA_NODEFER doesn't DTRT in a different
1209  * way: if SA_NODEFER is set and the signal is in sa_mask, the signal
1210  * will be unblocked in the sigmask during the signal handler.  -- RMK
1211  * X-mas day, 2005
1212  */
1213 static volatile int sigaction_nodefer_works = -1;
1214
1215 #define SA_NODEFER_TEST_BLOCK_SIGNAL SIGABRT
1216 #define SA_NODEFER_TEST_KILL_SIGNAL SIGUSR1
1217
1218 static void
1219 sigaction_nodefer_test_handler(int signal, siginfo_t *info, void *void_context)
1220 {
1221     sigset_t empty, current;
1222     int i;
1223     sigemptyset(&empty);
1224     thread_sigmask(SIG_BLOCK, &empty, &current);
1225     /* There should be exactly two blocked signals: the two we added
1226      * to sa_mask when setting up the handler.  NetBSD doesn't block
1227      * the signal we're handling when SA_NODEFER is set; Linux before
1228      * 2.6.13 or so also doesn't block the other signal when
1229      * SA_NODEFER is set. */
1230     for(i = 1; i < NSIG; i++)
1231         if (sigismember(&current, i) !=
1232             (((i == SA_NODEFER_TEST_BLOCK_SIGNAL) || (i == signal)) ? 1 : 0)) {
1233             FSHOW_SIGNAL((stderr, "SA_NODEFER doesn't work, signal %d\n", i));
1234             sigaction_nodefer_works = 0;
1235         }
1236     if (sigaction_nodefer_works == -1)
1237         sigaction_nodefer_works = 1;
1238 }
1239
1240 static void
1241 see_if_sigaction_nodefer_works()
1242 {
1243     struct sigaction sa, old_sa;
1244
1245     sa.sa_flags = SA_SIGINFO | SA_NODEFER;
1246     sa.sa_sigaction = sigaction_nodefer_test_handler;
1247     sigemptyset(&sa.sa_mask);
1248     sigaddset(&sa.sa_mask, SA_NODEFER_TEST_BLOCK_SIGNAL);
1249     sigaddset(&sa.sa_mask, SA_NODEFER_TEST_KILL_SIGNAL);
1250     sigaction(SA_NODEFER_TEST_KILL_SIGNAL, &sa, &old_sa);
1251     /* Make sure no signals are blocked. */
1252     {
1253         sigset_t empty;
1254         sigemptyset(&empty);
1255         thread_sigmask(SIG_SETMASK, &empty, 0);
1256     }
1257     kill(getpid(), SA_NODEFER_TEST_KILL_SIGNAL);
1258     while (sigaction_nodefer_works == -1);
1259     sigaction(SA_NODEFER_TEST_KILL_SIGNAL, &old_sa, NULL);
1260 }
1261
1262 #undef SA_NODEFER_TEST_BLOCK_SIGNAL
1263 #undef SA_NODEFER_TEST_KILL_SIGNAL
1264
1265 static void
1266 unblock_me_trampoline(int signal, siginfo_t *info, void *void_context)
1267 {
1268     sigset_t unblock;
1269
1270     sigemptyset(&unblock);
1271     sigaddset(&unblock, signal);
1272     thread_sigmask(SIG_UNBLOCK, &unblock, 0);
1273     interrupt_handle_now_handler(signal, info, void_context);
1274 }
1275
1276 static void
1277 low_level_unblock_me_trampoline(int signal, siginfo_t *info, void *void_context)
1278 {
1279     sigset_t unblock;
1280
1281     sigemptyset(&unblock);
1282     sigaddset(&unblock, signal);
1283     thread_sigmask(SIG_UNBLOCK, &unblock, 0);
1284     (*interrupt_low_level_handlers[signal])(signal, info, void_context);
1285 }
1286
1287 void
1288 undoably_install_low_level_interrupt_handler (int signal,
1289                                               void handler(int,
1290                                                            siginfo_t*,
1291                                                            void*))
1292 {
1293     struct sigaction sa;
1294
1295     if (0 > signal || signal >= NSIG) {
1296         lose("bad signal number %d\n", signal);
1297     }
1298
1299     if (ARE_SAME_HANDLER(handler, SIG_DFL))
1300         sa.sa_sigaction = handler;
1301     else if (sigismember(&deferrable_sigset,signal))
1302         sa.sa_sigaction = low_level_maybe_now_maybe_later;
1303     /* The use of a trampoline appears to break the
1304        arch_os_get_context() workaround for SPARC/Linux.  For now,
1305        don't use the trampoline (and so be vulnerable to the problems
1306        that SA_NODEFER is meant to solve. */
1307 #if !(defined(LISP_FEATURE_SPARC) && defined(LISP_FEATURE_LINUX))
1308     else if (!sigaction_nodefer_works &&
1309              !sigismember(&blockable_sigset, signal))
1310         sa.sa_sigaction = low_level_unblock_me_trampoline;
1311 #endif
1312     else
1313         sa.sa_sigaction = handler;
1314
1315     sigcopyset(&sa.sa_mask, &blockable_sigset);
1316     sa.sa_flags = SA_SIGINFO | SA_RESTART
1317         | (sigaction_nodefer_works ? SA_NODEFER : 0);
1318 #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
1319     if((signal==SIG_MEMORY_FAULT)
1320 #ifdef SIG_MEMORY_FAULT2
1321        || (signal==SIG_MEMORY_FAULT2)
1322 #endif
1323 #ifdef SIG_INTERRUPT_THREAD
1324        || (signal==SIG_INTERRUPT_THREAD)
1325 #endif
1326        )
1327         sa.sa_flags |= SA_ONSTACK;
1328 #endif
1329
1330     sigaction(signal, &sa, NULL);
1331     interrupt_low_level_handlers[signal] =
1332         (ARE_SAME_HANDLER(handler, SIG_DFL) ? 0 : handler);
1333 }
1334 #endif
1335
1336 /* This is called from Lisp. */
1337 unsigned long
1338 install_handler(int signal, void handler(int, siginfo_t*, void*))
1339 {
1340 #ifndef LISP_FEATURE_WIN32
1341     struct sigaction sa;
1342     sigset_t old, new;
1343     union interrupt_handler oldhandler;
1344
1345     FSHOW((stderr, "/entering POSIX install_handler(%d, ..)\n", signal));
1346
1347     sigemptyset(&new);
1348     sigaddset(&new, signal);
1349     thread_sigmask(SIG_BLOCK, &new, &old);
1350
1351     FSHOW((stderr, "/interrupt_low_level_handlers[signal]=%x\n",
1352            (unsigned int)interrupt_low_level_handlers[signal]));
1353     if (interrupt_low_level_handlers[signal]==0) {
1354         if (ARE_SAME_HANDLER(handler, SIG_DFL) ||
1355             ARE_SAME_HANDLER(handler, SIG_IGN))
1356             sa.sa_sigaction = handler;
1357         else if (sigismember(&deferrable_sigset, signal))
1358             sa.sa_sigaction = maybe_now_maybe_later;
1359         else if (!sigaction_nodefer_works &&
1360                  !sigismember(&blockable_sigset, signal))
1361             sa.sa_sigaction = unblock_me_trampoline;
1362         else
1363             sa.sa_sigaction = interrupt_handle_now_handler;
1364
1365         sigcopyset(&sa.sa_mask, &blockable_sigset);
1366         sa.sa_flags = SA_SIGINFO | SA_RESTART |
1367             (sigaction_nodefer_works ? SA_NODEFER : 0);
1368         sigaction(signal, &sa, NULL);
1369     }
1370
1371     oldhandler = interrupt_handlers[signal];
1372     interrupt_handlers[signal].c = handler;
1373
1374     thread_sigmask(SIG_SETMASK, &old, 0);
1375
1376     FSHOW((stderr, "/leaving POSIX install_handler(%d, ..)\n", signal));
1377
1378     return (unsigned long)oldhandler.lisp;
1379 #else
1380     /* Probably-wrong Win32 hack */
1381     return 0;
1382 #endif
1383 }
1384
1385 void
1386 interrupt_init()
1387 {
1388 #ifndef LISP_FEATURE_WIN32
1389     int i;
1390     SHOW("entering interrupt_init()");
1391     see_if_sigaction_nodefer_works();
1392     sigemptyset(&deferrable_sigset);
1393     sigemptyset(&blockable_sigset);
1394     sigaddset_deferrable(&deferrable_sigset);
1395     sigaddset_blockable(&blockable_sigset);
1396
1397     /* Set up high level handler information. */
1398     for (i = 0; i < NSIG; i++) {
1399         interrupt_handlers[i].c =
1400             /* (The cast here blasts away the distinction between
1401              * SA_SIGACTION-style three-argument handlers and
1402              * signal(..)-style one-argument handlers, which is OK
1403              * because it works to call the 1-argument form where the
1404              * 3-argument form is expected.) */
1405             (void (*)(int, siginfo_t*, void*))SIG_DFL;
1406     }
1407
1408     SHOW("returning from interrupt_init()");
1409 #endif
1410 }
1411
1412 #ifndef LISP_FEATURE_WIN32
1413 int
1414 siginfo_code(siginfo_t *info)
1415 {
1416     return info->si_code;
1417 }
1418 os_vm_address_t current_memory_fault_address;
1419
1420 void
1421 lisp_memory_fault_error(os_context_t *context, os_vm_address_t addr)
1422 {
1423    /* FIXME: This is lossy: if we get another memory fault (eg. from
1424     * another thread) before lisp has read this, we the information.
1425     * However, since this is mostly informative, we'll live with that for
1426     * now -- some address is better then no address in this case.
1427     */
1428     current_memory_fault_address = addr;
1429     arrange_return_to_lisp_function(context, SymbolFunction(MEMORY_FAULT_ERROR));
1430 }
1431 #endif
1432
1433 /* Common logic far trapping instructions. How we actually handle each
1434  * case is highly architecture dependant, but the overall shape is
1435  * this. */
1436 boolean
1437 maybe_handle_trap(os_context_t *context, int trap)
1438 {
1439     switch(trap) {
1440     case trap_PendingInterrupt:
1441         FSHOW((stderr, "/<trap pending interrupt>\n"));
1442         arch_skip_instruction(context);
1443         interrupt_handle_pending(context);
1444         break;
1445     case trap_Error:
1446     case trap_Cerror:
1447         FSHOW((stderr, "/<trap error/cerror %d>\n", trap));
1448         interrupt_internal_error(context, trap==trap_Cerror);
1449         break;
1450     case trap_Breakpoint:
1451         arch_handle_breakpoint(context);
1452         break;
1453     case trap_FunEndBreakpoint:
1454         arch_handle_fun_end_breakpoint(context);
1455         break;
1456 #ifdef trap_AfterBreakpoint
1457     case trap_AfterBreakpoint:
1458         arch_handle_after_breakpoint(context);
1459         break;
1460 #endif
1461 #ifdef trap_SingleStepAround
1462     case trap_SingleStepAround:
1463     case trap_SingleStepBefore:
1464         arch_handle_single_step_trap(context, trap);
1465         break;
1466 #endif
1467     case trap_Halt:
1468         fake_foreign_function_call(context);
1469         lose("%%PRIMITIVE HALT called; the party is over.\n");
1470     default:
1471         FSHOW((stderr,"/[C--trap default %d %d %x]\n",
1472                signal, trap, context));
1473         /* Not our trap! */
1474         return 0;
1475     }
1476     return 1;
1477 }
1478