0.8.20.29:
authorDaniel Barlow <dan@telent.net>
Tue, 22 Mar 2005 14:02:18 +0000 (14:02 +0000)
committerDaniel Barlow <dan@telent.net>
Tue, 22 Mar 2005 14:02:18 +0000 (14:02 +0000)
Merge SB-FUTEX and SB-THREAD: the latter now requires the
former.  SBCL threads now require Linux kernel 2.6, or an NPTL
backport to 2.4 such as the Red Hat one

Lock/unlock functions take long (not int) as arguments: this makes
a difference on 64 bit ports (or would do if we had threading support
on either of them)

14 files changed:
NEWS
base-target-features.lisp-expr
src/code/cold-init.lisp
src/code/target-thread.lisp
src/code/target-unithread.lisp
src/runtime/alpha-arch.h
src/runtime/hppa-arch.h
src/runtime/linux-os.c
src/runtime/mips-arch.h
src/runtime/ppc-arch.h
src/runtime/sparc-arch.h
src/runtime/x86-64-arch.h
src/runtime/x86-arch.h
version.lisp-expr

diff --git a/NEWS b/NEWS
index 4dc064d..c872529 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,8 @@
 changes in sbcl-0.8.21 (0.9alpha.1?) relative to sbcl-0.8.20:
+  * incompatible change: thread support for non-NPTL systems has
+    been removed - locking is buggy and unreliable.  A threaded 
+    SBCL build will now refuse to start unless futex support is 
+    detected in the kernel
   * incompatible change: the top level REPL now has only an ABORT
     restart associated with it, not TOPLEVEL and ABORT as it used to.
     TOP and TOPLEVEL are now available as debugger commands for 
index 08f1a71..7f9a524 100644 (file)
 
  ;; low-level thread primitives support
  ;;
- ;; As of SBCL 0.8,  this is only supposed to work in x86 Linux, on which
- ;; system it's implemented using clone(2) and the %fs segment register.
- ;; Note that no consistent effort to audit the SBCL library code for
- ;; thread safety has been performed, so caveat executor.
+ ;; As of SBCL 0.8, this is only supposed to work in x86 Linux with
+ ;; NPTL support (usually kernel 2.6, though sme Red Hat distributions
+ ;; with older kernels also have it) and is implemented using clone(2)
+ ;; and the %fs segment register.  Note that no consistent effort to
+ ;; audit the SBCL library code for thread safety has been performed,
+ ;; so caveat executor.
  ; :sb-thread
 
- ;; Kernel support for futexes (so-called "fast userspace mutexes") is
- ;; available in Linux 2.6 and some versions of 2.4 (Red Hat vendor
- ;; kernels, possibly other vendors too).  We can take advantage of
- ;; these to do faster and probably more reliable mutex and condition
- ;; variable support.  An SBCL built with this feature will fall back
- ;; to the old system if the futex() syscall is not available at
- ;; runtime
- ; :sb-futex
-
  ;; Support for detection of unportable code (when applied to the
  ;; COMMON-LISP package, or SBCL-internal pacakges) or bad-neighbourly
  ;; code (when applied to user-level packages), relating to material
index db603e9..262e296 100644 (file)
@@ -297,8 +297,7 @@ UNIX-like systems, UNIX-STATUS is used as the status code."
       ;; see also comment at the previous SET-FLOATING-POINT-MODES
       ;; call site.
       (set-floating-point-modes
-       :traps '(:overflow #!-netbsd :invalid :divide-by-zero))
-      (sb!thread::maybe-install-futex-functions)))
+       :traps '(:overflow #!-netbsd :invalid :divide-by-zero))))
   (thread-init-or-reinit)
   (gc-reinit)
   ;; make sure TIME works correctly from saved cores
index 0bedaba..aedfa10 100644 (file)
 (sb!alien:define-alien-routine "block_sigcont"  void)
 (sb!alien:define-alien-routine "unblock_sigcont_and_sleep"  void)
 
-#!+sb-futex
 (declaim (inline futex-wait futex-wake))
-#!+sb-futex
 (sb!alien:define-alien-routine
     "futex_wait" int (word unsigned-long) (old-value unsigned-long))
-#!+sb-futex
 (sb!alien:define-alien-routine
     "futex_wake" int (word unsigned-long) (n unsigned-long))
 
 
-;;; this should only be called while holding the queue spinlock.
-;;; it releases the spinlock before sleeping
-(defun wait-on-queue (queue &optional lock)
-  (let ((pid (current-thread-id)))
-    (block-sigcont)
-    (when lock (release-mutex lock))
-    (sb!sys:without-interrupts
-     (pushnew pid (waitqueue-data queue)))
-    (setf (waitqueue-lock queue) 0)
-    (unblock-sigcont-and-sleep)))
-
-;;; this should only be called while holding the queue spinlock.  It doesn't
-;;; release it
-(defun dequeue (queue)
-  (let ((pid (current-thread-id)))
-    (sb!sys:without-interrupts     
-     (setf (waitqueue-data queue)
-          (delete pid (waitqueue-data queue))))))
-
-;;; this should only be called while holding the queue spinlock.
-(defun signal-queue-head (queue)
-  (let ((p (car (waitqueue-data queue))))
-    (when p (signal-thread-to-dequeue p))))
-
 ;;;; mutex
 
