Skip to content

Commit 8fab921

Browse files
Rollup merge of rust-lang#130543 - CAD97:generic-atomic, r=Noratrieb
Create `Atomic<T>` type alias and use it in core/alloc/std where possible, ignoring test files for now. This is step one, creating the alias from `Atomic<T>` to `AtomicT`. The next step of flipping this and aliasing `AtomicT` to `Atomic<T>` will have a bigger impact, since `AtomicT` imports can be dropped once `Atomic::new` is a usable name. First commit is the true change. Second commit is mostly mechanical replacement of `AtomicT` type names with `Atomic<T>`. See [how this was done for `NonZero`](rust-lang#120257) for the rough blueprint I'm following. - ACP: rust-lang/libs-team#443 (comment) - Tracking issue: rust-lang#130539
2 parents cfa2951 + fbf092e commit 8fab921

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+340
-240
lines changed

library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@
124124
#![feature(extend_one_unchecked)]
125125
#![feature(fmt_internals)]
126126
#![feature(fn_traits)]
127+
#![feature(generic_atomic)]
127128
#![feature(hasher_prefixfree_extras)]
128129
#![feature(inplace_iteration)]
129130
#![feature(iter_advance_by)]

library/alloc/src/sync.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ use core::pin::{Pin, PinCoerceUnsized};
2424
use core::ptr::{self, NonNull};
2525
#[cfg(not(no_global_oom_handling))]
2626
use core::slice::from_raw_parts_mut;
27-
use core::sync::atomic;
2827
use core::sync::atomic::Ordering::{Acquire, Relaxed, Release};
28+
use core::sync::atomic::{self, Atomic};
2929
use core::{borrow, fmt, hint};
3030

3131
#[cfg(not(no_global_oom_handling))]
@@ -346,12 +346,12 @@ impl<T: ?Sized, A: Allocator> fmt::Debug for Weak<T, A> {
346346
// inner types.
347347
#[repr(C)]
348348
struct ArcInner<T: ?Sized> {
349-
strong: atomic::AtomicUsize,
349+
strong: Atomic<usize>,
350350

351351
// the value usize::MAX acts as a sentinel for temporarily "locking" the
352352
// ability to upgrade weak pointers or downgrade strong ones; this is used
353353
// to avoid races in `make_mut` and `get_mut`.
354-
weak: atomic::AtomicUsize,
354+
weak: Atomic<usize>,
355355

356356
data: T,
357357
}
@@ -2706,8 +2706,8 @@ impl<T, A: Allocator> Weak<T, A> {
27062706
/// Helper type to allow accessing the reference counts without
27072707
/// making any assertions about the data field.
27082708
struct WeakInner<'a> {
2709-
weak: &'a atomic::AtomicUsize,
2710-
strong: &'a atomic::AtomicUsize,
2709+
weak: &'a Atomic<usize>,
2710+
strong: &'a Atomic<usize>,
27112711
}
27122712

27132713
impl<T: ?Sized> Weak<T> {

library/core/src/sync/atomic.rs

+97-3
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,100 @@ use crate::cell::UnsafeCell;
227227
use crate::hint::spin_loop;
228228
use crate::{fmt, intrinsics};
229229

230+
trait Sealed {}
231+
232+
/// A marker trait for primitive types which can be modified atomically.
233+
///
234+
/// This is an implementation detail for <code>[Atomic]\<T></code> which may disappear or be replaced at any time.
235+
///
236+
/// # Safety
237+
///
238+
/// Types implementing this trait must be primitives that can be modified atomically.
239+
///
240+
/// The associated `Self::AtomicInner` type must have the same size and bit validity as `Self`,
241+
/// but may have a higher alignment requirement, so the following `transmute`s are sound:
242+
///
243+
/// - `&mut Self::AtomicInner` as `&mut Self`
244+
/// - `Self` as `Self::AtomicInner` or the reverse
245+
#[unstable(
246+
feature = "atomic_internals",
247+
reason = "implementation detail which may disappear or be replaced at any time",
248+
issue = "none"
249+
)]
250+
#[allow(private_bounds)]
251+
pub unsafe trait AtomicPrimitive: Sized + Copy + Sealed {
252+
#[doc(hidden)]
253+
type AtomicInner: Sized;
254+
}
255+
256+
macro impl_atomic_primitive(
257+
$Atom:ident $(<$T:ident>)? ($Primitive:ty),
258+
size($size:literal),
259+
align($align:literal) $(,)?
260+
) {
261+
impl $(<$T>)? Sealed for $Primitive {}
262+
263+
#[unstable(
264+
feature = "atomic_internals",
265+
reason = "implementation detail which may disappear or be replaced at any time",
266+
issue = "none"
267+
)]
268+
#[cfg(target_has_atomic_load_store = $size)]
269+
unsafe impl $(<$T>)? AtomicPrimitive for $Primitive {
270+
type AtomicInner = $Atom $(<$T>)?;
271+
}
272+
}
273+
274+
impl_atomic_primitive!(AtomicBool(bool), size("8"), align(1));
275+
impl_atomic_primitive!(AtomicI8(i8), size("8"), align(1));
276+
impl_atomic_primitive!(AtomicU8(u8), size("8"), align(1));
277+
impl_atomic_primitive!(AtomicI16(i16), size("16"), align(2));
278+
impl_atomic_primitive!(AtomicU16(u16), size("16"), align(2));
279+
impl_atomic_primitive!(AtomicI32(i32), size("32"), align(4));
280+
impl_atomic_primitive!(AtomicU32(u32), size("32"), align(4));
281+
impl_atomic_primitive!(AtomicI64(i64), size("64"), align(8));
282+
impl_atomic_primitive!(AtomicU64(u64), size("64"), align(8));
283+
impl_atomic_primitive!(AtomicI128(i128), size("128"), align(16));
284+
impl_atomic_primitive!(AtomicU128(u128), size("128"), align(16));
285+
286+
#[cfg(target_pointer_width = "16")]
287+
impl_atomic_primitive!(AtomicIsize(isize), size("ptr"), align(2));
288+
#[cfg(target_pointer_width = "32")]
289+
impl_atomic_primitive!(AtomicIsize(isize), size("ptr"), align(4));
290+
#[cfg(target_pointer_width = "64")]
291+
impl_atomic_primitive!(AtomicIsize(isize), size("ptr"), align(8));
292+
293+
#[cfg(target_pointer_width = "16")]
294+
impl_atomic_primitive!(AtomicUsize(usize), size("ptr"), align(2));
295+
#[cfg(target_pointer_width = "32")]
296+
impl_atomic_primitive!(AtomicUsize(usize), size("ptr"), align(4));
297+
#[cfg(target_pointer_width = "64")]
298+
impl_atomic_primitive!(AtomicUsize(usize), size("ptr"), align(8));
299+
300+
#[cfg(target_pointer_width = "16")]
301+
impl_atomic_primitive!(AtomicPtr<T>(*mut T), size("ptr"), align(2));
302+
#[cfg(target_pointer_width = "32")]
303+
impl_atomic_primitive!(AtomicPtr<T>(*mut T), size("ptr"), align(4));
304+
#[cfg(target_pointer_width = "64")]
305+
impl_atomic_primitive!(AtomicPtr<T>(*mut T), size("ptr"), align(8));
306+
307+
/// A memory location which can be safely modified from multiple threads.
308+
///
309+
/// This has the same size and bit validity as the underlying type `T`. However,
310+
/// the alignment of this type is always equal to its size, even on targets where
311+
/// `T` has alignment less than its size.
312+
///
313+
/// For more about the differences between atomic types and non-atomic types as
314+
/// well as information about the portability of this type, please see the
315+
/// [module-level documentation].
316+
///
317+
/// **Note:** This type is only available on platforms that support atomic loads
318+
/// and stores of `T`.
319+
///
320+
/// [module-level documentation]: crate::sync::atomic
321+
#[unstable(feature = "generic_atomic", issue = "130539")]
322+
pub type Atomic<T> = <T as AtomicPrimitive>::AtomicInner;
323+
230324
// Some architectures don't have byte-sized atomics, which results in LLVM
231325
// emulating them using a LL/SC loop. However for AtomicBool we can take
232326
// advantage of the fact that it only ever contains 0 or 1 and use atomic OR/AND
@@ -388,7 +482,7 @@ pub enum Ordering {
388482
note = "the `new` function is now preferred",
389483
suggestion = "AtomicBool::new(false)"
390484
)]
391-
pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false);
485+
pub const ATOMIC_BOOL_INIT: Atomic<bool> = AtomicBool::new(false);
392486

