1.0.6.38: thread and interrupt safe ADD/REMOVE-METHOD
[sbcl.git] / src / code / thread.lisp
1 ;;;; support for threads needed at cross-compile time
2
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.
11
12 (in-package "SB!THREAD")
13
14 (def!struct mutex
15   #!+sb-doc
16   "Mutex type."
17   (name nil :type (or null simple-string))
18   (value nil)
19   #!+(and sb-lutex sb-thread)
20   (lutex (make-lutex)))
21
22 (def!struct spinlock
23   #!+sb-doc
24   "Spinlock type."
25   (name nil :type (or null simple-string))
26   (value nil))
27
28 (sb!xc:defmacro with-mutex ((mutex &key (value '*current-thread*) (wait-p t))
29                             &body body)
30   #!+sb-doc
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   `(call-with-mutex
35     (lambda () ,@body)
36     ,mutex
37     ,value
38     ,wait-p))
39
40 (sb!xc:defmacro with-system-mutex ((mutex &key without-gcing) &body body)
41   `(call-with-system-mutex
42     (lambda () ,@body)
43     ,mutex
44     ,without-gcing))
45
46 (sb!xc:defmacro with-recursive-lock ((mutex) &body body)
47   #!+sb-doc
48   "Acquires MUTEX for the dynamic scope of BODY. Within that scope
49 further recursive lock attempts for the same mutex succeed. It is
50 allowed to mix WITH-MUTEX and WITH-RECURSIVE-LOCK for the same mutex
51 provided the default value is used for the mutex."
52   `(call-with-recursive-lock
53     (lambda () ,@body)
54     ,mutex))
55
56 (sb!xc:defmacro with-recursive-spinlock ((spinlock) &body body)
57   `(call-with-recursive-spinlock
58     (lambda () ,@body)
59     ,spinlock))
60
61 (sb!xc:defmacro with-recursive-system-spinlock ((spinlock &key without-gcing)
62                                                 &body body)
63   `(call-with-recursive-system-spinlock
64     (lambda () ,@body)
65     ,spinlock
66     ,without-gcing))
67
68 (sb!xc:defmacro with-spinlock ((spinlock) &body body)
69   `(call-with-spinlock
70     (lambda () ,@body)
71     ,spinlock))
72
73 ;;; KLUDGE: this separate implementation for (NOT SB-THREAD) is not
74 ;;; strictly necessary; GET-MUTEX and RELEASE-MUTEX are implemented.
75 ;;; However, there would be a (possibly slight) performance hit in
76 ;;; using them.
77 #!-sb-thread
78 (progn
79   (defun call-with-system-mutex (function mutex &optional without-gcing-p)
80     (declare (ignore mutex)
81              (function function))
82     (if without-gcing-p
83         (without-gcing
84           (funcall function))
85         (without-interrupts
86           (funcall function))))
87
88   (defun call-with-recursive-system-spinlock (function lock
89                                               &optional without-gcing-p)
90     (declare (ignore lock)
91              (function function))
92     (if without-gcing-p
93         (without-gcing
94           (funcall function))
95         (without-interrupts
96           (funcall function))))
97
98   (defun call-with-mutex (function mutex value waitp)
99     (declare (ignore mutex value waitp)
100              (function function))
101     (funcall function))
102
103   (defun call-with-recursive-lock (function mutex)
104     (declare (ignore mutex) (function function))
105     (funcall function))
106
107   (defun call-with-spinlock (function spinlock)
108     (declare (ignore spinlock) (function function))
109     (funcall function))
110
111   (defun call-with-recursive-spinlock (function spinlock)
112     (declare (ignore spinlock) (function function))
113     (funcall function)))
114
115 #!+sb-thread
116 (progn
117   (defun call-with-system-mutex (function mutex &optional without-gcing-p)
118     (declare (function function))
119     (flet ((%call-with-system-mutex ()
120              (let (got-it)
121                (unwind-protect
122                     (when (setf got-it (get-mutex mutex))
123                       (funcall function))
124                  (when got-it
125                    (release-mutex mutex))))))
126       (if without-gcing-p
127           (without-gcing
128             (%call-with-system-mutex))
129           (without-interrupts
130             (%call-with-system-mutex)))))
131
132   (defun call-with-recursive-system-spinlock (function lock &optional without-gcing-p)
133     (declare (function function))
134     (flet ((%call-with-system-spinlock ()
135              (let ((inner-lock-p (eq *current-thread* (spinlock-value lock)))
136                    (got-it nil))
137                (unwind-protect
138                     (when (or inner-lock-p (setf got-it (get-spinlock lock)))
139                       (funcall function))
140                  (when got-it
141                    (release-spinlock lock))))))
142       (if without-gcing-p
143           (without-gcing
144             (%call-with-system-spinlock))
145           (without-interrupts
146             (%call-with-system-spinlock)))))
147
148   (defun call-with-mutex (function mutex value waitp)
149     (declare (function function))
150     (let ((got-it nil))
151       (without-interrupts
152         (unwind-protect
153              (when (setq got-it (allow-with-interrupts
154                                  (get-mutex mutex value waitp)))
155                (with-local-interrupts (funcall function)))
156           (when got-it
157             (release-mutex mutex))))))
158
159   (defun call-with-recursive-lock (function mutex)
160     (declare (function function))
161     (let ((inner-lock-p (eq (mutex-value mutex) *current-thread*))
162           (got-it nil))
163       (without-interrupts
164         (unwind-protect
165              (when (or inner-lock-p (setf got-it (allow-with-interrupts
166                                                   (get-mutex mutex))))
167                (with-local-interrupts (funcall function)))
168           (when got-it
169             (release-mutex mutex))))))
170
171   (defun call-with-spinlock (function spinlock)
172     (declare (function function))
173     (let ((got-it nil))
174       (without-interrupts
175         (unwind-protect
176              (when (setf got-it (allow-with-interrupts
177                                  (get-spinlock spinlock)))
178                (with-local-interrupts (funcall function)))
179           (when got-it
180             (release-spinlock spinlock))))))
181
182   (defun call-with-recursive-spinlock (function spinlock)
183     (declare (function function))
184     (let ((inner-lock-p (eq (spinlock-value spinlock) *current-thread*))
185           (got-it nil))
186       (without-interrupts
187         (unwind-protect
188              (when (or inner-lock-p (setf got-it (allow-with-interrupts
189                                                   (get-spinlock spinlock))))
190                (with-local-interrupts (funcall function)))
191           (when got-it
192             (release-spinlock spinlock)))))))