-;;; i suspect there may be a race still in this: the futex version requires
-;;; the old mutex value before sleeping, so how do we get away without it
 (defun get-mutex (lock &optional new-value (wait-p t))
   "Acquire LOCK, setting it to NEW-VALUE or some suitable default value 
 if NIL.  If WAIT-P is non-NIL and the lock is in use, sleep until it
 is available"
-  (declare (type mutex lock) (optimize (speed 3)))
-  (let ((pid (current-thread-id)))
-    (unless new-value (setf new-value pid))
-    (assert (not (eql new-value (mutex-value lock))))
-    (get-spinlock lock 2 pid)
-    (loop
-     (unless
-        ;; args are object slot-num old-value new-value
-        (sb!vm::%instance-set-conditional lock 4 nil new-value)
-       (dequeue lock)
-       (setf (waitqueue-lock lock) 0)
-       (return t))
-     (unless wait-p
-       (setf (waitqueue-lock lock) 0)
-       (return nil))
-     (wait-on-queue lock nil))))
-
-#!+sb-futex
-(defun get-mutex/futex (lock &optional new-value (wait-p t))
   (declare (type mutex lock)  (optimize (speed 3)))
   (let ((pid (current-thread-id))
        old)
@@ -159,15 +111,7 @@ is available"
      (futex-wait (mutex-value-address lock)
                 (sb!kernel:get-lisp-obj-address old)))))
 
