91d7a13c3a4e7fbbd51387189fbb0b0a12172359
[sbcl.git] / src / code / signal.lisp
1 ;;;; handling UNIX signals
2
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
11
12 (in-package "SB!UNIX")
13 \f
14 ;;;; macros for dynamically enabling and disabling signal handling
15
16 ;;; Notes on how the without-interrupts/with-interrupts stuff works:
17 ;;;
18 ;;; Before invoking the supplied handler for any of the signals that
19 ;;; can be blocked, the C interrupt support code checks to see whether
20 ;;; *interrupts-enabled* has been bound to NIL. If so, it saves the
21 ;;; signal number and the value of the signal mask (from the signal
22 ;;; context), sets the signal mask to block all blockable signals,
23 ;;; sets *interrupt-pending* and returns without handling the signal.
24 ;;;
25 ;;; When we drop out the without interrupts, we check to see whether
26 ;;; *INTERRUPT-PENDING* has been set. If so, we call
27 ;;; RECEIVE-PENDING-INTERRUPT, which generates a SIGTRAP. The C code
28 ;;; invokes the handler for the saved signal instead of the SIGTRAP
29 ;;; after replacing the signal mask in the signal context with the
30 ;;; saved value. When that hander returns, the original signal mask is
31 ;;; installed, allowing any other pending signals to be handled.
32 ;;;
33 ;;; This means that the cost of WITHOUT-INTERRUPTS is just a special
34 ;;; binding in the case when no signals are delivered (the normal
35 ;;; case). It's only when a signal is actually delivered that we use
36 ;;; any system calls, and by then the cost of the extra system calls
37 ;;; are lost in the noise when compared with the cost of delivering
38 ;;; the signal in the first place.
39
40 (defvar *interrupts-enabled* t)
41 (defvar *interrupt-pending* nil)
42
43 (sb!xc:defmacro without-interrupts (&body body)
44   #!+sb-doc
45   "Execute BODY in a context impervious to interrupts."
46   (let ((name (gensym "WITHOUT-INTERRUPTS-BODY-")))
47     `(flet ((,name () ,@body))
48        (if *interrupts-enabled*
49            (unwind-protect
50                 (let ((*interrupts-enabled* nil))
51                   (,name))
52              ;; FIXME: Does it matter that an interrupt coming in here
53              ;; could be executed before any of the pending interrupts?
54              ;; Or do incoming interrupts have the good grace to check
55              ;; whether interrupts are pending before executing themselves
56              ;; immediately?
57              ;;
58              ;; FIXME: from the kernel's POV we've already handled the
59              ;; signal the moment we return from the handler having
60              ;; decided to defer it, meaning that the kernel is free
61              ;; to deliver _more_ signals to us... of which we save,
62              ;; and subsequently handle here, only the last one.
63              ;; PSEUDO-ATOMIC has the same issue. -- NS 2005-05-19
64              (when *interrupt-pending*
65                (receive-pending-interrupt)))
66            (,name)))))
67
68 (sb!xc:defmacro with-interrupts (&body body)
69   #!+sb-doc
70   "Allow interrupts while executing BODY. As interrupts are normally allowed,
71   this is only useful inside a WITHOUT-INTERRUPTS."
72   (let ((name (gensym)))
73     `(flet ((,name () ,@body))
74        (if *interrupts-enabled*
75            (,name)
76            (let ((*interrupts-enabled* t))
77              (when *interrupt-pending*
78                (receive-pending-interrupt))
79              (,name))))))