1 ;;;; -*- indent-tabs-mode: nil -*-
3 (in-package :bordeaux-threads-2
)
9 (deftype native-thread
()
12 (defun %start-multiprocessing
()
13 (mp::startup-idle-and-top-level-loops
))
15 (defun %make-thread
(function name
)
16 ;; CMUCL doesn't like NIL names.
17 (mp:make-process function
:name
(or name
"")))
19 (defun %current-thread
()
22 (defun %thread-name
(thread)
23 (mp:process-name thread
))
25 (defun %join-thread
(thread)
26 (mp:process-join thread
))
28 (defun %thread-yield
()
32 ;;; Introspection/debugging
35 (defun %all-threads
()
38 (defun %interrupt-thread
(thread function
)
39 (mp:process-interrupt thread function
))
41 (defun %destroy-thread
(thread)
42 (mp:destroy-process thread
))
44 (defun %thread-alive-p
(thread)
45 (mp:process-active-p thread
))
49 ;;; Non-recursive locks
52 (deftype native-lock
() 'mp
::error-check-lock
)
54 (defun %make-lock
(name)
55 (mp:make-lock name
:kind
:error-check
))
57 (defun %acquire-lock
(lock waitp timeout
)
58 (if (and waitp
(null timeout
))
59 (mp::lock-wait lock
"Lock wait")
60 (mp::lock-wait-with-timeout lock
"Lock wait"
61 (if waitp timeout
0))))
63 (defun %release-lock
(lock)
64 (setf (mp::lock-process lock
) nil
))
66 (defmacro %with-lock
((place timeout
) &body body
)
67 `(mp:with-lock-held
(,place
"Lock wait" :timeout
,timeout
) ,@body
))
73 ;;; Note that the locks _are_ recursive, but not "balanced", and only
74 ;;; checked if they are being held by the same process by with-lock-held.
75 ;;; The default with-lock-held in sort of works, in that
76 ;;; it will wait for recursive locks by the same process as well.
78 (deftype native-recursive-lock
() 'mp
::recursive-lock
)
80 (defun %make-recursive-lock
(name)
81 (mp:make-lock name
:kind
:recursive
))
83 (defun %acquire-recursive-lock
(lock waitp timeout
)
84 (%acquire-lock lock waitp timeout
))
86 (defun %release-recursive-lock
(lock)
89 (defmacro %with-recursive-lock
((place timeout
) &body body
)
90 `(mp:with-lock-held
(,place
"Lock Wait" :timeout
,timeout
) ,@body
))
94 ;;; Condition variables
97 ;;; There's some stuff in x86-vm.lisp that might be worth investigating
98 ;;; whether to build on. There's also process-wait and friends.
100 (defstruct (condition-variable
101 (:constructor %make-condition-variable
(name)))
102 "Bordeaux-threads implementation of condition variables."
104 (lock (%make-lock nil
))
107 (defmethod print-object ((cv condition-variable
) stream
)
108 (print-unreadable-object (cv stream
:type t
:identity t
)
109 (format stream
"~S" (condition-variable-name cv
))))
111 (mark-not-implemented 'condition-wait
:timeout
)
112 (defun %condition-wait
(cv lock timeout
)
113 (check-type cv condition-variable
)
115 (signal-not-implemented 'condition-wait
:timeout
))
116 (%with-lock
((condition-variable-lock cv
) nil
)
117 (setf (condition-variable-active cv
) nil
))
119 (mp:process-wait
"Condition Wait"
120 #'(lambda () (condition-variable-active cv
)))
121 (%acquire-lock lock t nil
)
124 (defun %condition-notify
(cv)
125 (check-type cv condition-variable
)
126 (%with-lock
((condition-variable-lock cv
) nil
)
127 (setf (condition-variable-active cv
) t
))
130 (mark-not-implemented 'condition-broadcast
)
131 (defun %condition-broadcast
(cv)
132 (declare (ignore cv
))
133 (signal-not-implemented 'condition-broadcast
))
140 (defmacro with-timeout
((timeout) &body body
)
142 `(mp:with-timeout
(,timeout
(error 'timeout
:length
,timeout
))