From: Nikodemus S. <de...@us...> - 2007-04-29 14:04:24
|
Update of /cvsroot/sbcl/sbcl/src/code In directory sc8-pr-cvs8.sourceforge.net:/tmp/cvs-serv19002/src/code Modified Files: sysmacs.lisp target-hash-table.lisp Log Message: 1.0.5.2: non-racy WITH-SPINLOCK-AND-WITHOUT-GCING * It used to be possible for an interrupt or a GC request to come in during the small window after RECEIVE-PENDING-INTERRUPTS, but while we were running with interrupts and GC disabled. This would leave it pending and block further ones -- without any guarantee when the next one would come in. Experimentally this could also deadlock GC, but the code path leading to that is not entirely clear. * WITHOUT-GCING can be implemented by using just a single UWP, so do it like that. Index: sysmacs.lisp =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/code/sysmacs.lisp,v retrieving revision 1.27 retrieving revision 1.28 diff -u -d -r1.27 -r1.28 --- sysmacs.lisp 26 Mar 2007 10:30:30 -0000 1.27 +++ sysmacs.lisp 29 Apr 2007 14:04:17 -0000 1.28 @@ -49,11 +49,13 @@ locks, application code can never be certain that this invariant is maintained." `(unwind-protect - (without-interrupts - (let ((*gc-inhibit* t)) - ,@body)) - ;; the test is racy, but it can err only on the overeager side - (sb!kernel::maybe-handle-pending-gc))) + (let* ((*interrupts-enabled* nil) + (*gc-inhibit* t)) + ,@body) + (when (or (and *interrupts-enabled* *interrupt-pending*) + (and (not *gc-inhibit*) + (or *gc-pending* #!+sb-thread *stop-for-gc-pending*))) + (sb!unix::receive-pending-interrupt)))) ;;; EOF-OR-LOSE is a useful macro that handles EOF. Index: target-hash-table.lisp =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/code/target-hash-table.lisp,v retrieving revision 1.34 retrieving revision 1.35 diff -u -d -r1.34 -r1.35 --- target-hash-table.lisp 14 Apr 2007 12:28:15 -0000 1.34 +++ target-hash-table.lisp 29 Apr 2007 14:04:17 -0000 1.35 @@ -14,30 +14,22 @@ ;;;; utilities -;; This stuff is performance critical and unwind-protect is too -;; slow. And without the locking the next vector can get cyclic -;; causing looping in a WITHOUT-GCING form, SHRINK-VECTOR can corrupt -;; memory and who knows what else. +;;; Without the locking the next vector can get cyclic causing +;;; looping in a WITHOUT-GCING form, SHRINK-VECTOR can corrupt memory +;;; and who knows what else. +;;; +;;; WITHOUT-GCING implies WITHOUT-INTERRUPTS. (defmacro with-spinlock-and-without-gcing ((spinlock) &body body) #!-sb-thread (declare (ignore spinlock)) - (with-unique-names (old-gc-inhibit old-interrupts-enabled) - `(let ((,old-gc-inhibit *gc-inhibit*) - (,old-interrupts-enabled *interrupts-enabled*) - (*interrupts-enabled* nil) - (*gc-inhibit* t)) + `(without-gcing (unwind-protect (progn #!+sb-thread (sb!thread::get-spinlock ,spinlock) ,@body) #!+sb-thread - (sb!thread::release-spinlock ,spinlock) - (let ((*interrupts-enabled* ,old-interrupts-enabled) - (*gc-inhibit* ,old-gc-inhibit)) - ;; the test is racy, but it can err only on the overeager - ;; side - (sb!kernel::maybe-handle-pending-gc)))))) + (sb!thread::release-spinlock ,spinlock)))) (eval-when (:compile-toplevel :load-toplevel :execute) (defconstant max-hash sb!xc:most-positive-fixnum)) |