From: Gábor M. <me...@us...> - 2009-01-09 16:44:03
|
Update of /cvsroot/sbcl/sbcl/src/code In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv22045/src/code Modified Files: target-thread.lisp Log Message: 1.0.24.26: fix release spinlock Both in the runtime and in Lisp releasing a spinlock was a simple assignment. That doesn't work because the new value may not make it to main memory by the time another CPU wants to acquire it making it needlessly slow. Worse, it also allows the CPU to reorder instructions from the critical section after the release. There is a spinlock implementation for MIPS in the runtime, but it's not used as we don't have threads on that platform. I don't know if it's broken too. Index: target-thread.lisp =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/code/target-thread.lisp,v retrieving revision 1.97 retrieving revision 1.98 diff -u -d -r1.97 -r1.98 --- target-thread.lisp 3 Dec 2008 13:13:08 -0000 1.97 +++ target-thread.lisp 9 Jan 2009 16:43:56 -0000 1.98 @@ -218,8 +218,15 @@ (defun release-spinlock (spinlock) (declare (optimize (speed 3) (safety 0))) - (setf (spinlock-value spinlock) nil) - nil) + ;; Simply setting SPINLOCK-VALUE to NIL is not enough as it does not + ;; propagate to other processors, plus without a memory barrier the + ;; CPU might reorder instructions allowing code from the critical + ;; section to leak out. Use COMPARE-AND-SWAP for the memory barrier + ;; effect and do some sanity checking while we are at it. + (unless (eq *current-thread* + (sb!ext:compare-and-swap (spinlock-value spinlock) + *current-thread* nil)) + (error "Only the owner can release the spinlock ~S." spinlock))) ;;;; mutexes |