Skip to content

Commit eda1128

Browse files
committed
cpu: Replace use of OnceNonZeroUsize::get() with get_unchecked().
1 parent bcf68dd commit eda1128

File tree

3 files changed

+45
-15
lines changed

3 files changed

+45
-15
lines changed

src/cpu/arm.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,12 @@ pub(super) mod featureflags {
148148
// SAFETY: Since only `get_or_init()` could have created
149149
// `_cpu_features`, and it only does so after `FEATURES.get_or_init()`,
150150
// we know we are reading from `FEATURES` after initializing it.
151-
//
152-
// Also, 0 means "no features detected" to users, which is designed to
153-
// be a safe configuration.
154-
let features = FEATURES.get().map(NonZeroUsize::get).unwrap_or(0);
151+
// The `get_or_init()` also did the synchronization.
152+
let features = unsafe { FEATURES.get_unchecked() };
155153

156154
// The truncation is lossless, as we set the value with a u32.
157155
#[allow(clippy::cast_possible_truncation)]
158-
let features = features as u32;
156+
let features = features.get() as u32;
159157

160158
features
161159
}

src/cpu/intel.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,12 @@ pub(super) mod featureflags {
7272
// SAFETY: Since only `get_or_init()` could have created
7373
// `_cpu_features`, and it only does so after `FEATURES.get_or_init()`,
7474
// we know we are reading from `FEATURES` after initializing it.
75-
//
76-
// Also, 0 means "no features detected" to users, which is designed to
77-
// be a safe configuration.
78-
let features = FEATURES.get().map(NonZeroUsize::get).unwrap_or(0);
75+
// The `get_or_init()` also did the synchronization.
76+
let features = unsafe { FEATURES.get_unchecked() };
7977

8078
// The truncation is lossless, as we set the value with a u32.
8179
#[allow(clippy::cast_possible_truncation)]
82-
let features = features as u32;
80+
let features = features.get() as u32;
8381

8482
features
8583
}

src/polyfill/once_cell/race.rs

+39-5
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,45 @@ impl OnceNonZeroUsize {
3838
}
3939
}
4040

41-
/// Gets the underlying value.
42-
#[inline]
43-
pub fn get(&self) -> Option<NonZeroUsize> {
44-
let val = self.inner.load(Ordering::Acquire);
45-
NonZeroUsize::new(val)
41+
/// Get the reference to the underlying value, without checking if the cell
42+
/// is initialized.
43+
///
44+
/// # Safety
45+
///
46+
/// Caller must ensure that the cell is in initialized state, and that
47+
/// the contents are acquired by (synchronized to) this thread.
48+
pub unsafe fn get_unchecked(&self) -> NonZeroUsize {
49+
#[inline(always)]
50+
fn as_const_ptr(r: &AtomicUsize) -> *const usize {
51+
use core::mem::align_of;
52+
53+
let p: *const AtomicUsize = r;
54+
// SAFETY: "This type has the same size and bit validity as
55+
// the underlying integer type, usize. However, the alignment of
56+
// this type is always equal to its size, even on targets where
57+
// usize has a lesser alignment."
58+
const _ALIGNMENT_COMPATIBLE: () =
59+
assert!(align_of::<AtomicUsize>() % align_of::<usize>() == 0);
60+
p.cast::<usize>()
61+
}
62+
63+
// TODO(MSRV-1.70): Use `AtomicUsize::as_ptr().cast_const()`
64+
// See https://github.com/rust-lang/rust/issues/138246.
65+
let p = as_const_ptr(&self.inner);
66+
67+
// SAFETY: The caller is responsible for ensuring that the value
68+
// was initialized and that the contents have been acquired by
69+
// this thread. Assuming that, we can assume there will be no
70+
// conflicting writes to the value since the value will never
71+
// change once initialized. This relies on the statement in
72+
// https://doc.rust-lang.org/1.83.0/core/sync/atomic/ that "(A
73+
// `compare_exchange` or `compare_exchange_weak` that does not
74+
// succeed is not considered a write."
75+
let val = unsafe { p.read() };
76+
77+
// SAFETY: The caller is responsible for ensuring the value is
78+
// initialized and thus not zero.
79+
unsafe { NonZeroUsize::new_unchecked(val) }
4680
}
4781

4882
/// Gets the contents of the cell, initializing it with `f` if the cell was

0 commit comments

Comments
 (0)