Skip to main content

starnix_rcu/
rcu_atomic.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use starnix_sync::{LockDepGuard, LockDepMutex, LockLevel};
6use starnix_types::atomic::{AsAtomic, AtomicOperations};
7use std::ops::{Deref, DerefMut};
8use std::sync::atomic::Ordering;
9
10pub struct RcuAtomic<T: AsAtomic, L: LockLevel> {
11    mutex: LockDepMutex<T, L>,
12    atomic: T::Atomic,
13}
14
15impl<T: AsAtomic + std::fmt::Debug, L: LockLevel> std::fmt::Debug for RcuAtomic<T, L> {
16    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        f.debug_struct("RcuAtomic").field("value", &self.read()).finish()
18    }
19}
20
21impl<T: AsAtomic, L: LockLevel> RcuAtomic<T, L> {
22    pub fn new(value: T) -> Self {
23        Self { mutex: LockDepMutex::new(value), atomic: T::Atomic::new(value) }
24    }
25
26    /// Read the value from the atomic without taking the lock.
27    pub fn read(&self) -> T {
28        self.atomic.load(Ordering::Relaxed)
29    }
30
31    /// Basic write operation: takes the mutex and updates both the mutex value and the atomic.
32    pub fn write(&self, value: T) {
33        let mut guard = self.mutex.lock();
34        *guard = value;
35        self.atomic.store(value, Ordering::Relaxed);
36    }
37
38    /// Takes the mutex and returns a guard that can be used to read and modify the value.
39    /// Updates are only committed to the atomic when `update` is called on the guard.
40    pub fn copy(&self) -> RcuAtomicGuard<'_, T, L> {
41        let guard = self.mutex.lock();
42        RcuAtomicGuard { parent: self, guard }
43    }
44}
45
46pub struct RcuAtomicGuard<'a, T: AsAtomic, L: LockLevel> {
47    parent: &'a RcuAtomic<T, L>,
48    guard: LockDepGuard<'a, T>,
49}
50
51impl<'a, T: AsAtomic, L: LockLevel> Deref for RcuAtomicGuard<'a, T, L> {
52    type Target = T;
53    fn deref(&self) -> &Self::Target {
54        &*self.guard
55    }
56}
57
58impl<'a, T: AsAtomic, L: LockLevel> DerefMut for RcuAtomicGuard<'a, T, L> {
59    fn deref_mut(&mut self) -> &mut Self::Target {
60        &mut *self.guard
61    }
62}
63
64impl<'a, T: AsAtomic, L: LockLevel> RcuAtomicGuard<'a, T, L> {
65    /// Consumes the guard, updates the atomic in `RcuAtomic` with the current value,
66    /// and drops the mutex guard.
67    pub fn update(self) {
68        let value = *self.guard;
69        self.parent.atomic.store(value, Ordering::Relaxed);
70        // guard dropped here
71    }
72}