(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
#endif
}
-static inline void
-release_spinlock(volatile lispobj *word)
-{
- *word=0;
-}
-
static inline lispobj
swap_lispobjs(volatile lispobj *dest, lispobj value)
{
return old_value;
}
+static inline void
+release_spinlock(volatile lispobj *word)
+{
+ /* A memory barrier is needed, use swap_lispobjs. See comment in
+ * RELEASE-SPINLOCK in target-thread.lisp. */
+ swap_lispobjs(word,0);
+}
+
#endif /* _X86_64_ARCH_H */
#endif
}
-static inline void
-release_spinlock(volatile lispobj *word)
-{
- *word=0;
-}
-
#include <stdio.h>
static inline lispobj
return old_value;
}
+static inline void
+release_spinlock(volatile lispobj *word)
+{
+ /* A memory barrier is needed, use swap_lispobjs. See comment in
+ * RELEASE-SPINLOCK in target-thread.lisp. */
+ swap_lispobjs(word,0);
+}
+
extern void fast_bzero_detect(void *, size_t);
extern void (*fast_bzero_pointer)(void *, size_t);
;;; checkins which aren't released. (And occasionally for internal
;;; versions, especially for internal versions off the main CVS
;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.24.25"
+"1.0.24.26"