-(defun release-mutex (lock &optional (new-value nil))
-  (declare (type mutex lock))
-  ;; we assume the lock is ours to release
-  (with-spinlock (lock)
-    (setf (mutex-value lock) new-value)
-    (signal-queue-head lock)))
-
-#!+sb-futex
-(defun release-mutex/futex (lock)
+(defun release-mutex (lock)
   (declare (type mutex lock))
   (setf (mutex-value lock) nil)
   (futex-wake (mutex-value-address lock) 1))
@@ -181,22 +125,6 @@ time we reacquire LOCK and return to the caller."
   (assert lock)
   (let ((value (mutex-value lock)))
     (unwind-protect
-        (progn
-          (get-spinlock queue 2 (current-thread-id))
-          (wait-on-queue queue lock))
-      ;; If we are interrupted while waiting, we should do these things
-      ;; before returning.  Ideally, in the case of an unhandled signal,
-      ;; we should do them before entering the debugger, but this is
-      ;; better than nothing.
-      (with-spinlock (queue)
-       (dequeue queue))
-      (get-mutex lock value))))
-
-#!+sb-futex
-(defun condition-wait/futex (queue lock)
-  (assert lock)
-  (let ((value (mutex-value lock)))
-    (unwind-protect
         (let ((me (current-thread-id)))
           ;; XXX we should do something to ensure that the result of this setf
           ;; is visible to all CPUs
@@ -218,11 +146,6 @@ time we reacquire LOCK and return to the caller."
 
 (defun condition-notify (queue)
   "Notify one of the processes waiting on QUEUE"
-  (with-spinlock (queue) (signal-queue-head queue)))
-
-#!+sb-futex
-(defun condition-notify/futex (queue)
-  "Notify one of the processes waiting on QUEUE."
   (let ((me (current-thread-id)))
     ;; no problem if >1 thread notifies during the comment in
     ;; condition-wait: as long as the value in queue-data isn't the
@@ -232,30 +155,11 @@ time we reacquire LOCK and return to the caller."
     (setf (waitqueue-data queue) me)
     (futex-wake (waitqueue-data-address queue) 1)))
 
-#!+sb-futex
-(defun condition-broadcast/futex (queue)
+(defun condition-broadcast (queue)
   (let ((me (current-thread-id)))
     (setf (waitqueue-data queue) me)
     (futex-wake (waitqueue-data-address queue) (ash 1 30))))
 
-(defun condition-broadcast (queue)
-  "Notify all of the processes waiting on QUEUE."
-  (with-spinlock (queue)
-    (map nil #'signal-thread-to-dequeue (waitqueue-data queue))))
-
-;;; Futexes may be available at compile time but not runtime, so we
-;;; default to not using them unless os_init says they're available
-(defun maybe-install-futex-functions ()
-  #!+sb-futex
-  (unless (zerop (extern-alien "linux_supports_futex" int))
-    (sb!ext:without-package-locks
-      (setf (fdefinition 'get-mutex) #'get-mutex/futex
-            (fdefinition 'release-mutex) #'release-mutex/futex
-            (fdefinition 'condition-wait) #'condition-wait/futex
-            (fdefinition 'condition-broadcast) #'condition-broadcast/futex
-            (fdefinition 'condition-notify) #'condition-notify/futex))
-    t))
-
 (defun make-thread (function)
   (let* ((real-function (coerce function 'function))
         (tid
index 89f7bb2..5d2505e 100644 (file)
@@ -141,8 +141,6 @@ time we reacquire LOCK and return to the caller."
   "Notify one of the processes waiting on QUEUE"
   (signal-queue-head queue))
 
-(defun maybe-install-futex-functions () nil)
-
 ;;;; job control
 
 (defun init-job-control () t)
index 28008db..fe6a6ef 100644 (file)
@@ -3,7 +3,7 @@
 
 
 static inline void 
-get_spinlock(lispobj *word,int value)
+get_spinlock(lispobj *word,long value)
 {
     *word=value;               /* FIXME for threads */
 }
index 42b8a1c..1c682f1 100644 (file)
@@ -3,7 +3,7 @@
 
 
 static inline void 
-get_spinlock(lispobj *word,int value)
+get_spinlock(lispobj *word,long value)
 {
     *word=value;               /* FIXME for threads */
 }
index 26304a8..077f441 100644 (file)
@@ -49,7 +49,7 @@
 #include "thread.h"
 size_t os_vm_page_size;
 
-#ifdef LISP_FEATURE_SB_FUTEX
+#ifdef LISP_FEATURE_SB_THREAD
 #include <linux/unistd.h>
 #include <errno.h>
 
@@ -73,7 +73,6 @@ _syscall4(int,sys_futex,
 #include "gc.h"
 \f
 int linux_sparc_siginfo_bug = 0;
-int linux_supports_futex=0;
 
 void os_init(void)
 {
@@ -94,17 +93,16 @@ void os_init(void)
             major_version);
     }
     if (!(major_version>2 || minor_version >= 4)) {
-#ifdef LISP_FEATURE_SB_THREAD
-       lose("linux kernel 2.4 required for thread-enabled SBCL");
-#endif
 #ifdef LISP_FEATURE_SPARC
        FSHOW((stderr,"linux kernel %d.%d predates 2.4;\n enabling workarounds for SPARC kernel bugs in signal handling.\n", major_version,minor_version));
        linux_sparc_siginfo_bug = 1;
 #endif
     }
-#ifdef LISP_FEATURE_SB_FUTEX
+#ifdef LISP_FEATURE_SB_THREAD
     futex_wait(futex,-1);
-    if(errno!=ENOSYS) linux_supports_futex=1;
+    if(errno==ENOSYS) {
+       lose("linux with NPTL support (e.g. kernel 2.6 or newer) required for thread-enabled SBCL");
+    }
 #endif
     os_vm_page_size = getpagesize();
 }
@@ -288,13 +286,10 @@ os_install_interrupt_handlers(void)
                                                 sig_stop_for_gc_handler);
     undoably_install_low_level_interrupt_handler(SIG_THREAD_EXIT,
                                                 thread_exit_handler);
-    if(!linux_supports_futex)
-       undoably_install_low_level_interrupt_handler(SIG_DEQUEUE,
-                                                    sigcont_handler);
 #endif
 }
 
-#ifdef LISP_FEATURE_SB_FUTEX
+#ifdef LISP_FEATURE_SB_THREAD
 int futex_wait(int *lock_word, int oldval) {
     int t= sys_futex(lock_word,FUTEX_WAIT,oldval, 0);
     return t;
index 50b0776..0e9a729 100644 (file)
@@ -3,7 +3,7 @@
 
 
 static inline void 
-get_spinlock(lispobj *word,int value)
+get_spinlock(lispobj *word,long value)
 {
     *word=value;               /* FIXME for threads */
 }
index cbaa670..a811ac4 100644 (file)
@@ -2,7 +2,7 @@
 #define _PPC_ARCH_H
 
 static inline void 
-get_spinlock(lispobj *word,int value)
+get_spinlock(lispobj *word,long value)
 {
     *word=value;               /* FIXME for threads */
 }
index 52c2578..d451deb 100644 (file)
@@ -2,7 +2,7 @@
 #define _SPARC_ARCH_H
 
 static inline void 
-get_spinlock(lispobj *word,int value)
+get_spinlock(lispobj *word,long value)
 {
     *word=value;               /* FIXME for threads */
 }
index a992756..bf3306b 100644 (file)
@@ -13,7 +13,7 @@
  * architecture-abstracting patches for CSR's SPARC port. -- WHN 2002-02-15) */
 
 static inline void 
-get_spinlock(lispobj *word,int value)
+get_spinlock(lispobj *word,long value)
 {
 #if 0
     u32 eax=0;
index c5498ff..439f508 100644 (file)
@@ -25,7 +25,7 @@
 extern never_returns lose(char *fmt, ...);
 
 static inline void 
-get_spinlock(volatile lispobj *word,int value)
+get_spinlock(volatile lispobj *word,long value)
 {
     u32 eax=0;
     if(*word==value) 
index 1a0c3d7..90840e9 100644 (file)
@@ -17,4 +17,4 @@
 ;;; 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".)
-"0.8.20.28"
+"0.8.20.29"