1 ;;;; support for threads needed at cross-compile time
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
12 (in-package "SB!THREAD")
17 (name nil
:type
(or null simple-string
))
18 (%owner nil
:type
(or null thread
))
19 #!+(and (not sb-lutex
) sb-thread
)
20 (state 0 :type fixnum
)
21 #!+(and sb-lutex sb-thread
)
24 (defun mutex-value (mutex)
25 "Current owner of the mutex, NIL if the mutex is free. May return a
26 stale value, use MUTEX-OWNER instead."
29 (defun holding-mutex-p (mutex)
30 "Test whether the current thread is holding MUTEX."
31 ;; This is about the only use for which a stale value of owner is
33 (eq sb
!thread
:*current-thread
* (mutex-%owner mutex
)))
35 (defsetf mutex-value set-mutex-value
)
37 (declaim (inline set-mutex-value
))
38 (defun set-mutex-value (mutex value
)
39 (declare (ignore mutex value
))
40 (error "~S is no longer supported." '(setf mutex-value
)))
42 (define-compiler-macro set-mutex-value
(&whole form mutex value
)
43 (declare (ignore mutex value
))
44 (warn "~S is no longer supported, and will signal an error at runtime."
51 (name nil
:type
(or null simple-string
))
54 (sb!xc
:defmacro with-mutex
((mutex &key
(value '*current-thread
*) (wait-p t
))
57 "Acquire MUTEX for the dynamic scope of BODY, setting it to
58 NEW-VALUE or some suitable default value if NIL. If WAIT-P is non-NIL
59 and the mutex is in use, sleep until it is available"
60 `(dx-flet ((with-mutex-thunk () ,@body
))
67 (sb!xc
:defmacro with-system-mutex
((mutex
68 &key without-gcing allow-with-interrupts
)
70 `(dx-flet ((with-system-mutex-thunk () ,@body
))
71 (,(cond (without-gcing
72 'call-with-system-mutex
/without-gcing
)
73 (allow-with-interrupts
74 'call-with-system-mutex
/allow-with-interrupts
)
76 'call-with-system-mutex
))
77 #'with-system-mutex-thunk
80 (sb!xc
:defmacro with-system-spinlock
((spinlock &key
) &body body
)
81 `(dx-flet ((with-system-spinlock-thunk () ,@body
))
82 (call-with-system-spinlock
83 #'with-system-spinlock-thunk
86 (sb!xc
:defmacro with-recursive-lock
((mutex) &body body
)
88 "Acquires MUTEX for the dynamic scope of BODY. Within that scope
89 further recursive lock attempts for the same mutex succeed. It is
90 allowed to mix WITH-MUTEX and WITH-RECURSIVE-LOCK for the same mutex
91 provided the default value is used for the mutex."
92 `(dx-flet ((with-recursive-lock-thunk () ,@body
))
93 (call-with-recursive-lock
94 #'with-recursive-lock-thunk
97 (sb!xc
:defmacro with-recursive-spinlock
((spinlock) &body body
)
98 `(dx-flet ((with-recursive-spinlock-thunk () ,@body
))
99 (call-with-recursive-spinlock
100 #'with-recursive-spinlock-thunk
103 (sb!xc
:defmacro with-recursive-system-spinlock
((spinlock
106 `(dx-flet ((with-recursive-system-spinlock-thunk () ,@body
))
107 (,(cond (without-gcing
108 'call-with-recursive-system-spinlock
/without-gcing
)
110 'call-with-recursive-system-spinlock
))
111 #'with-recursive-system-spinlock-thunk
114 (sb!xc
:defmacro with-spinlock
((spinlock) &body body
)
115 `(dx-flet ((with-spinlock-thunk () ,@body
))
117 #'with-spinlock-thunk
120 (macrolet ((def (name &optional variant
)
121 `(defun ,(if variant
(symbolicate name
"/" variant
) name
)
123 (declare (function function
))
124 (flet ((%call-with-system-mutex
()
127 (when (setf got-it
(get-mutex mutex
))
130 (release-mutex mutex
))))))
131 (declare (inline %call-with-system-mutex
))
134 `(without-gcing (%call-with-system-mutex
)))
135 (:allow-with-interrupts
137 (allow-with-interrupts (%call-with-system-mutex
))))
139 `(without-interrupts (%call-with-system-mutex
))))))))
140 (def call-with-system-mutex
)
141 (def call-with-system-mutex
:without-gcing
)
142 (def call-with-system-mutex
:allow-with-interrupts
))
146 (macrolet ((def (name &optional variant
)
147 `(defun ,(if variant
(symbolicate name
"/" variant
) name
)
149 (declare (ignore lock
) (function function
))
152 `(without-gcing (funcall function
)))
153 (:allow-with-interrupts
155 (allow-with-interrupts (funcall function
))))
157 `(without-interrupts (funcall function
)))))))
158 (def call-with-system-spinlock
)
159 (def call-with-recursive-system-spinlock
)
160 (def call-with-recursive-system-spinlock
:without-gcing
))
162 (defun call-with-mutex (function mutex value waitp
)
163 (declare (ignore mutex value waitp
)
167 (defun call-with-recursive-lock (function mutex
)
168 (declare (ignore mutex
) (function function
))
171 (defun call-with-spinlock (function spinlock
)
172 (declare (ignore spinlock
) (function function
))
175 (defun call-with-recursive-spinlock (function spinlock
)
176 (declare (ignore spinlock
) (function function
))
180 ;;; KLUDGE: These need to use DX-LET, because the cleanup form that
181 ;;; closes over GOT-IT causes a value-cell to be allocated for it --
182 ;;; and we prefer that to go on the stack since it can.
184 (defun call-with-system-spinlock (function spinlock
)
185 (declare (function function
))
189 (when (setf got-it
(get-spinlock spinlock
))
192 (release-spinlock spinlock
))))))
194 (macrolet ((def (name &optional variant
)
195 `(defun ,(if variant
(symbolicate name
"/" variant
) name
)
197 (declare (function function
))
198 (flet ((%call-with-system-spinlock
()
199 (dx-let ((inner-lock-p
201 (spinlock-value spinlock
)))
204 (when (or inner-lock-p
206 (get-spinlock spinlock
)))
209 (release-spinlock spinlock
))))))
210 (declare (inline %call-with-system-spinlock
))
213 `(without-gcing (%call-with-system-spinlock
)))
215 `(without-interrupts (%call-with-system-spinlock
))))))))
216 (def call-with-recursive-system-spinlock
)
217 (def call-with-recursive-system-spinlock
:without-gcing
))
219 (defun call-with-spinlock (function spinlock
)
220 (declare (function function
))
221 (dx-let ((got-it nil
))
224 (when (setf got-it
(allow-with-interrupts
225 (get-spinlock spinlock
)))
226 (with-local-interrupts (funcall function
)))
228 (release-spinlock spinlock
))))))
230 (defun call-with-mutex (function mutex value waitp
)
231 (declare (function function
))
232 (dx-let ((got-it nil
))
235 (when (setq got-it
(allow-with-interrupts
236 (get-mutex mutex value waitp
)))
237 (with-local-interrupts (funcall function
)))
239 (release-mutex mutex
))))))
241 (defun call-with-recursive-lock (function mutex
)
242 (declare (function function
))
243 (dx-let ((inner-lock-p (eq (mutex-%owner mutex
) *current-thread
*))
247 (when (or inner-lock-p
(setf got-it
(allow-with-interrupts
249 (with-local-interrupts (funcall function
)))
251 (release-mutex mutex
))))))
253 (defun call-with-recursive-spinlock (function spinlock
)
254 (declare (function function
))
255 (dx-let ((inner-lock-p (eq (spinlock-value spinlock
) *current-thread
*))
259 (when (or inner-lock-p
(setf got-it
(allow-with-interrupts
260 (get-spinlock spinlock
))))
261 (with-local-interrupts (funcall function
)))
263 (release-spinlock spinlock
)))))))