release, will be tagged as sbcl_1_0_27
[sbcl/tcr.git] / src / code / thread.lisp
bloba44b7630b6328013fdddbe483db17d9814f396ee
1 ;;;; support for threads needed at cross-compile time
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
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")
14 (def!struct mutex
15 #!+sb-doc
16 "Mutex type."
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)
22 (lutex (make-lutex)))
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."
27 (mutex-%owner mutex))
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
32 ;; sufficient.
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."
45 '(setf mutex-value))
46 form)
48 (def!struct spinlock
49 #!+sb-doc
50 "Spinlock type."
51 (name nil :type (or null simple-string))
52 (value nil))
54 (sb!xc:defmacro with-mutex ((mutex &key (value '*current-thread*) (wait-p t))
55 &body body)
56 #!+sb-doc
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))
61 (call-with-mutex
62 #'with-mutex-thunk
63 ,mutex
64 ,value
65 ,wait-p)))
67 (sb!xc:defmacro with-system-mutex ((mutex
68 &key without-gcing allow-with-interrupts)
69 &body body)
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
78 ,mutex)))
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
84 ,spinlock)))
86 (sb!xc:defmacro with-recursive-lock ((mutex) &body body)
87 #!+sb-doc
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
95 ,mutex)))
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
101 ,spinlock)))
103 (sb!xc:defmacro with-recursive-system-spinlock ((spinlock
104 &key without-gcing)
105 &body body)
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
112 ,spinlock)))
114 (sb!xc:defmacro with-spinlock ((spinlock) &body body)
115 `(dx-flet ((with-spinlock-thunk () ,@body))
116 (call-with-spinlock
117 #'with-spinlock-thunk
118 ,spinlock)))
120 (macrolet ((def (name &optional variant)
121 `(defun ,(if variant (symbolicate name "/" variant) name)
122 (function mutex)
123 (declare (function function))
124 (flet ((%call-with-system-mutex ()
125 (dx-let (got-it)
126 (unwind-protect
127 (when (setf got-it (get-mutex mutex))
128 (funcall function))
129 (when got-it
130 (release-mutex mutex))))))
131 (declare (inline %call-with-system-mutex))
132 ,(ecase variant
133 (:without-gcing
134 `(without-gcing (%call-with-system-mutex)))
135 (:allow-with-interrupts
136 `(without-interrupts
137 (allow-with-interrupts (%call-with-system-mutex))))
138 ((nil)
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))
144 #!-sb-thread
145 (progn
146 (macrolet ((def (name &optional variant)
147 `(defun ,(if variant (symbolicate name "/" variant) name)
148 (function lock)
149 (declare (ignore lock) (function function))
150 ,(ecase variant
151 (:without-gcing
152 `(without-gcing (funcall function)))
153 (:allow-with-interrupts
154 `(without-interrupts
155 (allow-with-interrupts (funcall function))))
156 ((nil)
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)
164 (function function))
165 (funcall function))
167 (defun call-with-recursive-lock (function mutex)
168 (declare (ignore mutex) (function function))
169 (funcall function))
171 (defun call-with-spinlock (function spinlock)
172 (declare (ignore spinlock) (function function))
173 (funcall function))
175 (defun call-with-recursive-spinlock (function spinlock)
176 (declare (ignore spinlock) (function function))
177 (funcall function)))
179 #!+sb-thread
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.
183 (progn
184 (defun call-with-system-spinlock (function spinlock)
185 (declare (function function))
186 (without-interrupts
187 (dx-let (got-it)
188 (unwind-protect
189 (when (setf got-it (get-spinlock spinlock))
190 (funcall function))
191 (when got-it
192 (release-spinlock spinlock))))))
194 (macrolet ((def (name &optional variant)
195 `(defun ,(if variant (symbolicate name "/" variant) name)
196 (function spinlock)
197 (declare (function function))
198 (flet ((%call-with-system-spinlock ()
199 (dx-let ((inner-lock-p
200 (eq *current-thread*
201 (spinlock-value spinlock)))
202 (got-it nil))
203 (unwind-protect
204 (when (or inner-lock-p
205 (setf got-it
206 (get-spinlock spinlock)))
207 (funcall function))
208 (when got-it
209 (release-spinlock spinlock))))))
210 (declare (inline %call-with-system-spinlock))
211 ,(ecase variant
212 (:without-gcing
213 `(without-gcing (%call-with-system-spinlock)))
214 ((nil)
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))
222 (without-interrupts
223 (unwind-protect
224 (when (setf got-it (allow-with-interrupts
225 (get-spinlock spinlock)))
226 (with-local-interrupts (funcall function)))
227 (when got-it
228 (release-spinlock spinlock))))))
230 (defun call-with-mutex (function mutex value waitp)
231 (declare (function function))
232 (dx-let ((got-it nil))
233 (without-interrupts
234 (unwind-protect
235 (when (setq got-it (allow-with-interrupts
236 (get-mutex mutex value waitp)))
237 (with-local-interrupts (funcall function)))
238 (when got-it
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*))
244 (got-it nil))
245 (without-interrupts
246 (unwind-protect
247 (when (or inner-lock-p (setf got-it (allow-with-interrupts
248 (get-mutex mutex))))
249 (with-local-interrupts (funcall function)))
250 (when got-it
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*))
256 (got-it nil))
257 (without-interrupts
258 (unwind-protect
259 (when (or inner-lock-p (setf got-it (allow-with-interrupts
260 (get-spinlock spinlock))))
261 (with-local-interrupts (funcall function)))
262 (when got-it
263 (release-spinlock spinlock)))))))