X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Fsignal.lisp;h=cc2100728e4d1958aa48bfd253604c2a67591b30;hb=cf0b72cd4052a09b9a305081524bd44e2948c1e5;hp=55eb7ca7398ffdc84e6c186d687ab774df8b5f36;hpb=4898ef32c639b1c7f4ee13a5ba566ce6debd03e6;p=sbcl.git diff --git a/src/code/signal.lisp b/src/code/signal.lisp index 55eb7ca..cc21007 100644 --- a/src/code/signal.lisp +++ b/src/code/signal.lisp @@ -40,38 +40,55 @@ (defvar *interrupts-enabled* t) (defvar *interrupt-pending* nil) +;;; KLUDGE: This tells INTERRUPT-THREAD that it is being invoked as an +;;; interruption, so that if the thread being interrupted is the +;;; current thread it knows to enable interrupts. INVOKE-INTERRUPTION +;;; binds it to T, and WITHOUT-INTERRUPTS binds it to NIL, so that if +;;; interrupts are disable between INTERRUPT-THREAD and this we don't +;;; accidentally re-enable them. +(defvar *in-interruption* nil) + (sb!xc:defmacro without-interrupts (&body body) #!+sb-doc - "Execute BODY in a context impervious to interrupts." + "Execute BODY with all deferrable interrupts deferred. Deferrable interrupts +include most blockable POSIX signals, and SB-THREAD:INTERRUPT-THREAD. Does not +interfere with garbage collection, and unlike in many traditional Lisps using +userspace threads, in SBCL WITHOUT-INTERRUPTS does not inhibit scheduling of +other threads." (let ((name (gensym "WITHOUT-INTERRUPTS-BODY-"))) `(flet ((,name () ,@body)) - (if *interrupts-enabled* - (unwind-protect - (let ((*interrupts-enabled* nil)) - (,name)) - ;; If we were interrupted in the protected section, then - ;; the interrupts are still blocked and it remains so - ;; until the pending interrupt is handled. - ;; - ;; If we were not interrupted in the protected section, - ;; but here, then even if the interrupt handler enters - ;; another WITHOUT-INTERRUPTS, the pending interrupt will - ;; be handled immediately upon exit from said - ;; WITHOUT-INTERRUPTS, so it is as if nothing has - ;; happened. - (when *interrupt-pending* - (receive-pending-interrupt))) - (,name))))) + (if *interrupts-enabled* + (unwind-protect + (let ((*interrupts-enabled* nil) + (*in-interruption* nil)) + (,name)) + ;; If we were interrupted in the protected section, then + ;; the interrupts are still blocked and it remains so + ;; until the pending interrupt is handled. + ;; + ;; If we were not interrupted in the protected section, + ;; but here, then even if the interrupt handler enters + ;; another WITHOUT-INTERRUPTS, the pending interrupt will + ;; be handled immediately upon exit from said + ;; WITHOUT-INTERRUPTS, so it is as if nothing has + ;; happened. + (when *interrupt-pending* + (receive-pending-interrupt))) + (,name))))) (sb!xc:defmacro with-interrupts (&body body) #!+sb-doc "Allow interrupts while executing BODY. As interrupts are normally allowed, - this is only useful inside a WITHOUT-INTERRUPTS." +this is only useful inside a SB-SYS:WITHOUT-INTERRUPTS. Signals a runtime +warning if used inside the dynamic countour of SB-SYS:WITHOUT-GCING." (let ((name (gensym))) `(flet ((,name () ,@body)) (if *interrupts-enabled* (,name) - (let ((*interrupts-enabled* t)) - (when *interrupt-pending* - (receive-pending-interrupt)) - (,name)))))) + (progn + (when sb!kernel:*gc-inhibit* + (warn "Re-enabling interrupts while GC is inhibited.")) + (let ((*interrupts-enabled* t)) + (when *interrupt-pending* + (receive-pending-interrupt)) + (,name)))))))