mmtk/util/metadata/
metadata_val_traits.rs

1use crate::util::Address;
2use core::sync::atomic::*;
3use num_traits::{FromPrimitive, ToPrimitive};
4use num_traits::{Unsigned, WrappingAdd, WrappingSub, Zero};
5
6/// Describes bits and log2 bits for the numbers.
7/// If num_traits has this, we do not need our own implementation: <https://github.com/rust-num/num-traits/issues/247>
8pub trait Bits {
9    /// The size of this atomic type in bits.
10    const BITS: u32;
11    /// The size (in log2) of this atomic type in bits.
12    const LOG2: u32;
13}
14macro_rules! impl_bits_trait {
15    ($t: ty) => {
16        impl Bits for $t {
17            const BITS: u32 = <$t>::BITS;
18            const LOG2: u32 = Self::BITS.trailing_zeros();
19        }
20    };
21}
22impl_bits_trait!(u8);
23impl_bits_trait!(u16);
24impl_bits_trait!(u32);
25impl_bits_trait!(u64);
26impl_bits_trait!(usize);
27
28/// Describes bitwise operations.
29/// If num_traits has this, we do not need our own implementation: <https://github.com/rust-num/num-traits/issues/232>
30pub trait BitwiseOps {
31    /// Perform bitwise and for two values.
32    fn bitand(self, other: Self) -> Self;
33    /// Perform bitwise or for two values.
34    fn bitor(self, other: Self) -> Self;
35    /// Perform bitwise xor for two values.
36    fn bitxor(self, other: Self) -> Self;
37    /// Perform bitwise invert (not) for the value.
38    fn inv(self) -> Self;
39}
40macro_rules! impl_bitwise_ops_trait {
41    ($t: ty) => {
42        impl BitwiseOps for $t {
43            fn bitand(self, other: Self) -> Self {
44                self & other
45            }
46            fn bitor(self, other: Self) -> Self {
47                self | other
48            }
49            fn bitxor(self, other: Self) -> Self {
50                self ^ other
51            }
52            fn inv(self) -> Self {
53                !self
54            }
55        }
56    };
57}
58impl_bitwise_ops_trait!(u8);
59impl_bitwise_ops_trait!(u16);
60impl_bitwise_ops_trait!(u32);
61impl_bitwise_ops_trait!(u64);
62impl_bitwise_ops_trait!(usize);
63
64/// The number type for accessing metadata.
65/// It requires a few traits from num-traits and a few traits we defined above.
66/// The methods in this trait are mostly about atomically accessing such types.
67pub trait MetadataValue:
68    Unsigned
69    + Zero
70    + WrappingAdd
71    + WrappingSub
72    + Bits
73    + BitwiseOps
74    + ToPrimitive
75    + Copy
76    + FromPrimitive
77    + std::fmt::Display
78    + std::fmt::Debug
79{
80    /// Non atomic load
81    /// # Safety
82    /// The caller needs to guarantee that the address is valid, and can be used as a pointer to the type.
83    /// The caller also needs to be aware that the method is not thread safe, as it is a non-atomic operation.
84    unsafe fn load(addr: Address) -> Self;
85
86    /// Atomic load
87    /// # Safety
88    /// The caller needs to guarantee that the address is valid, and can be used as a pointer to the type.
89    unsafe fn load_atomic(addr: Address, order: Ordering) -> Self;
90
91    /// Non atomic store
92    /// # Safety
93    /// The caller needs to guarantee that the address is valid, and can be used as a pointer to the type.
94    /// The caller also needs to be aware that the method is not thread safe, as it is a non-atomic operation.
95    unsafe fn store(addr: Address, value: Self);
96
97    /// Atomic store
98    /// # Safety
99    /// The caller needs to guarantee that the address is valid, and can be used as a pointer to the type.
100    /// The caller also needs to be aware that the method is not thread safe, as it is a non-atomic operation.
101    unsafe fn store_atomic(addr: Address, value: Self, order: Ordering);
102
103    /// # Safety
104    /// The caller needs to guarantee that the address is valid, and can be used as a pointer to the type.
105    unsafe fn compare_exchange(
106        addr: Address,
107        current: Self,
108        new: Self,
109        success: Ordering,
110        failure: Ordering,
111    ) -> Result<Self, Self>;
112
113    /// # Safety
114    /// The caller needs to guarantee that the address is valid, and can be used as a pointer to the type.
115    unsafe fn fetch_add(addr: Address, value: Self, order: Ordering) -> Self;
116
117    /// # Safety
118    /// The caller needs to guarantee that the address is valid, and can be used as a pointer to the type.
119    unsafe fn fetch_sub(addr: Address, value: Self, order: Ordering) -> Self;
120
121    /// # Safety
122    /// The caller needs to guarantee that the address is valid, and can be used as a pointer to the type.
123    unsafe fn fetch_and(addr: Address, value: Self, order: Ordering) -> Self;
124
125    /// # Safety
126    /// The caller needs to guarantee that the address is valid, and can be used as a pointer to the type.
127    unsafe fn fetch_or(addr: Address, value: Self, order: Ordering) -> Self;
128
129    /// # Safety
130    /// The caller needs to guarantee that the address is valid, and can be used as a pointer to the type.
131    unsafe fn fetch_update<F>(
132        addr: Address,
133        set_order: Ordering,
134        fetch_order: Ordering,
135        f: F,
136    ) -> Result<Self, Self>
137    where
138        F: FnMut(Self) -> Option<Self>;
139}
140macro_rules! impl_metadata_value_trait {
141    ($non_atomic: ty, $atomic: ty) => {
142        impl MetadataValue for $non_atomic {
143            unsafe fn load(addr: Address) -> Self {
144                addr.load::<$non_atomic>()
145            }
146
147            unsafe fn load_atomic(addr: Address, order: Ordering) -> Self {
148                addr.as_ref::<$atomic>().load(order)
149            }
150
151            unsafe fn store(addr: Address, value: Self) {
152                addr.store::<$non_atomic>(value)
153            }
154
155            unsafe fn store_atomic(addr: Address, value: Self, order: Ordering) {
156                addr.as_ref::<$atomic>().store(value, order)
157            }
158
159            unsafe fn compare_exchange(
160                addr: Address,
161                current: Self,
162                new: Self,
163                success: Ordering,
164                failure: Ordering,
165            ) -> Result<Self, Self> {
166                addr.as_ref::<$atomic>()
167                    .compare_exchange(current, new, success, failure)
168            }
169
170            unsafe fn fetch_add(addr: Address, value: Self, order: Ordering) -> Self {
171                addr.as_ref::<$atomic>().fetch_add(value, order)
172            }
173
174            unsafe fn fetch_sub(addr: Address, value: Self, order: Ordering) -> Self {
175                addr.as_ref::<$atomic>().fetch_sub(value, order)
176            }
177
178            unsafe fn fetch_and(addr: Address, value: Self, order: Ordering) -> Self {
179                addr.as_ref::<$atomic>().fetch_and(value, order)
180            }
181
182            unsafe fn fetch_or(addr: Address, value: Self, order: Ordering) -> Self {
183                addr.as_ref::<$atomic>().fetch_or(value, order)
184            }
185
186            unsafe fn fetch_update<F>(
187                addr: Address,
188                set_order: Ordering,
189                fetch_order: Ordering,
190                f: F,
191            ) -> Result<Self, Self>
192            where
193                F: FnMut(Self) -> Option<Self>,
194            {
195                addr.as_ref::<$atomic>()
196                    .fetch_update(set_order, fetch_order, f)
197            }
198        }
199    };
200}
201impl_metadata_value_trait!(u8, AtomicU8);
202impl_metadata_value_trait!(u16, AtomicU16);
203impl_metadata_value_trait!(u32, AtomicU32);
204impl_metadata_value_trait!(u64, AtomicU64);
205impl_metadata_value_trait!(usize, AtomicUsize);