@@ -148,6 +148,8 @@ impl WaitQueue {
148148 /// until a wakeup event.
149149 ///
150150 /// This function does not return until this thread has been awoken.
151+ ///
152+ /// Safety: `before_wait` must not panic
151153 pub fn wait < T , F : FnOnce ( ) > ( mut guard : SpinMutexGuard < ' _ , WaitVariable < T > > , before_wait : F ) {
152154 // very unsafe: check requirements of UnsafeList::push
153155 unsafe {
@@ -159,6 +161,9 @@ impl WaitQueue {
159161 drop ( guard) ;
160162 before_wait ( ) ;
161163 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`.
162167 // don't panic, this would invalidate `entry` during unwinding
163168 let eventset = rtunwrap ! ( Ok , usercalls:: wait( EV_UNPARK , WAIT_INDEFINITE ) ) ;
164169 rtassert ! ( eventset & EV_UNPARK == EV_UNPARK ) ;
@@ -169,6 +174,7 @@ impl WaitQueue {
169174 /// Adds the calling thread to the `WaitVariable`'s wait queue, then wait
170175 /// until a wakeup event or timeout. If event was observed, returns true.
171176 /// If not, it will remove the calling thread from the wait queue.
177+ /// Safety: `before_wait` must not panic
172178 pub fn wait_timeout < T , F : FnOnce ( ) > (
173179 lock : & SpinMutex < WaitVariable < T > > ,
174180 timeout : Duration ,
@@ -183,7 +189,9 @@ impl WaitQueue {
183189 let entry_lock = lock. lock ( ) . queue . inner . push ( & mut entry) ;
184190 before_wait ( ) ;
185191 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`)
187195 let mut guard = lock. lock ( ) ;
188196 let success = entry_lock. lock ( ) . wake ;
189197 if !success {
@@ -204,8 +212,8 @@ impl WaitQueue {
204212 ) -> Result < WaitGuard < ' _ , T > , SpinMutexGuard < ' _ , WaitVariable < T > > > {
205213 // SAFETY: lifetime of the pop() return value is limited to the map
206214 // 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) .
209217 unsafe {
210218 let tcs = guard. queue . inner . pop ( ) . map ( |entry| -> Tcs {
211219 let mut entry_guard = entry. lock ( ) ;
@@ -231,7 +239,7 @@ impl WaitQueue {
231239 ) -> Result < WaitGuard < ' _ , T > , SpinMutexGuard < ' _ , WaitVariable < T > > > {
232240 // SAFETY: lifetime of the pop() return values are limited to the
233241 // 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) .
235243 unsafe {
236244 let mut count = 0 ;
237245 while let Some ( entry) = guard. queue . inner . pop ( ) {
0 commit comments