393487
#[cfg(target_has_atomic_load_store = "8")]
394488
impl AtomicBool {
@@ -3253,7 +3347,7 @@ macro_rules! atomic_int_ptr_sized {
32533347
note = "the `new` function is now preferred",
32543348
suggestion = "AtomicIsize::new(0)",
32553349
)]
3256-
pub const ATOMIC_ISIZE_INIT: AtomicIsize = AtomicIsize::new(0);
3350+
pub const ATOMIC_ISIZE_INIT: Atomic<isize> = AtomicIsize::new(0);
32573351

32583352
/// An [`AtomicUsize`] initialized to `0`.
32593353
#[cfg(target_pointer_width = $target_pointer_width)]
@@ -3263,7 +3357,7 @@ macro_rules! atomic_int_ptr_sized {
32633357
note = "the `new` function is now preferred",
32643358
suggestion = "AtomicUsize::new(0)",
32653359
)]
3266-
pub const ATOMIC_USIZE_INIT: AtomicUsize = AtomicUsize::new(0);
3360+
pub const ATOMIC_USIZE_INIT: Atomic<usize> = AtomicUsize::new(0);
32673361
)* };
32683362
}
32693363

library/std/src/alloc.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
#![stable(feature = "alloc_module", since = "1.28.0")]
5858

