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
))
19 #!+(and sb-lutex sb-thread
)
25 (name nil
:type
(or null simple-string
))
28 (sb!xc
:defmacro with-mutex
((mutex &key
(value '*current-thread
*) (wait-p t
))
31 "Acquire MUTEX for the dynamic scope of BODY, setting it to
32 NEW-VALUE or some suitable default value if NIL. If WAIT-P is non-NIL
33 and the mutex is in use, sleep until it is available"
34 `(dx-flet ((with-mutex-thunk () ,@body
))
41 (sb!xc
:defmacro with-system-mutex
((mutex &key without-gcing
) &body body
)
42 `(dx-flet ((with-system-mutex-thunk () ,@body
))
43 (call-with-system-mutex
44 #'with-system-mutex-thunk
48 (sb!xc
:defmacro with-recursive-lock
((mutex) &body body
)
50 "Acquires MUTEX for the dynamic scope of BODY. Within that scope
51 further recursive lock attempts for the same mutex succeed. It is
52 allowed to mix WITH-MUTEX and WITH-RECURSIVE-LOCK for the same mutex
53 provided the default value is used for the mutex."
54 `(dx-flet ((with-recursive-lock-thunk () ,@body
))
55 (call-with-recursive-lock
56 #'with-recursive-lock-thunk
59 (sb!xc
:defmacro with-recursive-spinlock
((spinlock) &body body
)
60 `(dx-flet ((with-recursive-spinlock-thunk () ,@body
))
61 (call-with-recursive-spinlock
62 #'with-recursive-spinlock-thunk
65 (sb!xc
:defmacro with-recursive-system-spinlock
((spinlock &key without-gcing
)
67 `(dx-flet ((with-recursive-system-spinlock-thunk () ,@body
))
68 (call-with-recursive-system-spinlock
69 #'with-recursive-system-spinlock-thunk
73 (sb!xc
:defmacro with-spinlock
((spinlock) &body body
)
74 `(dx-flet ((with-spinlock-thunk () ,@body
))
79 ;;; KLUDGE: this separate implementation for (NOT SB-THREAD) is not
80 ;;; strictly necessary; GET-MUTEX and RELEASE-MUTEX are implemented.
81 ;;; However, there would be a (possibly slight) performance hit in
85 (defun call-with-system-mutex (function mutex
&optional without-gcing-p
)
86 (declare (ignore mutex
)
92 (allow-with-interrupts (funcall function
)))))
94 (defun call-with-system-spinlock (function spinlock
&optional without-gcing-p
)
95 (declare (ignore spinlock
)
101 (allow-with-interrupts (funcall function
)))))
103 (defun call-with-recursive-system-spinlock (function lock
104 &optional without-gcing-p
)
105 (declare (ignore lock
)
111 (allow-with-interrupts (funcall function
)))))
113 (defun call-with-mutex (function mutex value waitp
)
114 (declare (ignore mutex value waitp
)
118 (defun call-with-recursive-lock (function mutex
)
119 (declare (ignore mutex
) (function function
))
122 (defun call-with-spinlock (function spinlock
)
123 (declare (ignore spinlock
) (function function
))
126 (defun call-with-recursive-spinlock (function spinlock
)
127 (declare (ignore spinlock
) (function function
))
131 ;;; KLUDGE: These need to use DX-LET, because the cleanup form that
132 ;;; closes over GOT-IT causes a value-cell to be allocated for it -- and
133 ;;; we prefer that to go on the stack since it can.
135 (defun call-with-system-mutex (function mutex
&optional without-gcing-p
)
136 (declare (function function
))
137 (flet ((%call-with-system-mutex
()
140 (when (setf got-it
(get-mutex mutex
))
143 (release-mutex mutex
))))))
146 (%call-with-system-mutex
))
148 (allow-with-interrupts (%call-with-system-mutex
))))))
150 (defun call-with-system-spinlock (function spinlock
&optional without-gcing-p
)
151 (declare (function function
))
152 (flet ((%call-with-system-spinlock
()
155 (when (setf got-it
(get-spinlock spinlock
))
158 (release-spinlock spinlock
))))))
161 (%call-with-system-spinlock
))
163 (allow-with-interrupts (%call-with-system-spinlock
))))))
165 (defun call-with-recursive-system-spinlock (function lock
166 &optional without-gcing-p
)
167 (declare (function function
))
168 (flet ((%call-with-system-spinlock
()
169 (dx-let ((inner-lock-p (eq *current-thread
* (spinlock-value lock
)))
172 (when (or inner-lock-p
(setf got-it
(get-spinlock lock
)))
175 (release-spinlock lock
))))))
178 (%call-with-system-spinlock
))
180 (allow-with-interrupts (%call-with-system-spinlock
))))))
182 (defun call-with-spinlock (function spinlock
)
183 (declare (function function
))
184 (dx-let ((got-it nil
))
187 (when (setf got-it
(allow-with-interrupts
188 (get-spinlock spinlock
)))
189 (with-local-interrupts (funcall function
)))
191 (release-spinlock spinlock
))))))
193 (defun call-with-mutex (function mutex value waitp
)
194 (declare (function function
))
195 (dx-let ((got-it nil
))
198 (when (setq got-it
(allow-with-interrupts
199 (get-mutex mutex value waitp
)))
200 (with-local-interrupts (funcall function
)))
202 (release-mutex mutex
))))))
204 (defun call-with-recursive-lock (function mutex
)
205 (declare (function function
))
206 (dx-let ((inner-lock-p (eq (mutex-value mutex
) *current-thread
*))
210 (when (or inner-lock-p
(setf got-it
(allow-with-interrupts
212 (with-local-interrupts (funcall function
)))
214 (release-mutex mutex
))))))
218 (defun call-with-recursive-spinlock (function spinlock
)
219 (declare (function function
))
220 (dx-let ((inner-lock-p (eq (spinlock-value spinlock
) *current-thread
*))
224 (when (or inner-lock-p
(setf got-it
(allow-with-interrupts
225 (get-spinlock spinlock
))))
226 (with-local-interrupts (funcall function
)))
228 (release-spinlock spinlock
)))))))