Skip to main content

tokio/runtime/time/
entry.rs

1//! Timer state structures.
2//!
3//! This module contains the heart of the intrusive timer implementation, and as
4//! such the structures inside are full of tricky concurrency and unsafe code.
5//!
6//! # Ground rules
7//!
8//! The heart of the timer implementation here is the [`TimerShared`] structure,
9//! shared between the [`TimerEntry`] and the driver. Generally, we permit access
10//! to [`TimerShared`] ONLY via either 1) a mutable reference to [`TimerEntry`] or
11//! 2) a held driver lock.
12//!
13//! It follows from this that any changes made while holding BOTH 1 and 2 will
14//! be reliably visible, regardless of ordering. This is because of the `acq/rel`
15//! fences on the driver lock ensuring ordering with 2, and rust mutable
16//! reference rules for 1 (a mutable reference to an object can't be passed
17//! between threads without an `acq/rel` barrier, and same-thread we have local
18//! happens-before ordering).
19//!
20//! # State field
21//!
22//! Each timer has a state field associated with it. This field contains either
23//! the current scheduled time, or a special flag value indicating its state.
24//! This state can either indicate that the timer is on the 'pending' queue (and
25//! thus will be fired with an `Ok(())` result soon) or that it has already been
26//! fired/deregistered.
27//!
28//! This single state field allows for code that is firing the timer to
29//! synchronize with any racing `reset` calls reliably.
30//!
31//! # Registered vs true timeouts
32//!
33//! To allow for the use case of a timeout that is periodically reset before
34//! expiration to be as lightweight as possible, we support optimistically
35//! lock-free timer resets, in the case where a timer is rescheduled to a later
36//! point than it was originally scheduled for.
37//!
38//! This is accomplished by lazily rescheduling timers. That is, we update the
39//! state field with the true expiration of the timer from the holder of
40//! the [`TimerEntry`]. When the driver services timers (ie, whenever it's
41//! walking lists of timers), it checks this "true when" value, and reschedules
42//! based on it.
43//!
44//! We do, however, also need to track what the expiration time was when we
45//! originally registered the timer; this is used to locate the right linked
46//! list when the timer is being cancelled.
47//! This is referred to as the `registered_when` internally.
48//!
49//! There is of course a race condition between timer reset and timer
50//! expiration. If the driver fails to observe the updated expiration time, it
51//! could trigger expiration of the timer too early. However, because
52//! [`mark_pending`][mark_pending] performs a compare-and-swap, it will identify this race and
53//! refuse to mark the timer as pending.
54//!
55//! [mark_pending]: TimerHandle::mark_pending
56
57use crate::loom::cell::UnsafeCell;
58use crate::loom::sync::atomic::AtomicU64;
59use crate::loom::sync::atomic::Ordering;
60
61use crate::runtime::scheduler;
62use crate::sync::AtomicWaker;
63use crate::util::linked_list;
64
65use pin_project_lite::pin_project;
66use std::task::{Context, Poll, Waker};
67use std::{marker::PhantomPinned, pin::Pin, ptr::NonNull};
68
69type TimerResult = Result<(), crate::time::error::Error>;
70
71pub(in crate::runtime::time) const STATE_DEREGISTERED: u64 = u64::MAX;
72const STATE_PENDING_FIRE: u64 = STATE_DEREGISTERED - 1;
73const STATE_MIN_VALUE: u64 = STATE_PENDING_FIRE;
74/// The largest safe integer to use for ticks.
75///
76/// This value should be updated if any other signal values are added above.
77pub(super) const MAX_SAFE_MILLIS_DURATION: u64 = STATE_MIN_VALUE - 1;
78
79/// This structure holds the current shared state of the timer - its scheduled
80/// time (if registered), or otherwise the result of the timer completing, as
81/// well as the registered waker.
82///
83/// Generally, the `StateCell` is only permitted to be accessed from two contexts:
84/// Either a thread holding the corresponding `&mut TimerEntry`, or a thread
85/// holding the timer driver lock. The write actions on the `StateCell` amount to
86/// passing "ownership" of the `StateCell` between these contexts; moving a timer
87/// from the `TimerEntry` to the driver requires _both_ holding the `&mut
88/// TimerEntry` and the driver lock, while moving it back (firing the timer)
89/// requires only the driver lock.
90pub(super) struct StateCell {
91    /// Holds either the scheduled expiration time for this timer, or (if the
92    /// timer has been fired and is unregistered), `u64::MAX`.
93    state: AtomicU64,
94    /// If the timer is fired (an Acquire order read on state shows
95    /// `u64::MAX`), holds the result that should be returned from
96    /// polling the timer. Otherwise, the contents are unspecified and reading
97    /// without holding the driver lock is undefined behavior.
98    result: UnsafeCell<TimerResult>,
99    /// The currently-registered waker
100    waker: AtomicWaker,
101}
102
103impl Default for StateCell {
104    fn default() -> Self {
105        Self::new()
106    }
107}
108
109impl std::fmt::Debug for StateCell {
110    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111        write!(f, "StateCell({:?})", self.read_state())
112    }
113}
114
115impl StateCell {
116    fn new() -> Self {
117        Self {
118            state: AtomicU64::new(STATE_DEREGISTERED),
119            result: UnsafeCell::new(Ok(())),
120            waker: AtomicWaker::new(),
121        }
122    }
123
124    fn is_pending(&self) -> bool {
125        self.state.load(Ordering::Relaxed) == STATE_PENDING_FIRE
126    }
127
128    /// Returns the current expiration time, or None if not currently scheduled.
129    fn when(&self) -> Option<u64> {
130        let cur_state = self.state.load(Ordering::Relaxed);
131
132        if cur_state == STATE_DEREGISTERED {
133            None
134        } else {
135            Some(cur_state)
136        }
137    }
138
139    /// If the timer is completed, returns the result of the timer. Otherwise,
140    /// returns None and registers the waker.
141    fn poll(&self, waker: &Waker) -> Poll<TimerResult> {
142        // We must register first. This ensures that either `fire` will
143        // observe the new waker, or we will observe a racing fire to have set
144        // the state, or both.
145        self.waker.register_by_ref(waker);
146
147        self.read_state()
148    }
149
150    fn read_state(&self) -> Poll<TimerResult> {
151        let cur_state = self.state.load(Ordering::Acquire);
152
153        if cur_state == STATE_DEREGISTERED {
154            // SAFETY: The driver has fired this timer; this involves writing
155            // the result, and then writing (with release ordering) the state
156            // field.
157            Poll::Ready(unsafe { self.result.with(|p| *p) })
158        } else {
159            Poll::Pending
160        }
161    }
162
163    /// Marks this timer as being moved to the pending list, if its scheduled
164    /// time is not after `not_after`.
165    ///
166    /// If the timer is scheduled for a time after `not_after`, returns an Err
167    /// containing the current scheduled time.
168    ///
169    /// SAFETY: Must hold the driver lock.
170    unsafe fn mark_pending(&self, not_after: u64) -> Result<(), u64> {
171        // Quick initial debug check to see if the timer is already fired. Since
172        // firing the timer can only happen with the driver lock held, we know
173        // we shouldn't be able to "miss" a transition to a fired state, even
174        // with relaxed ordering.
175        let mut cur_state = self.state.load(Ordering::Relaxed);
176
177        loop {
178            // improve the error message for things like
179            // https://github.com/tokio-rs/tokio/issues/3675
180            assert!(
181                cur_state < STATE_MIN_VALUE,
182                "mark_pending called when the timer entry is in an invalid state"
183            );
184
185            if cur_state > not_after {
186                break Err(cur_state);
187            }
188
189            match self.state.compare_exchange_weak(
190                cur_state,
191                STATE_PENDING_FIRE,
192                Ordering::AcqRel,
193                Ordering::Acquire,
194            ) {
195                Ok(_) => break Ok(()),
196                Err(actual_state) => cur_state = actual_state,
197            }
198        }
199    }
200
201    /// Fires the timer, setting the result to the provided result.
202    ///
203    /// Returns:
204    /// * `Some(waker)` - if fired and a waker needs to be invoked once the
205    ///   driver lock is released
206    /// * `None` - if fired and a waker does not need to be invoked, or if
207    ///   already fired
208    ///
209    /// SAFETY: The driver lock must be held.
210    unsafe fn fire(&self, result: TimerResult) -> Option<Waker> {
211        // Quick initial check to see if the timer is already fired. Since
212        // firing the timer can only happen with the driver lock held, we know
213        // we shouldn't be able to "miss" a transition to a fired state, even
214        // with relaxed ordering.
215        let cur_state = self.state.load(Ordering::Relaxed);
216        if cur_state == STATE_DEREGISTERED {
217            return None;
218        }
219
220        // SAFETY: We assume the driver lock is held and the timer is not
221        // fired, so only the driver is accessing this field.
222        //
223        // We perform a release-ordered store to state below, to ensure this
224        // write is visible before the state update is visible.
225        unsafe { self.result.with_mut(|p| *p = result) };
226
227        self.state.store(STATE_DEREGISTERED, Ordering::Release);
228
229        self.waker.take_waker()
230    }
231
232    /// Marks the timer as registered (poll will return None) and sets the
233    /// expiration time.
234    ///
235    /// While this function is memory-safe, it should only be called from a
236    /// context holding both `&mut TimerEntry` and the driver lock.
237    fn set_expiration(&self, timestamp: u64) {
238        debug_assert!(timestamp < STATE_MIN_VALUE);
239
240        // We can use relaxed ordering because we hold the driver lock and will
241        // fence when we release the lock.
242        self.state.store(timestamp, Ordering::Relaxed);
243    }
244
245    /// Attempts to adjust the timer to a new timestamp.
246    ///
247    /// If the timer has already been fired, is pending firing, or the new
248    /// timestamp is earlier than the old timestamp, (or occasionally
249    /// spuriously) returns Err without changing the timer's state. In this
250    /// case, the timer must be deregistered and re-registered.
251    fn extend_expiration(&self, new_timestamp: u64) -> Result<(), ()> {
252        let mut prior = self.state.load(Ordering::Relaxed);
253        loop {
254            if new_timestamp < prior || prior >= STATE_MIN_VALUE {
255                return Err(());
256            }
257
258            match self.state.compare_exchange_weak(
259                prior,
260                new_timestamp,
261                Ordering::AcqRel,
262                Ordering::Acquire,
263            ) {
264                Ok(_) => return Ok(()),
265                Err(true_prior) => prior = true_prior,
266            }
267        }
268    }
269
270    /// Returns true if the state of this timer indicates that the timer might
271    /// be registered with the driver. This check is performed with relaxed
272    /// ordering, but is conservative - if it returns false, the timer is
273    /// definitely _not_ registered.
274    pub(super) fn might_be_registered(&self) -> bool {
275        self.state.load(Ordering::Relaxed) != STATE_DEREGISTERED
276    }
277}
278
279pin_project! {
280    // A timer entry.
281    //
282    // This is the handle to a timer that is controlled by the requester of the
283    // timer. As this participates in intrusive data structures, it must be pinned
284    // before polling.
285    #[derive(Debug)]
286    pub(crate) struct TimerEntry {
287        // Arc reference to the runtime handle. We can only free the driver after
288        // deregistering everything from their respective timer wheels.
289        driver: scheduler::Handle,
290        // Shared inner structure; this is part of an intrusive linked list, and
291        // therefore other references can exist to it while mutable references to
292        // Entry exist.
293        //
294        // This is manipulated only under the inner mutex.
295        #[pin]
296        inner: TimerShared,
297    }
298
299    impl PinnedDrop for TimerEntry {
300        fn drop(this: Pin<&mut Self>) {
301            this.cancel();
302        }
303    }
304}
305
306unsafe impl Send for TimerEntry {}
307unsafe impl Sync for TimerEntry {}
308
309/// An `TimerHandle` is the (non-enforced) "unique" pointer from the driver to the
310/// timer entry. Generally, at most one `TimerHandle` exists for a timer at a time
311/// (enforced by the timer state machine).
312///
313/// SAFETY: An `TimerHandle` is essentially a raw pointer, and the usual caveats
314/// of pointer safety apply. In particular, `TimerHandle` does not itself enforce
315/// that the timer does still exist; however, normally an `TimerHandle` is created
316/// immediately before registering the timer, and is consumed when firing the
317/// timer, to help minimize mistakes. Still, because `TimerHandle` cannot enforce
318/// memory safety, all operations are unsafe.
319#[derive(Debug)]
320pub(crate) struct TimerHandle {
321    inner: NonNull<TimerShared>,
322}
323
324/// The shared state structure of a timer. This structure is shared between the
325/// frontend (`Entry`) and driver backend.
326///
327/// Note that this structure is located inside the `TimerEntry` structure.
328pub(crate) struct TimerShared {
329    /// A link within the doubly-linked list of timers on a particular level and
330    /// slot. Valid only if state is equal to Registered.
331    ///
332    /// Only accessed under the entry lock.
333    pointers: linked_list::Pointers<TimerShared>,
334
335    /// The time when the [`TimerEntry`] was registered into the Wheel,
336    /// [`STATE_DEREGISTERED`] means it is not registered.
337    ///
338    /// Generally owned by the driver, but is accessed by the entry when not
339    /// registered.
340    ///
341    /// We use relaxed ordering for both loading and storing since this value
342    /// is only accessed either when holding the driver lock or through mutable
343    /// references to [`TimerEntry`].
344    registered_when: AtomicU64,
345
346    /// Current state. This records whether the timer entry is currently under
347    /// the ownership of the driver, and if not, its current state (not
348    /// complete, fired, error, etc).
349    state: StateCell,
350
351    _p: PhantomPinned,
352}
353
354unsafe impl Send for TimerShared {}
355unsafe impl Sync for TimerShared {}
356
357impl std::fmt::Debug for TimerShared {
358    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
359        f.debug_struct("TimerShared")
360            .field(
361                "registered_when",
362                &self.registered_when.load(Ordering::Relaxed),
363            )
364            .field("state", &self.state)
365            .finish()
366    }
367}
368
369generate_addr_of_methods! {
370    impl<> TimerShared {
371        unsafe fn addr_of_pointers(self: NonNull<Self>) -> NonNull<linked_list::Pointers<TimerShared>> {
372            &self.pointers
373        }
374    }
375}
376
377impl TimerShared {
378    pub(super) fn new() -> Self {
379        Self {
380            registered_when: AtomicU64::new(0),
381            pointers: linked_list::Pointers::new(),
382            state: StateCell::default(),
383            _p: PhantomPinned,
384        }
385    }
386
387    /// Gets the cached time-of-expiration value.
388    pub(super) fn registered_when(&self) -> u64 {
389        // Cached-when is only accessed under the driver lock, so we can use relaxed
390        self.registered_when.load(Ordering::Relaxed)
391    }
392
393    /// Gets the true time-of-expiration value, and copies it into the cached
394    /// time-of-expiration value.
395    ///
396    /// SAFETY: Must be called with the driver lock held, and when this entry is
397    /// not in any timer wheel lists.
398    pub(super) unsafe fn sync_when(&self) -> u64 {
399        let true_when = self.true_when();
400
401        self.registered_when.store(true_when, Ordering::Relaxed);
402
403        true_when
404    }
405
406    /// Sets the cached time-of-expiration value.
407    ///
408    /// SAFETY: Must be called with the driver lock held, and when this entry is
409    /// not in any timer wheel lists.
410    unsafe fn set_registered_when(&self, when: u64) {
411        self.registered_when.store(when, Ordering::Relaxed);
412    }
413
414    /// Returns the true time-of-expiration value, with relaxed memory ordering.
415    pub(super) fn true_when(&self) -> u64 {
416        self.state.when().expect("Timer already fired")
417    }
418
419    /// Sets the true time-of-expiration value, even if it is less than the
420    /// current expiration or the timer is deregistered.
421    ///
422    /// SAFETY: Must only be called with the driver lock held and the entry not
423    /// in the timer wheel.
424    pub(super) unsafe fn set_expiration(&self, t: u64) {
425        self.state.set_expiration(t);
426        self.registered_when.store(t, Ordering::Relaxed);
427    }
428
429    /// Sets the true time-of-expiration only if it is after the current.
430    pub(super) fn extend_expiration(&self, t: u64) -> Result<(), ()> {
431        self.state.extend_expiration(t)
432    }
433
434    /// Returns a `TimerHandle` for this timer.
435    pub(super) fn handle(&self) -> TimerHandle {
436        TimerHandle {
437            inner: NonNull::from(self),
438        }
439    }
440
441    /// Returns true if the state of this timer indicates that the timer might
442    /// be registered with the driver. This check is performed with relaxed
443    /// ordering, but is conservative - if it returns false, the timer is
444    /// definitely _not_ registered.
445    pub(super) fn might_be_registered(&self) -> bool {
446        self.state.might_be_registered()
447    }
448}
449
450unsafe impl linked_list::Link for TimerShared {
451    type Handle = TimerHandle;
452
453    type Target = TimerShared;
454
455    fn as_raw(handle: &Self::Handle) -> NonNull<Self::Target> {
456        handle.inner
457    }
458
459    unsafe fn from_raw(ptr: NonNull<Self::Target>) -> Self::Handle {
460        TimerHandle { inner: ptr }
461    }
462
463    unsafe fn pointers(
464        target: NonNull<Self::Target>,
465    ) -> NonNull<linked_list::Pointers<Self::Target>> {
466        unsafe { TimerShared::addr_of_pointers(target) }
467    }
468}
469
470// ===== impl Entry =====
471
472impl TimerEntry {
473    pub(crate) fn new(handle: scheduler::Handle) -> Self {
474        Self {
475            driver: handle,
476            inner: TimerShared::new(),
477        }
478    }
479
480    pub(crate) fn init(self: Pin<&mut Self>, deadline: u64) {
481        unsafe {
482            self.driver()
483                .reregister(&self.driver.driver().io, deadline, (&self.inner).into());
484        }
485    }
486
487    pub(crate) fn is_elapsed(&self) -> bool {
488        // Is this timer still in the timer wheel?
489        !self.inner.might_be_registered()
490    }
491
492    /// Cancels and deregisters the timer. This operation is irreversible.
493    pub(crate) fn cancel(self: Pin<&mut Self>) {
494        // We need to perform an acq/rel fence with the driver thread, and the
495        // simplest way to do so is to grab the driver lock.
496        //
497        // Why is this necessary? We're about to release this timer's memory for
498        // some other non-timer use. However, we've been doing a bunch of
499        // relaxed (or even non-atomic) writes from the driver thread, and we'll
500        // be doing more from _this thread_ (as this memory is interpreted as
501        // something else).
502        //
503        // It is critical to ensure that, from the point of view of the driver,
504        // those future non-timer writes happen-after the timer is fully fired,
505        // and from the purpose of this thread, the driver's writes all
506        // happen-before we drop the timer. This in turn requires us to perform
507        // an acquire-release barrier in _both_ directions between the driver
508        // and dropping thread.
509        //
510        // The lock acquisition in clear_entry serves this purpose. All of the
511        // driver manipulations happen with the lock held, so we can just take
512        // the lock and be sure that this drop happens-after everything the
513        // driver did so far and happens-before everything the driver does in
514        // the future. While we have the lock held, we also go ahead and
515        // deregister the entry if necessary.
516        unsafe { self.driver().clear_entry(NonNull::from(&self.inner)) };
517    }
518
519    pub(crate) fn reset(self: Pin<&mut Self>, deadline: u64) {
520        if self.inner.extend_expiration(deadline).is_ok() {
521            return;
522        }
523
524        unsafe {
525            self.driver()
526                .reregister(&self.driver.driver().io, deadline, (&self.inner).into());
527        }
528    }
529
530    pub(crate) fn poll_elapsed(
531        self: Pin<&mut Self>,
532        cx: &mut Context<'_>,
533    ) -> Poll<Result<(), super::Error>> {
534        assert!(
535            !self.driver().is_shutdown(),
536            "{}",
537            crate::util::error::RUNTIME_SHUTTING_DOWN_ERROR
538        );
539
540        self.inner.state.poll(cx.waker())
541    }
542
543    fn driver(&self) -> &super::Handle {
544        self.driver.driver().time()
545    }
546}
547
548impl TimerHandle {
549    pub(super) unsafe fn registered_when(&self) -> u64 {
550        unsafe { self.inner.as_ref().registered_when() }
551    }
552
553    pub(super) unsafe fn sync_when(&self) -> u64 {
554        unsafe { self.inner.as_ref().sync_when() }
555    }
556
557    pub(super) unsafe fn is_pending(&self) -> bool {
558        unsafe { self.inner.as_ref().state.is_pending() }
559    }
560
561    /// Forcibly sets the true and cached expiration times to the given tick.
562    ///
563    /// SAFETY: The caller must ensure that the handle remains valid, the driver
564    /// lock is held, and that the timer is not in any wheel linked lists.
565    pub(super) unsafe fn set_expiration(&self, tick: u64) {
566        unsafe {
567            self.inner.as_ref().set_expiration(tick);
568        }
569    }
570
571    /// Attempts to mark this entry as pending. If the expiration time is after
572    /// `not_after`, however, returns an Err with the current expiration time.
573    ///
574    /// If an `Err` is returned, the `registered_when` value will be updated to this
575    /// new expiration time.
576    ///
577    /// SAFETY: The caller must ensure that the handle remains valid, the driver
578    /// lock is held, and that the timer is not in any wheel linked lists.
579    /// After returning Ok, the entry must be added to the pending list.
580    pub(super) unsafe fn mark_pending(&self, not_after: u64) -> Result<(), u64> {
581        match unsafe { self.inner.as_ref().state.mark_pending(not_after) } {
582            Ok(()) => {
583                // mark this as being on the pending queue in registered_when
584                unsafe {
585                    self.inner.as_ref().set_registered_when(STATE_DEREGISTERED);
586                }
587                Ok(())
588            }
589            Err(tick) => {
590                unsafe {
591                    self.inner.as_ref().set_registered_when(tick);
592                }
593                Err(tick)
594            }
595        }
596    }
597
598    /// Attempts to transition to a terminal state. If the state is already a
599    /// terminal state, does nothing.
600    ///
601    /// Because the entry might be dropped after the state is moved to a
602    /// terminal state, this function consumes the handle to ensure we don't
603    /// access the entry afterwards.
604    ///
605    /// Returns the last-registered waker, if any.
606    ///
607    /// SAFETY: The driver lock must be held while invoking this function, and
608    /// the entry must not be in any wheel linked lists.
609    pub(super) unsafe fn fire(self, completed_state: TimerResult) -> Option<Waker> {
610        unsafe { self.inner.as_ref().state.fire(completed_state) }
611    }
612}