5959
use core::ptr::NonNull;
60-
use core::sync::atomic::{AtomicPtr, Ordering};
60+
use core::sync::atomic::{Atomic, AtomicPtr, Ordering};
6161
use core::{hint, mem, ptr};
6262

6363
#[stable(feature = "alloc_module", since = "1.28.0")]
@@ -287,7 +287,7 @@ unsafe impl Allocator for System {
287287
}
288288
}
289289

290-
static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
290+
static HOOK: Atomic<*mut ()> = AtomicPtr::new(ptr::null_mut());
291291

292292
/// Registers a custom allocation error hook, replacing any that was previously registered.
293293
///

library/std/src/backtrace.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ mod tests;
9191
use crate::backtrace_rs::{self, BytesOrWideString};
9292
use crate::ffi::c_void;
9393
use crate::panic::UnwindSafe;
94-
use crate::sync::atomic::AtomicU8;
9594
use crate::sync::atomic::Ordering::Relaxed;
95+
use crate::sync::atomic::{Atomic, AtomicU8};
9696
use crate::sync::LazyLock;
9797
use crate::sys::backtrace::{lock, output_filename, set_image_base};
9898
use crate::{env, fmt};
@@ -254,7 +254,7 @@ impl Backtrace {
254254
// Cache the result of reading the environment variables to make
255255
// backtrace captures speedy, because otherwise reading environment
256256
// variables every time can be somewhat slow.
257-
static ENABLED: AtomicU8 = AtomicU8::new(0);
257+
static ENABLED: Atomic<u8> = AtomicU8::new(0);
258258
match ENABLED.load(Relaxed) {
259259
0 => {}
260260
1 => return false,

library/std/src/io/stdio.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::io::{
1111
self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines, SpecReadByte,
1212
};
1313
use crate::panic::{RefUnwindSafe, UnwindSafe};
14-
use crate::sync::atomic::{AtomicBool, Ordering};
14+
use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
1515
use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantLock, ReentrantLockGuard};
1616
use crate::sys::stdio;
1717
use crate::thread::AccessError;
@@ -37,7 +37,7 @@ thread_local! {
3737
/// have a consistent order between set_output_capture and print_to *within
3838
/// the same thread*. Within the same thread, things always have a perfectly
3939
/// consistent order. So Ordering::Relaxed is fine.
40-
static OUTPUT_CAPTURE_USED: AtomicBool = AtomicBool::new(false);
40+
static OUTPUT_CAPTURE_USED: Atomic<bool> = AtomicBool::new(false);
4141

4242
/// A handle to a raw instance of the standard input stream of this process.
4343
///

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@
334334
#![feature(float_minimum_maximum)]
335335
#![feature(float_next_up_down)]
336336
#![feature(fmt_internals)]
337+
#![feature(generic_atomic)]
337338
#![feature(hasher_prefixfree_extras)]
338339
#![feature(hashmap_internals)]
339340
#![feature(ip)]

library/std/src/os/uefi/env.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44

55
use crate::ffi::c_void;
66
use crate::ptr::NonNull;
7-
use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
7+
use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, Ordering};
88

9-
static SYSTEM_TABLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_mut());
10-
static IMAGE_HANDLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_mut());
9+
static SYSTEM_TABLE: Atomic<*mut c_void> = AtomicPtr::new(crate::ptr::null_mut());
10+
static IMAGE_HANDLE: Atomic<*mut c_void> = AtomicPtr::new(crate::ptr::null_mut());
1111
// Flag to check if BootServices are still valid.
1212
// Start with assuming that they are not available
13-
static BOOT_SERVICES_FLAG: AtomicBool = AtomicBool::new(false);
13+
static BOOT_SERVICES_FLAG: Atomic<bool> = AtomicBool::new(false);
1414

