Repository: tokio-rs/tokio
File: tokio/src/runtime/task/mod.rs (Rust)

Code before:
//!
//!  * The Notified reference has exclusive access to the `queue_next` field.
//!
//!  * The `owner_id` field can be set as part of construction of the task, but
//!    is otherwise immutable and anyone can access the field immutably without
//!    synchronization.
//!
//!  * If COMPLETE is one, then the JoinHandle has exclusive access to the
//!    stage field. If COMPLETE is zero, then the RUNNING bitfield functions as
//!    a lock for the stage field, and it can be accessed only by the thread
//!    that set RUNNING to one.
//!
//!  * The waker field may be concurrently accessed by different threads: in one
//!    thread the runtime may complete a task and *read* the waker field to
//!    invoke the waker, and in another thread the task's JoinHandle may be
//!    polled, and if the task hasn't yet completed, the JoinHandle may *write*
//!    a waker to the waker field. The JOIN_WAKER bit ensures safe access by
//!    multiple threads to the waker field using the following rules:
//!
//!    1. JOIN_WAKER is initialized to zero.
//!
//!    2. If JOIN_WAKER is zero, then the JoinHandle has exclusive (mutable)
//!       access to the waker field.
//!
//!    3. If JOIN_WAKER is one, then the JoinHandle and the runtime have shared
//!       (read-only) access to the waker field.
//!
//!    4. If the JoinHandle needs to write to the waker field, then the
//!       JoinHandle needs to (i) successfully set JOIN_WAKER to zero if it is
//!       not already zero to gain exclusive access to the waker field per rule
//!       2, (ii) write a waker, and (iii) successfully set JOIN_WAKER to one.
//!
//!    5. The JoinHandle can change JOIN_WAKER only if COMPLETE is zero (i.e.
//!       the task hasn't yet completed).
//!
//!    Rule 5 implies that the steps (i) or (iii) of rule 4 may fail due to a
//!    race. If step (i) fails, then the attempt to write a waker is aborted. If
//!    step (iii) fails because COMPLETE is set to one by another thread after
//!    step (i), then the waker field is cleared. Once COMPLETE is one (i.e.
//!    task has completed), the JoinHandle will not modify JOIN_WAKER. After the
//!    runtime sets COMPLETE to one, it invokes the waker if there is one.
//!
//! All other fields are immutable and can be accessed immutably without
//! synchronization by anyone.
//!
//! # Safety
//!
//! This section goes through various situations and explains why the API is
//! safe in that situation.
//!
//! ## Polling or dropping the future

Review comment (security):
The runtime only has read-only access when COMPLETE is one. If you don't do this, then the JoinHandle is taking away permissions of the runtime in step 4 (i), which is normally not allowed in rule-sets for atomics.

Code after:
//!
//!  * The Notified reference has exclusive access to the `queue_next` field.
//!
//!  * The `owner_id` field can be set as part of construction of the task, but
//!    is otherwise immutable and anyone can access the field immutably without
//!    synchronization.
//!
//!  * If COMPLETE is one, then the JoinHandle has exclusive access to the
//!    stage field. If COMPLETE is zero, then the RUNNING bitfield functions as
//!    a lock for the stage field, and it can be accessed only by the thread
//!    that set RUNNING to one.
//!
//!  * The waker field may be concurrently accessed by different threads: in one
//!    thread the runtime may complete a task and *read* the waker field to
//!    invoke the waker, and in another thread the task's JoinHandle may be
//!    polled, and if the task hasn't yet completed, the JoinHandle may *write*
//!    a waker to the waker field. The JOIN_WAKER bit ensures safe access by
//!    multiple threads to the waker field using the following rules:
//!
//!    1. JOIN_WAKER is initialized to zero.
//!
//!    2. If JOIN_WAKER is zero, then the JoinHandle has exclusive (mutable)
//!       access to the waker field.
//!
//!    3. If JOIN_WAKER is one, then the JoinHandle has shared (read-only)
//!       access to the waker field.
//!
//!    4. If JOIN_WAKER is one and COMPLETE is one, then the runtime has shared
//!       (read-only) access to the waker field.
//!
//!    5. If the JoinHandle needs to write to the waker field, then the
//!       JoinHandle needs to (i) successfully set JOIN_WAKER to zero if it is
//!       not already zero to gain exclusive access to the waker field per rule
//!       2, (ii) write a waker, and (iii) successfully set JOIN_WAKER to one.
//!
//!    6. The JoinHandle can change JOIN_WAKER only if COMPLETE is zero (i.e.
//!       the task hasn't yet completed).
//!
//!    Rule 6 implies that the steps (i) or (iii) of rule 5 may fail due to a
//!    race. If step (i) fails, then the attempt to write a waker is aborted. If
//!    step (iii) fails because COMPLETE is set to one by another thread after
//!    step (i), then the waker field is cleared. Once COMPLETE is one (i.e.
//!    task has completed), the JoinHandle will not modify JOIN_WAKER. After the
//!    runtime sets COMPLETE to one, it invokes the waker if there is one.
//!
//! All other fields are immutable and can be accessed immutably without
//! synchronization by anyone.
//!
//! # Safety
//!
//! This section goes through various situations and explains why the API is