@@ -148,6 +148,8 @@ impl WaitQueue {
148
148
/// until a wakeup event.
149
149
///
150
150
/// This function does not return until this thread has been awoken.
151
+ ///
152
+ /// Safety: `before_wait` must not panic
151
153
pub fn wait < T , F : FnOnce ( ) > ( mut guard : SpinMutexGuard < ' _ , WaitVariable < T > > , before_wait : F ) {
152
154
// very unsafe: check requirements of UnsafeList::push
153
155
unsafe {
@@ -159,6 +161,9 @@ impl WaitQueue {
159
161
drop ( guard) ;
160
162
before_wait ( ) ;
161
163
while !entry. lock ( ) . wake {
164
+ // `entry.wake` is only set in `notify_one` and `notify_all` functions. Both ensure
165
+ // the entry is removed from the queue _before_ setting this bool. There are no
166
+ // other references to `entry`.
162
167
// don't panic, this would invalidate `entry` during unwinding
163
168
let eventset = rtunwrap ! ( Ok , usercalls:: wait( EV_UNPARK , WAIT_INDEFINITE ) ) ;
164
169
rtassert ! ( eventset & EV_UNPARK == EV_UNPARK ) ;
@@ -169,6 +174,7 @@ impl WaitQueue {
169
174
/// Adds the calling thread to the `WaitVariable`'s wait queue, then wait
170
175
/// until a wakeup event or timeout. If event was observed, returns true.
171
176
/// If not, it will remove the calling thread from the wait queue.
177
+ /// Safety: `before_wait` must not panic
172
178
pub fn wait_timeout < T , F : FnOnce ( ) > (
173
179
lock : & SpinMutex < WaitVariable < T > > ,
174
180
timeout : Duration ,
@@ -183,7 +189,9 @@ impl WaitQueue {
183
189
let entry_lock = lock. lock ( ) . queue . inner . push ( & mut entry) ;
184
190
before_wait ( ) ;
185
191
usercalls:: wait_timeout ( EV_UNPARK , timeout, || entry_lock. lock ( ) . wake ) ;
186
- // acquire the wait queue's lock first to avoid deadlock.
192
+ // acquire the wait queue's lock first to avoid deadlock
193
+ // and ensure no other function can simultaneously access the list
194
+ // (e.g., `notify_one` or `notify_all`)
187
195
let mut guard = lock. lock ( ) ;
188
196
let success = entry_lock. lock ( ) . wake ;
189
197
if !success {
@@ -204,8 +212,8 @@ impl WaitQueue {
204
212
) -> Result < WaitGuard < ' _ , T > , SpinMutexGuard < ' _ , WaitVariable < T > > > {
205
213
// SAFETY: lifetime of the pop() return value is limited to the map
206
214
// closure (The closure return value is 'static). The underlying
207
- // stack frame won't be freed until after the WaitGuard created below
208
- // is dropped.
215
+ // stack frame won't be freed until after the lock on the queue is released
216
+ // (i.e., `guard` is dropped) .
209
217
unsafe {
210
218
let tcs = guard. queue . inner . pop ( ) . map ( |entry| -> Tcs {
211
219
let mut entry_guard = entry. lock ( ) ;
@@ -231,7 +239,7 @@ impl WaitQueue {
231
239
) -> Result < WaitGuard < ' _ , T > , SpinMutexGuard < ' _ , WaitVariable < T > > > {
232
240
// SAFETY: lifetime of the pop() return values are limited to the
233
241
// while loop body. The underlying stack frames won't be freed until
234
- // after the WaitGuard created below is dropped.
242
+ // after the lock on the queue is released (i.e., `guard` is dropped) .
235
243
unsafe {
236
244
let mut count = 0 ;
237
245
while let Some ( entry) = guard. queue . inner . pop ( ) {
0 commit comments