|
Lines 77-84
Link Here
|
| 77 |
Some of these primitives may be used at the low (interrupt) level and |
77 |
Some of these primitives may be used at the low (interrupt) level and |
| 78 |
some may not. |
78 |
some may not. |
| 79 |
.Pp |
79 |
.Pp |
| 80 |
There are strict ordering requirements and for some of the types this |
80 |
There are strict ordering requirements for the different lock types, |
| 81 |
is checked using the |
81 |
and for some of the types this ordering is checked using the |
| 82 |
.Xr witness 4 |
82 |
.Xr witness 4 |
| 83 |
code. |
83 |
code. |
| 84 |
.Pp |
84 |
.Pp |
|
Lines 98-106
Link Here
|
| 98 |
A non-spin mutex can be considered to be equivalent |
98 |
A non-spin mutex can be considered to be equivalent |
| 99 |
to getting a write lock on an |
99 |
to getting a write lock on an |
| 100 |
.Em rw_lock |
100 |
.Em rw_lock |
| 101 |
(see below), and in fact non-spin mutexes and rw_locks may soon become the same thing. |
101 |
(see below), and in fact non-spin mutexes and rw_locks |
| 102 |
As in spin mutexes, you either get it or you don't. |
102 |
may soon become the same thing. |
| 103 |
You may only call the |
103 |
As for spin mutexes, you either get it or you don't. |
|
|
104 |
While holding a mutex, you may only call the |
| 104 |
.Xr sleep 9 |
105 |
.Xr sleep 9 |
| 105 |
call via |
106 |
call via |
| 106 |
.Fn msleep |
107 |
.Fn msleep |
|
Lines 111-130
Link Here
|
| 111 |
as part of waking up. |
112 |
as part of waking up. |
| 112 |
This is often however a |
113 |
This is often however a |
| 113 |
.Em BAD |
114 |
.Em BAD |
| 114 |
idea because it generally relies on you having |
115 |
idea because it generally relies on you the programmer having |
| 115 |
such a good knowledge of all the call graph above you |
116 |
such a good knowledge of all the call graph above you |
| 116 |
and what assumptions it is making that there are a lot |
117 |
and what assumptions the calling code has made that there are a lot |
| 117 |
of ways to make hard-to-find mistakes. |
118 |
of ways to make hard-to-find mistakes. |
| 118 |
For example you MUST re-test all the assumptions you made before, |
119 |
For example you MUST re-test all the assumptions that were made before |
| 119 |
all the way up the call graph to where you got the lock. |
120 |
acquiring the lock, in all the levels of the call graph. |
| 120 |
You can not just assume that mtx_sleep can be inserted anywhere. |
121 |
You can not just assume that a |
| 121 |
If any caller above you has any mutex or |
122 |
.Fn mtx_sleep |
| 122 |
rwlock, your sleep, will cause a panic. |
123 |
can be inserted anywhere. |
|
|
124 |
If any caller above you holds any mutex or |
| 125 |
rwlock, your sleep will cause a panic. |
| 123 |
If the sleep only happens rarely it may be years before the |
126 |
If the sleep only happens rarely it may be years before the |
| 124 |
bad code path is found. |
127 |
bad code path is found. |
| 125 |
.Ss Pool Mutexes |
128 |
.Ss Pool Mutexes |
| 126 |
A variant of regular mutexes where the allocation of the mutex is handled |
129 |
A variant of regular mutexes where the allocation of the mutex is |
| 127 |
more by the system. |
130 |
largely handled by the system. |
| 128 |
.Ss Rw_locks |
131 |
.Ss Rw_locks |
| 129 |
Reader/writer locks allow shared access to protected data by multiple threads, |
132 |
Reader/writer locks allow shared access to protected data by multiple threads, |
| 130 |
or exclusive access by a single thread. |
133 |
or exclusive access by a single thread. |
|
Lines 173-179
Link Here
|
| 173 |
locking. |
176 |
locking. |
| 174 |
.Em rm_lock |
177 |
.Em rm_lock |
| 175 |
locks implement full priority propagation by tracking shared owners |
178 |
locks implement full priority propagation by tracking shared owners |
| 176 |
using a lock user supplied |
179 |
using a caller-supplied |
| 177 |
.Em tracker |
180 |
.Em tracker |
| 178 |
data structure. |
181 |
data structure. |
| 179 |
.Ss Sx_locks |
182 |
.Ss Sx_locks |
|
Lines 205-215
Link Here
|
| 205 |
Turnstiles are used to hold a queue of threads blocked on |
208 |
Turnstiles are used to hold a queue of threads blocked on |
| 206 |
non-sleepable locks. |
209 |
non-sleepable locks. |
| 207 |
Sleepable locks use condition variables to implement their queues. |
210 |
Sleepable locks use condition variables to implement their queues. |
| 208 |
Turnstiles differ from a sleep queue in that turnstile queue's |
211 |
Turnstiles differ from sleep queues in that turnstile queues |
| 209 |
are assigned to a lock held by an owning thread. |
212 |
are assigned to a lock held by an owning thread, whereas |
| 210 |
Thus, when one thread is enqueued onto a turnstile, it can lend its |
213 |
there is a global hash table of active sleep queues |
| 211 |
priority to the owning thread. |
214 |
Thus, when a thread running at a high priority is enqueued onto |
| 212 |
If this sounds confusing, we need to describe it better. |
215 |
a turnstile, its priority can propagate to the thread that holds |
|
|
216 |
the lock, helping to avoid a deadlock situation. |
| 213 |
.Ss Semaphores |
217 |
.Ss Semaphores |
| 214 |
.Ss Condition variables |
218 |
.Ss Condition variables |
| 215 |
Condition variables are used in conjunction with mutexes to wait for |
219 |
Condition variables are used in conjunction with mutexes to wait for |
|
Lines 329-335
Link Here
|
| 329 |
Lock order is important. |
333 |
Lock order is important. |
| 330 |
.Pp |
334 |
.Pp |
| 331 |
.Em *3 |
335 |
.Em *3 |
| 332 |
There are calls atomically release this primitive when going to sleep |
336 |
There are calls that atomically release this primitive when going to sleep |
| 333 |
and reacquire it on wakeup (e.g. |
337 |
and reacquire it on wakeup (e.g. |
| 334 |
.Fn mtx_sleep , |
338 |
.Fn mtx_sleep , |
| 335 |
.Fn rw_sleep |
339 |
.Fn rw_sleep |