(inherits (inherits-for-structure dd)))
(%compiler-defstruct dd inherits)))
+;;; finding these beasts
+(defun find-defstruct-description (name &optional (errorp t))
+ (let ((info (layout-info (classoid-layout (find-classoid name errorp)))))
+ (if (defstruct-description-p info)
+ info
+ (when errorp
+ (error "No DEFSTRUCT-DESCRIPTION for ~S." name)))))
+
+(defun structure-slot-index (type slot-name &optional (errorp t))
+ (let ((slotd (find slot-name
+ (dd-slots (find-defstruct-description type))
+ :key #'dsd-name)))
+ (if slotd
+ (dsd-index slotd)
+ (when errorp
+ (error "No slot named ~S in ~S." slot-name type)))))
+
+;;; Used internally, but it would be nice to provide something
+;;; like this for users as well.
+#!+sb-thread
+(defmacro define-structure-slot-compare-and-exchange
+ (name &key structure slot)
+ (let* ((dd (find-defstruct-description structure t))
+ (slotd (when dd (find slot (dd-slots dd) :key #'dsd-name)))
+ (type (when slotd (dsd-type slotd)))
+ (index (when slotd (dsd-index slotd))))
+ (unless index
+ (error "Slot ~S not found in ~S." slot structure))
+ `(progn
+ (declaim (inline ,name))
+ (defun ,name (instance old new)
+ (declare (type ,structure instance)
+ (type ,type new))
+ (sb!vm::%instance-set-conditional instance ,index old new)))))
+
+;;; Ditto
+#!+sb-thread
+(defmacro define-structure-slot-addressor (name &key structure slot)
+ (let* ((dd (find-defstruct-description structure t))
+ (slotd (when dd (find slot (dd-slots dd) :key #'dsd-name)))
+ (index (when slotd (dsd-index slotd))))
+ (unless index
+ (error "Slot ~S not found in ~S." slot structure))
+ `(progn
+ (declaim (inline ,name))
+ (defun ,name (instance)
+ (declare (type ,structure instance) (optimize speed))
+ (sb!ext:truly-the
+ sb!vm:word
+ (+ (sb!kernel:get-lisp-obj-address instance)
+ (- (* ,(+ sb!vm:instance-slots-offset index) sb!vm:n-word-bytes)
+ sb!vm:instance-pointer-lowtag)))))))
+
(/show0 "code/defstruct.lisp end of file")
;;; set the doc here because in early-thread FDOCUMENTATION is not
;;; available, yet
#!+sb-doc
-(setf (sb!kernel:fdocumentation '*current-thread* 'variable)
+(setf (fdocumentation '*current-thread* 'variable)
"Bound in each thread to the thread itself.")
(defstruct (thread (:constructor %make-thread))
(result-lock (make-mutex :name "thread result lock")))
#!+sb-doc
-(setf (sb!kernel:fdocumentation 'thread-name 'function)
+(setf (fdocumentation 'thread-name 'function)
"The name of the thread. Setfable.")
(def!method print-object ((thread thread) stream)
(defmacro with-lutex-address ((name lutex) &body body)
`(let ((,name ,lutex))
(with-pinned-objects (,name)
- (let ((,name (sb!kernel:get-lisp-obj-address ,name)))
+ (let ((,name (get-lisp-obj-address ,name)))
,@body))))
(defun make-lutex ()
(sb!vm::current-thread-offset-sap n))
;;;; spinlocks
+#!+sb-thread
+(define-structure-slot-compare-and-exchange
+ compare-and-exchange-spinlock-value
+ :structure spinlock
+ :slot value)
(declaim (inline get-spinlock release-spinlock))
-;;; The bare 2 here and below are offsets of the slots in the struct.
-;;; There ought to be some better way to get these numbers
(defun get-spinlock (spinlock)
(declare (optimize (speed 3) (safety 0))
#!-sb-thread
- (ignore spinlock new-value))
+ (ignore spinlock))
;; %instance-set-conditional can test for 0 (which is a fixnum) and
;; store any value
#!+sb-thread
- (loop until
- (eql (sb!vm::%instance-set-conditional spinlock 2 0 1) 0))
+ (compare-and-exchange-spinlock-value spinlock 0 1)
t)
(defun release-spinlock (spinlock)
(declare (optimize (speed 3) (safety 0))
#!-sb-thread (ignore spinlock))
;; %instance-set-conditional cannot compare arbitrary objects
- ;; meaningfully, so
- ;; (sb!vm::%instance-set-conditional spinlock 2 our-value 0)
+ ;; meaningfully, so (compare-and-exchange-spinlock-value our-value 0)
;; does not work for bignum thread ids.
#!+sb-thread
- (sb!vm::%instance-set spinlock 2 0))
+ (setf (spinlock-value spinlock) 0)
+ nil)
(defmacro with-spinlock ((spinlock) &body body)
(sb!int:with-unique-names (lock got-it)
;;;; mutexes
#!+sb-doc
-(setf (sb!kernel:fdocumentation 'make-mutex 'function)
+(setf (fdocumentation 'make-mutex 'function)
"Create a mutex."
- (sb!kernel:fdocumentation 'mutex-name 'function)
+ (fdocumentation 'mutex-name 'function)
"The name of the mutex. Setfable."
- (sb!kernel:fdocumentation 'mutex-value 'function)
+ (fdocumentation 'mutex-value 'function)
"The value of the mutex. NIL if the mutex is free. Setfable.")
#!+(and sb-thread (not sb-lutex))
(progn
- (declaim (inline mutex-value-address))
- (defun mutex-value-address (mutex)
- (declare (optimize (speed 3)))
- (sb!ext:truly-the
- sb!vm:word
- (+ (sb!kernel:get-lisp-obj-address mutex)
- (- (* 3 sb!vm:n-word-bytes) sb!vm:instance-pointer-lowtag)))))
+ (define-structure-slot-addressor mutex-value-address
+ :structure mutex
+ :slot value)
+ (define-structure-slot-compare-and-exchange
+ compare-and-exchange-mutex-value
+ :structure mutex
+ :slot value))
(defun get-mutex (mutex &optional (new-value *current-thread*) (wait-p t))
#!+sb-doc
"Acquire MUTEX, setting it to NEW-VALUE or some suitable default
-value if NIL. If WAIT-P is non-NIL and the mutex is in use, sleep
-until it is available"
+value if NIL. If WAIT-P is non-NIL and the mutex is in use, sleep
+until it is available."
(declare (type mutex mutex) (optimize (speed 3)))
(/show0 "Entering GET-MUTEX")
(unless new-value
(let (old)
(loop
(unless
- (setf old (sb!vm::%instance-set-conditional mutex 2 nil
- new-value))
+ (setf old
+ (compare-and-exchange-mutex-value mutex nil new-value))
(return t))
(unless wait-p (return nil))
(with-pinned-objects (mutex old)
(futex-wait (mutex-value-address mutex)
- (sb!kernel:get-lisp-obj-address old)))))))
+ (get-lisp-obj-address old)))))))
(defun release-mutex (mutex)
#!+sb-doc
(%make-waitqueue :name name))
#!+sb-doc
-(setf (sb!kernel:fdocumentation 'waitqueue-name 'function)
+(setf (fdocumentation 'waitqueue-name 'function)
"The name of the waitqueue. Setfable.")
#!+(and sb-thread (not sb-lutex))
-(progn
- (declaim (inline waitqueue-data-address))
- (defun waitqueue-data-address (waitqueue)
- (declare (optimize (speed 3)))
- (sb!ext:truly-the
- sb!vm:word
- (+ (sb!kernel:get-lisp-obj-address waitqueue)
- (- (* 3 sb!vm:n-word-bytes) sb!vm:instance-pointer-lowtag)))))
+(define-structure-slot-addressor waitqueue-data-address
+ :structure waitqueue
+ :slot data)
(defun condition-wait (queue mutex)
#!+sb-doc
;; Ergo, no lost wakeup
(with-pinned-objects (queue me)
(futex-wait (waitqueue-data-address queue)
- (sb!kernel:get-lisp-obj-address me))))
+ (get-lisp-obj-address me))))
;; 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
"Create a semaphore with the supplied COUNT."
(%make-semaphore :name name :count count))
-(setf (sb!kernel:fdocumentation 'semaphore-name 'function)
+(setf (fdocumentation 'semaphore-name 'function)
"The name of the semaphore. Setfable.")
(defun wait-on-semaphore (sem)
;; least accessible to users to secure their own libraries.
;; --njf, 2006-07-15
(let ((*current-thread* thread)
- (sb!kernel::*restart-clusters* nil)
- (sb!kernel::*handler-clusters* nil)
- (sb!kernel::*condition-restarts* nil)
+ (*restart-clusters* nil)
+ (*handler-clusters* nil)
+ (*condition-restarts* nil)
(sb!impl::*step-out* nil)
;; internal printer variables
(sb!impl::*previous-case* nil)
(with-pinned-objects (initial-function)
(let ((os-thread
(%create-thread
- (sb!kernel:get-lisp-obj-address initial-function))))
+ (get-lisp-obj-address initial-function))))
(when (zerop os-thread)
(error "Can't create a new thread"))
(wait-on-semaphore setup-sem)
(join-thread-error-thread c)))))
#!+sb-doc
-(setf (sb!kernel:fdocumentation 'join-thread-error-thread 'function)
+(setf (fdocumentation 'join-thread-error-thread 'function)
"The thread that we failed to join.")
(defun join-thread (thread &key (default nil defaultp))
(interrupt-thread-error-thread c)))))
#!+sb-doc
-(setf (sb!kernel:fdocumentation 'interrupt-thread-error-thread 'function)
+(setf (fdocumentation 'interrupt-thread-error-thread 'function)
"The thread that was not interrupted.")
(defmacro with-interruptions-lock ((thread) &body body)
(* sb!vm:n-word-bytes index))))
(if (eql tl-val sb!vm::no-tls-value-marker-widetag)
(sb!vm::symbol-global-value symbol)
- (sb!kernel:make-lisp-obj tl-val))))
+ (make-lisp-obj tl-val))))
(defun sb!vm::locked-symbol-global-value-add (symbol-name delta)
(sb!vm::locked-symbol-global-value-add symbol-name delta))
;;; Stepping
(defun thread-stepping ()
- (sb!kernel:make-lisp-obj
+ (make-lisp-obj
(sap-ref-word (current-thread-sap)
(* sb!vm::thread-stepping-slot sb!vm:n-word-bytes))))
(defun (setf thread-stepping) (value)
(setf (sap-ref-word (current-thread-sap)
(* sb!vm::thread-stepping-slot sb!vm:n-word-bytes))
- (sb!kernel:get-lisp-obj-address value)))
+ (get-lisp-obj-address value)))