1515
/// Initializes the global System Table and Image Handle pointers.
1616
///

library/std/src/os/xous/services.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use core::sync::atomic::{AtomicU32, Ordering};
1+
use core::sync::atomic::{Atomic, AtomicU32, Ordering};
22

33
use crate::os::xous::ffi::Connection;
44

@@ -106,7 +106,7 @@ pub fn try_connect(name: &str) -> Option<Connection> {
106106
ns::try_connect_with_name(name)
107107
}
108108

109-
static NAME_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0);
109+
static NAME_SERVER_CONNECTION: Atomic<u32> = AtomicU32::new(0);
110110

111111
/// Returns a `Connection` to the name server. If the name server has not been started,
112112
/// then this call will block until the name server has been started. The `Connection`

library/std/src/os/xous/services/dns.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl Into<usize> for DnsLendMut {
1717
/// Returns a `Connection` to the DNS lookup server. This server is used for
1818
/// querying domain name values.
1919
pub(crate) fn dns_server() -> Connection {
20-
static DNS_CONNECTION: AtomicU32 = AtomicU32::new(0);
20+
static DNS_CONNECTION: Atomic<u32> = AtomicU32::new(0);
2121
let cid = DNS_CONNECTION.load(Ordering::Relaxed);
2222
if cid != 0 {
2323
return cid.into();

library/std/src/os/xous/services/log.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use core::sync::atomic::{AtomicU32, Ordering};
1+
use core::sync::atomic::{Atomic, AtomicU32, Ordering};
22

33
use crate::os::xous::ffi::Connection;
44

@@ -64,7 +64,7 @@ impl Into<usize> for LogLend {
6464
/// running. It is safe to call this multiple times, because the address is
6565
/// shared among all threads in a process.
6666
pub(crate) fn log_server() -> Connection {
67-
static LOG_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0);
67+
static LOG_SERVER_CONNECTION: Atomic<u32> = AtomicU32::new(0);
6868

6969
let cid = LOG_SERVER_CONNECTION.load(Ordering::Relaxed);
7070
if cid != 0 {

library/std/src/os/xous/services/net.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ impl<'a> Into<[usize; 5]> for NetBlockingScalar {
8484
/// Returns a `Connection` to the Network server. This server provides all
8585
/// OS-level networking functions.
8686
pub(crate) fn net_server() -> Connection {
87-
static NET_CONNECTION: AtomicU32 = AtomicU32::new(0);
87+
static NET_CONNECTION: Atomic<u32> = AtomicU32::new(0);
8888
let cid = NET_CONNECTION.load(Ordering::Relaxed);
8989
if cid != 0 {
9090
return cid.into();

library/std/src/os/xous/services/systime.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use core::sync::atomic::{AtomicU32, Ordering};
1+
use core::sync::atomic::{Atomic, AtomicU32, Ordering};
22

33
use crate::os::xous::ffi::{connect, Connection};
44

@@ -17,7 +17,7 @@ impl Into<[usize; 5]> for SystimeScalar {
1717
/// Returns a `Connection` to the systime server. This server is used for reporting the
1818
/// realtime clock.
1919
pub(crate) fn systime_server() -> Connection {
20-
static SYSTIME_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0);
20+
static SYSTIME_SERVER_CONNECTION: Atomic<u32> = AtomicU32::new(0);
2121
let cid = SYSTIME_SERVER_CONNECTION.load(Ordering::Relaxed);
2222
if cid != 0 {
2323
return cid.into();

library/std/src/os/xous/services/ticktimer.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use core::sync::atomic::{AtomicU32, Ordering};
1+
use core::sync::atomic::{Atomic, AtomicU32, Ordering};
22

33
use crate::os::xous::ffi::Connection;
44

@@ -31,7 +31,7 @@ impl Into<[usize; 5]> for TicktimerScalar {
3131
/// Returns a `Connection` to the ticktimer server. This server is used for synchronization
3232
/// primitives such as sleep, Mutex, and Condvar.
3333
pub(crate) fn ticktimer_server() -> Connection {
34-
static TICKTIMER_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0);
34+
static TICKTIMER_SERVER_CONNECTION: Atomic<u32> = AtomicU32::new(0);
3535
let cid = TICKTIMER_SERVER_CONNECTION.load(Ordering::Relaxed);
3636
if cid != 0 {
3737
return cid.into();

library/std/src/panic.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![stable(feature = "std_panic", since = "1.9.0")]
44

55
use crate::any::Any;
6-
use crate::sync::atomic::{AtomicU8, Ordering};
6+
use crate::sync::atomic::{Atomic, AtomicU8, Ordering};
77
use crate::sync::{Condvar, Mutex, RwLock};
88
use crate::thread::Result;
99
use crate::{collections, fmt, panicking};
@@ -456,7 +456,7 @@ impl BacktraceStyle {
456456
// that backtrace.
457457
//
458458
// Internally stores equivalent of an Option<BacktraceStyle>.
459-
static SHOULD_CAPTURE: AtomicU8 = AtomicU8::new(0);
459+
static SHOULD_CAPTURE: Atomic<u8> = AtomicU8::new(0);
460460

461461
/// Configures whether the default panic hook will capture and display a
462462
/// backtrace.

library/std/src/panicking.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::any::Any;
2121
use crate::io::try_set_output_capture;
2222
use crate::mem::{self, ManuallyDrop};
2323
use crate::panic::{BacktraceStyle, PanicHookInfo};
24-
use crate::sync::atomic::{AtomicBool, Ordering};
24+
use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
2525
use crate::sync::{PoisonError, RwLock};
2626
use crate::sys::stdio::panic_output;
2727
use crate::sys::{backtrace, dbg};
@@ -257,7 +257,7 @@ fn default_hook(info: &PanicHookInfo<'_>) {
257257
let mut lock = backtrace::lock();
258258
let _ = writeln!(err, "thread '{name}' panicked at {location}:\n{msg}");
259259

260-
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
260+
static FIRST_PANIC: Atomic<bool> = AtomicBool::new(true);
261261

262262
match backtrace {
263263
// SAFETY: we took out a lock just a second ago.
@@ -342,7 +342,7 @@ pub mod panic_count {
342342
#[unstable(feature = "update_panic_count", issue = "none")]
343343
pub mod panic_count {
344344
use crate::cell::Cell;
345-
use crate::sync::atomic::{AtomicUsize, Ordering};
345+
use crate::sync::atomic::{Atomic, AtomicUsize, Ordering};
346346

347347
const ALWAYS_ABORT_FLAG: usize = 1 << (usize::BITS - 1);
348348

@@ -384,7 +384,7 @@ pub mod panic_count {
384384
//
385385
// Stealing a bit is fine because it just amounts to assuming that each
386386
// panicking thread consumes at least 2 bytes of address space.
387-
static GLOBAL_PANIC_COUNT: AtomicUsize = AtomicUsize::new(0);
387+
static GLOBAL_PANIC_COUNT: Atomic<usize> = AtomicUsize::new(0);
388388

389389
// Increases the global and local panic count, and returns whether an
390390
// immediate abort is required.

0 commit comments

Comments
 (0)