diff options
| author | Raoul Strackx <raoul.strackx@fortanix.com> | 2023-05-15 15:10:25 +0200 |
|---|---|---|
| committer | Raoul Strackx <raoul.strackx@fortanix.com> | 2023-07-31 12:59:42 +0200 |
| commit | 9a5443fe21bfaba77a4c872ec76b8e828bb265c0 (patch) | |
| tree | 17a413dd300624e7efeb0335fe60ebf8381765e1 /library/std/src | |
| parent | 5082281609a7c3bcba0292b0db6a0d3e20bf9549 (diff) | |
| download | rust-9a5443fe21bfaba77a4c872ec76b8e828bb265c0.tar.gz rust-9a5443fe21bfaba77a4c872ec76b8e828bb265c0.zip | |
`waitqueue` clarifications for SGX platform
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/sys/sgx/waitqueue/mod.rs | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/library/std/src/sys/sgx/waitqueue/mod.rs b/library/std/src/sys/sgx/waitqueue/mod.rs index 5e1d859ee99..32328123f73 100644 --- a/library/std/src/sys/sgx/waitqueue/mod.rs +++ b/library/std/src/sys/sgx/waitqueue/mod.rs @@ -148,6 +148,8 @@ impl WaitQueue { /// until a wakeup event. /// /// This function does not return until this thread has been awoken. + /// + /// Safety: `before_wait` must not panic pub fn wait<T, F: FnOnce()>(mut guard: SpinMutexGuard<'_, WaitVariable<T>>, before_wait: F) { // very unsafe: check requirements of UnsafeList::push unsafe { @@ -159,6 +161,9 @@ impl WaitQueue { drop(guard); before_wait(); while !entry.lock().wake { + // `entry.wake` is only set in `notify_one` and `notify_all` functions. Both ensure + // the entry is removed from the queue _before_ setting this bool. There are no + // other references to `entry`. // don't panic, this would invalidate `entry` during unwinding let eventset = rtunwrap!(Ok, usercalls::wait(EV_UNPARK, WAIT_INDEFINITE)); rtassert!(eventset & EV_UNPARK == EV_UNPARK); @@ -169,6 +174,7 @@ impl WaitQueue { /// Adds the calling thread to the `WaitVariable`'s wait queue, then wait /// until a wakeup event or timeout. If event was observed, returns true. /// If not, it will remove the calling thread from the wait queue. + /// Safety: `before_wait` must not panic pub fn wait_timeout<T, F: FnOnce()>( lock: &SpinMutex<WaitVariable<T>>, timeout: Duration, @@ -183,7 +189,9 @@ impl WaitQueue { let entry_lock = lock.lock().queue.inner.push(&mut entry); before_wait(); usercalls::wait_timeout(EV_UNPARK, timeout, || entry_lock.lock().wake); - // acquire the wait queue's lock first to avoid deadlock. + // acquire the wait queue's lock first to avoid deadlock + // and ensure no other function can simultaneously access the list + // (e.g., `notify_one` or `notify_all`) let mut guard = lock.lock(); let success = entry_lock.lock().wake; if !success { @@ -204,8 +212,8 @@ impl WaitQueue { ) -> Result<WaitGuard<'_, T>, SpinMutexGuard<'_, WaitVariable<T>>> { // SAFETY: lifetime of the pop() return value is limited to the map // closure (The closure return value is 'static). The underlying - // stack frame won't be freed until after the WaitGuard created below - // is dropped. + // stack frame won't be freed until after the lock on the queue is released + // (i.e., `guard` is dropped). unsafe { let tcs = guard.queue.inner.pop().map(|entry| -> Tcs { let mut entry_guard = entry.lock(); @@ -231,7 +239,7 @@ impl WaitQueue { ) -> Result<WaitGuard<'_, T>, SpinMutexGuard<'_, WaitVariable<T>>> { // SAFETY: lifetime of the pop() return values are limited to the // while loop body. The underlying stack frames won't be freed until - // after the WaitGuard created below is dropped. + // after the lock on the queue is released (i.e., `guard` is dropped). unsafe { let mut count = 0; while let Some(entry) = guard.queue.inner.pop() { |
