diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 0bb7c432cc35f..1d60578507593 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -120,6 +120,7 @@
 #![feature(fmt_internals)]
 #![feature(fn_traits)]
 #![feature(formatting_options)]
+#![feature(generic_atomic)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(inplace_iteration)]
 #![feature(iter_advance_by)]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 431e19e6ef1d7..7f4a7a3857434 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -25,8 +25,8 @@ use core::pin::{Pin, PinCoerceUnsized};
 use core::ptr::{self, NonNull};
 #[cfg(not(no_global_oom_handling))]
 use core::slice::from_raw_parts_mut;
-use core::sync::atomic;
 use core::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use core::sync::atomic::{self, Atomic};
 use core::{borrow, fmt, hint};
 
 #[cfg(not(no_global_oom_handling))]
@@ -348,12 +348,12 @@ impl<T: ?Sized, A: Allocator> fmt::Debug for Weak<T, A> {
 // inner types.
 #[repr(C)]
 struct ArcInner<T: ?Sized> {
-    strong: atomic::AtomicUsize,
+    strong: Atomic<usize>,
 
     // the value usize::MAX acts as a sentinel for temporarily "locking" the
     // ability to upgrade weak pointers or downgrade strong ones; this is used
     // to avoid races in `make_mut` and `get_mut`.
-    weak: atomic::AtomicUsize,
+    weak: Atomic<usize>,
 
     data: T,
 }
@@ -2724,8 +2724,8 @@ impl<T, A: Allocator> Weak<T, A> {
 /// Helper type to allow accessing the reference counts without
 /// making any assertions about the data field.
 struct WeakInner<'a> {
-    weak: &'a atomic::AtomicUsize,
-    strong: &'a atomic::AtomicUsize,
+    weak: &'a Atomic<usize>,
+    strong: &'a Atomic<usize>,
 }
 
 impl<T: ?Sized> Weak<T> {
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 73180bde54aa9..f4d88d6b625e0 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -246,6 +246,100 @@ use crate::cell::UnsafeCell;
 use crate::hint::spin_loop;
 use crate::{fmt, intrinsics};
 
+trait Sealed {}
+
+/// A marker trait for primitive types which can be modified atomically.
+///
+/// This is an implementation detail for <code>[Atomic]\<T></code> which may disappear or be replaced at any time.
+///
+/// # Safety
+///
+/// Types implementing this trait must be primitives that can be modified atomically.
+///
+/// The associated `Self::AtomicInner` type must have the same size and bit validity as `Self`,
+/// but may have a higher alignment requirement, so the following `transmute`s are sound:
+///
+/// - `&mut Self::AtomicInner` as `&mut Self`
+/// - `Self` as `Self::AtomicInner` or the reverse
+#[unstable(
+    feature = "atomic_internals",
+    reason = "implementation detail which may disappear or be replaced at any time",
+    issue = "none"
+)]
+#[expect(private_bounds)]
+pub unsafe trait AtomicPrimitive: Sized + Copy + Sealed {
+    /// Temporary implementation detail.
+    type AtomicInner: Sized;
+}
+
+macro impl_atomic_primitive(
+    $Atom:ident $(<$T:ident>)? ($Primitive:ty),
+    size($size:literal),
+    align($align:literal) $(,)?
+) {
+    impl $(<$T>)? Sealed for $Primitive {}
+
+    #[unstable(
+        feature = "atomic_internals",
+        reason = "implementation detail which may disappear or be replaced at any time",
+        issue = "none"
+    )]
+    #[cfg(target_has_atomic_load_store = $size)]
+    unsafe impl $(<$T>)? AtomicPrimitive for $Primitive {
+        type AtomicInner = $Atom $(<$T>)?;
+    }
+}
+
+impl_atomic_primitive!(AtomicBool(bool), size("8"), align(1));
+impl_atomic_primitive!(AtomicI8(i8), size("8"), align(1));
+impl_atomic_primitive!(AtomicU8(u8), size("8"), align(1));
+impl_atomic_primitive!(AtomicI16(i16), size("16"), align(2));
+impl_atomic_primitive!(AtomicU16(u16), size("16"), align(2));
+impl_atomic_primitive!(AtomicI32(i32), size("32"), align(4));
+impl_atomic_primitive!(AtomicU32(u32), size("32"), align(4));
+impl_atomic_primitive!(AtomicI64(i64), size("64"), align(8));
+impl_atomic_primitive!(AtomicU64(u64), size("64"), align(8));
+impl_atomic_primitive!(AtomicI128(i128), size("128"), align(16));
+impl_atomic_primitive!(AtomicU128(u128), size("128"), align(16));
+
+#[cfg(target_pointer_width = "16")]
+impl_atomic_primitive!(AtomicIsize(isize), size("ptr"), align(2));
+#[cfg(target_pointer_width = "32")]
+impl_atomic_primitive!(AtomicIsize(isize), size("ptr"), align(4));
+#[cfg(target_pointer_width = "64")]
+impl_atomic_primitive!(AtomicIsize(isize), size("ptr"), align(8));
+
+#[cfg(target_pointer_width = "16")]
+impl_atomic_primitive!(AtomicUsize(usize), size("ptr"), align(2));
+#[cfg(target_pointer_width = "32")]
+impl_atomic_primitive!(AtomicUsize(usize), size("ptr"), align(4));
+#[cfg(target_pointer_width = "64")]
+impl_atomic_primitive!(AtomicUsize(usize), size("ptr"), align(8));
+
+#[cfg(target_pointer_width = "16")]
+impl_atomic_primitive!(AtomicPtr<T>(*mut T), size("ptr"), align(2));
+#[cfg(target_pointer_width = "32")]
+impl_atomic_primitive!(AtomicPtr<T>(*mut T), size("ptr"), align(4));
+#[cfg(target_pointer_width = "64")]
+impl_atomic_primitive!(AtomicPtr<T>(*mut T), size("ptr"), align(8));
+
+/// A memory location which can be safely modified from multiple threads.
+///
+/// This has the same size and bit validity as the underlying type `T`. However,
+/// the alignment of this type is always equal to its size, even on targets where
+/// `T` has alignment less than its size.
+///
+/// For more about the differences between atomic types and non-atomic types as
+/// well as information about the portability of this type, please see the
+/// [module-level documentation].
+///
+/// **Note:** This type is only available on platforms that support atomic loads
+/// and stores of `T`.
+///
+/// [module-level documentation]: crate::sync::atomic
+#[unstable(feature = "generic_atomic", issue = "130539")]
+pub type Atomic<T> = <T as AtomicPrimitive>::AtomicInner;
+
 // Some architectures don't have byte-sized atomics, which results in LLVM
 // emulating them using a LL/SC loop. However for AtomicBool we can take
 // advantage of the fact that it only ever contains 0 or 1 and use atomic OR/AND
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index 5d51d6a0c78a8..d60624b652a69 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -57,7 +57,7 @@
 #![stable(feature = "alloc_module", since = "1.28.0")]
 
 use core::ptr::NonNull;
-use core::sync::atomic::{AtomicPtr, Ordering};
+use core::sync::atomic::{Atomic, AtomicPtr, Ordering};
 use core::{hint, mem, ptr};
 
 #[stable(feature = "alloc_module", since = "1.28.0")]
@@ -287,7 +287,7 @@ unsafe impl Allocator for System {
     }
 }
 
-static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
+static HOOK: Atomic<*mut ()> = AtomicPtr::new(ptr::null_mut());
 
 /// Registers a custom allocation error hook, replacing any that was previously registered.
 ///
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index fc333d7ff3f95..b893b88f6fcd5 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -92,8 +92,8 @@ use crate::backtrace_rs::{self, BytesOrWideString};
 use crate::ffi::c_void;
 use crate::panic::UnwindSafe;
 use crate::sync::LazyLock;
-use crate::sync::atomic::AtomicU8;
 use crate::sync::atomic::Ordering::Relaxed;
+use crate::sync::atomic::{Atomic, AtomicU8};
 use crate::sys::backtrace::{lock, output_filename, set_image_base};
 use crate::{env, fmt};
 
@@ -254,7 +254,7 @@ impl Backtrace {
         // Cache the result of reading the environment variables to make
         // backtrace captures speedy, because otherwise reading environment
         // variables every time can be somewhat slow.
-        static ENABLED: AtomicU8 = AtomicU8::new(0);
+        static ENABLED: Atomic<u8> = AtomicU8::new(0);
         match ENABLED.load(Relaxed) {
             0 => {}
             1 => return false,
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 318c350822168..0cf1140a4aa08 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -11,7 +11,7 @@ use crate::io::{
     self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines, SpecReadByte,
 };
 use crate::panic::{RefUnwindSafe, UnwindSafe};
-use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
 use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantLock, ReentrantLockGuard};
 use crate::sys::stdio;
 use crate::thread::AccessError;
@@ -37,7 +37,7 @@ thread_local! {
 /// have a consistent order between set_output_capture and print_to *within
 /// the same thread*. Within the same thread, things always have a perfectly
 /// consistent order. So Ordering::Relaxed is fine.
-static OUTPUT_CAPTURE_USED: AtomicBool = AtomicBool::new(false);
+static OUTPUT_CAPTURE_USED: Atomic<bool> = AtomicBool::new(false);
 
 /// A handle to a raw instance of the standard input stream of this process.
 ///
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index acb3a0578e505..ba4a8f57983a0 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -336,6 +336,7 @@
 #![feature(float_gamma)]
 #![feature(float_minimum_maximum)]
 #![feature(fmt_internals)]
+#![feature(generic_atomic)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
 #![feature(hint_must_use)]
diff --git a/library/std/src/os/uefi/env.rs b/library/std/src/os/uefi/env.rs
index cf8ae697e389d..ab5406e605c6b 100644
--- a/library/std/src/os/uefi/env.rs
+++ b/library/std/src/os/uefi/env.rs
@@ -4,13 +4,13 @@
 
 use crate::ffi::c_void;
 use crate::ptr::NonNull;
-use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
+use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, Ordering};
 
-static SYSTEM_TABLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_mut());
-static IMAGE_HANDLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_mut());
+static SYSTEM_TABLE: Atomic<*mut c_void> = AtomicPtr::new(crate::ptr::null_mut());
+static IMAGE_HANDLE: Atomic<*mut c_void> = AtomicPtr::new(crate::ptr::null_mut());
 // Flag to check if BootServices are still valid.
 // Start with assuming that they are not available
-static BOOT_SERVICES_FLAG: AtomicBool = AtomicBool::new(false);
+static BOOT_SERVICES_FLAG: Atomic<bool> = AtomicBool::new(false);
 
 /// Initializes the global System Table and Image Handle pointers.
 ///
diff --git a/library/std/src/os/xous/services.rs b/library/std/src/os/xous/services.rs
index 93916750c0547..0681485ea0610 100644
--- a/library/std/src/os/xous/services.rs
+++ b/library/std/src/os/xous/services.rs
@@ -1,4 +1,4 @@
-use core::sync::atomic::{AtomicU32, Ordering};
+use core::sync::atomic::{Atomic, AtomicU32, Ordering};
 
 use crate::os::xous::ffi::Connection;
 
@@ -106,7 +106,7 @@ pub fn try_connect(name: &str) -> Option<Connection> {
     ns::try_connect_with_name(name)
 }
 
-static NAME_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0);
+static NAME_SERVER_CONNECTION: Atomic<u32> = AtomicU32::new(0);
 
 /// Returns a `Connection` to the name server. If the name server has not been started,
 /// then this call will block until the name server has been started. The `Connection`
diff --git a/library/std/src/os/xous/services/dns.rs b/library/std/src/os/xous/services/dns.rs
index 0288164839360..7641d1f15e444 100644
--- a/library/std/src/os/xous/services/dns.rs
+++ b/library/std/src/os/xous/services/dns.rs
@@ -1,4 +1,4 @@
-use core::sync::atomic::{AtomicU32, Ordering};
+use core::sync::atomic::{Atomic, AtomicU32, Ordering};
 
 use crate::os::xous::ffi::Connection;
 use crate::os::xous::services::connect;
@@ -17,7 +17,7 @@ impl Into<usize> for DnsLendMut {
 /// Returns a `Connection` to the DNS lookup server. This server is used for
 /// querying domain name values.
 pub(crate) fn dns_server() -> Connection {
-    static DNS_CONNECTION: AtomicU32 = AtomicU32::new(0);
+    static DNS_CONNECTION: Atomic<u32> = AtomicU32::new(0);
     let cid = DNS_CONNECTION.load(Ordering::Relaxed);
     if cid != 0 {
         return cid.into();
diff --git a/library/std/src/os/xous/services/log.rs b/library/std/src/os/xous/services/log.rs
index 1661011ca64b1..0b5b103211aa1 100644
--- a/library/std/src/os/xous/services/log.rs
+++ b/library/std/src/os/xous/services/log.rs
@@ -1,4 +1,4 @@
-use core::sync::atomic::{AtomicU32, Ordering};
+use core::sync::atomic::{Atomic, AtomicU32, Ordering};
 
 use crate::os::xous::ffi::Connection;
 
@@ -64,7 +64,7 @@ impl Into<usize> for LogLend {
 /// running. It is safe to call this multiple times, because the address is
 /// shared among all threads in a process.
 pub(crate) fn log_server() -> Connection {
-    static LOG_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0);
+    static LOG_SERVER_CONNECTION: Atomic<u32> = AtomicU32::new(0);
 
     let cid = LOG_SERVER_CONNECTION.load(Ordering::Relaxed);
     if cid != 0 {
diff --git a/library/std/src/os/xous/services/net.rs b/library/std/src/os/xous/services/net.rs
index 83acc7961b377..c20bf1a7ad596 100644
--- a/library/std/src/os/xous/services/net.rs
+++ b/library/std/src/os/xous/services/net.rs
@@ -1,4 +1,4 @@
-use core::sync::atomic::{AtomicU32, Ordering};
+use core::sync::atomic::{Atomic, AtomicU32, Ordering};
 
 use crate::os::xous::ffi::Connection;
 use crate::os::xous::services::connect;
@@ -84,7 +84,7 @@ impl<'a> Into<[usize; 5]> for NetBlockingScalar {
 /// Returns a `Connection` to the Network server. This server provides all
 /// OS-level networking functions.
 pub(crate) fn net_server() -> Connection {
-    static NET_CONNECTION: AtomicU32 = AtomicU32::new(0);
+    static NET_CONNECTION: Atomic<u32> = AtomicU32::new(0);
     let cid = NET_CONNECTION.load(Ordering::Relaxed);
     if cid != 0 {
         return cid.into();
diff --git a/library/std/src/os/xous/services/systime.rs b/library/std/src/os/xous/services/systime.rs
index de87694b4cdca..e54cffdc4c018 100644
--- a/library/std/src/os/xous/services/systime.rs
+++ b/library/std/src/os/xous/services/systime.rs
@@ -1,4 +1,4 @@
-use core::sync::atomic::{AtomicU32, Ordering};
+use core::sync::atomic::{Atomic, AtomicU32, Ordering};
 
 use crate::os::xous::ffi::{Connection, connect};
 
@@ -17,7 +17,7 @@ impl Into<[usize; 5]> for SystimeScalar {
 /// Returns a `Connection` to the systime server. This server is used for reporting the
 /// realtime clock.
 pub(crate) fn systime_server() -> Connection {
-    static SYSTIME_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0);
+    static SYSTIME_SERVER_CONNECTION: Atomic<u32> = AtomicU32::new(0);
     let cid = SYSTIME_SERVER_CONNECTION.load(Ordering::Relaxed);
     if cid != 0 {
         return cid.into();
diff --git a/library/std/src/os/xous/services/ticktimer.rs b/library/std/src/os/xous/services/ticktimer.rs
index 66ade6da65cd3..bf51ecde8e5bc 100644
--- a/library/std/src/os/xous/services/ticktimer.rs
+++ b/library/std/src/os/xous/services/ticktimer.rs
@@ -1,4 +1,4 @@
-use core::sync::atomic::{AtomicU32, Ordering};
+use core::sync::atomic::{Atomic, AtomicU32, Ordering};
 
 use crate::os::xous::ffi::Connection;
 
@@ -31,7 +31,7 @@ impl Into<[usize; 5]> for TicktimerScalar {
 /// Returns a `Connection` to the ticktimer server. This server is used for synchronization
 /// primitives such as sleep, Mutex, and Condvar.
 pub(crate) fn ticktimer_server() -> Connection {
-    static TICKTIMER_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0);
+    static TICKTIMER_SERVER_CONNECTION: Atomic<u32> = AtomicU32::new(0);
     let cid = TICKTIMER_SERVER_CONNECTION.load(Ordering::Relaxed);
     if cid != 0 {
         return cid.into();
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index d649357a56d71..3208e732b4e11 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -3,7 +3,7 @@
 #![stable(feature = "std_panic", since = "1.9.0")]
 
 use crate::any::Any;
-use crate::sync::atomic::{AtomicU8, Ordering};
+use crate::sync::atomic::{Atomic, AtomicU8, Ordering};
 use crate::sync::{Condvar, Mutex, RwLock};
 use crate::thread::Result;
 use crate::{collections, fmt, panicking};
@@ -466,7 +466,7 @@ impl BacktraceStyle {
 // that backtrace.
 //
 // Internally stores equivalent of an Option<BacktraceStyle>.
-static SHOULD_CAPTURE: AtomicU8 = AtomicU8::new(0);
+static SHOULD_CAPTURE: Atomic<u8> = AtomicU8::new(0);
 
 /// Configures whether the default panic hook will capture and display a
 /// backtrace.
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 8e50bf11dd082..6a6aacac6c86c 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -21,7 +21,7 @@ use crate::any::Any;
 use crate::io::try_set_output_capture;
 use crate::mem::{self, ManuallyDrop};
 use crate::panic::{BacktraceStyle, PanicHookInfo};
-use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
 use crate::sync::{PoisonError, RwLock};
 use crate::sys::backtrace;
 use crate::sys::stdio::panic_output;
@@ -287,7 +287,7 @@ fn default_hook(info: &PanicHookInfo<'_>) {
             };
         });
 
-        static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
+        static FIRST_PANIC: Atomic<bool> = AtomicBool::new(true);
 
         match backtrace {
             // SAFETY: we took out a lock just a second ago.
@@ -372,7 +372,7 @@ pub mod panic_count {
 #[unstable(feature = "update_panic_count", issue = "none")]
 pub mod panic_count {
     use crate::cell::Cell;
-    use crate::sync::atomic::{AtomicUsize, Ordering};
+    use crate::sync::atomic::{Atomic, AtomicUsize, Ordering};
 
     const ALWAYS_ABORT_FLAG: usize = 1 << (usize::BITS - 1);
 
@@ -414,7 +414,7 @@ pub mod panic_count {
     //
     // Stealing a bit is fine because it just amounts to assuming that each
     // panicking thread consumes at least 2 bytes of address space.
-    static GLOBAL_PANIC_COUNT: AtomicUsize = AtomicUsize::new(0);
+    static GLOBAL_PANIC_COUNT: Atomic<usize> = AtomicUsize::new(0);
 
     // Increases the global and local panic count, and returns whether an
     // immediate abort is required.
diff --git a/library/std/src/sync/mpmc/array.rs b/library/std/src/sync/mpmc/array.rs
index a467237fef152..880d8b5f57cf4 100644
--- a/library/std/src/sync/mpmc/array.rs
+++ b/library/std/src/sync/mpmc/array.rs
@@ -16,13 +16,13 @@ use super::waker::SyncWaker;
 use crate::cell::UnsafeCell;
 use crate::mem::MaybeUninit;
 use crate::ptr;
-use crate::sync::atomic::{self, AtomicUsize, Ordering};
+use crate::sync::atomic::{self, Atomic, AtomicUsize, Ordering};
 use crate::time::Instant;
 
 /// A slot in a channel.
 struct Slot<T> {
     /// The current stamp.
-    stamp: AtomicUsize,
+    stamp: Atomic<usize>,
 
     /// The message in this slot. Either read out in `read` or dropped through
     /// `discard_all_messages`.
@@ -55,7 +55,7 @@ pub(crate) struct Channel<T> {
     /// represent the lap. The mark bit in the head is always zero.
     ///
     /// Messages are popped from the head of the channel.
-    head: CachePadded<AtomicUsize>,
+    head: CachePadded<Atomic<usize>>,
 
     /// The tail of the channel.
     ///
@@ -64,7 +64,7 @@ pub(crate) struct Channel<T> {
     /// represent the lap. The mark bit indicates that the channel is disconnected.
     ///
     /// Messages are pushed into the tail of the channel.
-    tail: CachePadded<AtomicUsize>,
+    tail: CachePadded<Atomic<usize>>,
 
     /// The buffer holding slots.
     buffer: Box<[Slot<T>]>,
diff --git a/library/std/src/sync/mpmc/context.rs b/library/std/src/sync/mpmc/context.rs
index 51aa7e82e7890..6b2f4cb6ffd29 100644
--- a/library/std/src/sync/mpmc/context.rs
+++ b/library/std/src/sync/mpmc/context.rs
@@ -5,7 +5,7 @@ use super::waker::current_thread_id;
 use crate::cell::Cell;
 use crate::ptr;
 use crate::sync::Arc;
-use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
+use crate::sync::atomic::{Atomic, AtomicPtr, AtomicUsize, Ordering};
 use crate::thread::{self, Thread};
 use crate::time::Instant;
 
@@ -19,10 +19,10 @@ pub struct Context {
 #[derive(Debug)]
 struct Inner {
     /// Selected operation.
-    select: AtomicUsize,
+    select: Atomic<usize>,
 
     /// A slot into which another thread may store a pointer to its `Packet`.
-    packet: AtomicPtr<()>,
+    packet: Atomic<*mut ()>,
 
     /// Thread handle.
     thread: Thread,
diff --git a/library/std/src/sync/mpmc/counter.rs b/library/std/src/sync/mpmc/counter.rs
index d1bfe612f536f..efa6af1148334 100644
--- a/library/std/src/sync/mpmc/counter.rs
+++ b/library/std/src/sync/mpmc/counter.rs
@@ -1,16 +1,16 @@
-use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
+use crate::sync::atomic::{Atomic, AtomicBool, AtomicUsize, Ordering};
 use crate::{ops, process};
 
 /// Reference counter internals.
 struct Counter<C> {
     /// The number of senders associated with the channel.
-    senders: AtomicUsize,
+    senders: Atomic<usize>,
 
     /// The number of receivers associated with the channel.
-    receivers: AtomicUsize,
+    receivers: Atomic<usize>,
 
     /// Set to `true` if the last sender or the last receiver reference deallocates the channel.
-    destroy: AtomicBool,
+    destroy: Atomic<bool>,
 
     /// The internal channel.
     chan: C,
diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs
index d88914f529142..661d9ea1ff514 100644
--- a/library/std/src/sync/mpmc/list.rs
+++ b/library/std/src/sync/mpmc/list.rs
@@ -9,7 +9,7 @@ use crate::cell::UnsafeCell;
 use crate::marker::PhantomData;
 use crate::mem::MaybeUninit;
 use crate::ptr;
-use crate::sync::atomic::{self, AtomicPtr, AtomicUsize, Ordering};
+use crate::sync::atomic::{self, Atomic, AtomicPtr, AtomicUsize, Ordering};
 use crate::time::Instant;
 
 // Bits indicating the state of a slot:
@@ -37,7 +37,7 @@ struct Slot<T> {
     msg: UnsafeCell<MaybeUninit<T>>,
 
     /// The state of the slot.
-    state: AtomicUsize,
+    state: Atomic<usize>,
 }
 
 impl<T> Slot<T> {
@@ -55,7 +55,7 @@ impl<T> Slot<T> {
 /// Each block in the list can hold up to `BLOCK_CAP` messages.
 struct Block<T> {
     /// The next block in the linked list.
-    next: AtomicPtr<Block<T>>,
+    next: Atomic<*mut Block<T>>,
 
     /// Slots for messages.
     slots: [Slot<T>; BLOCK_CAP],
@@ -65,11 +65,11 @@ impl<T> Block<T> {
     /// Creates an empty block.
     fn new() -> Box<Block<T>> {
         // SAFETY: This is safe because:
-        //  [1] `Block::next` (AtomicPtr) may be safely zero initialized.
+        //  [1] `Block::next` (Atomic<*mut _>) may be safely zero initialized.
         //  [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4].
         //  [3] `Slot::msg` (UnsafeCell) may be safely zero initialized because it
         //       holds a MaybeUninit.
-        //  [4] `Slot::state` (AtomicUsize) may be safely zero initialized.
+        //  [4] `Slot::state` (Atomic<usize>) may be safely zero initialized.
         unsafe { Box::new_zeroed().assume_init() }
     }
 
@@ -110,10 +110,10 @@ impl<T> Block<T> {
 #[derive(Debug)]
 struct Position<T> {
     /// The index in the channel.
-    index: AtomicUsize,
+    index: Atomic<usize>,
 
     /// The block in the linked list.
-    block: AtomicPtr<Block<T>>,
+    block: Atomic<*mut Block<T>>,
 }
 
 /// The token type for the list flavor.
diff --git a/library/std/src/sync/mpmc/waker.rs b/library/std/src/sync/mpmc/waker.rs
index 1895466f95d45..3531cad0478a6 100644
--- a/library/std/src/sync/mpmc/waker.rs
+++ b/library/std/src/sync/mpmc/waker.rs
@@ -4,7 +4,7 @@ use super::context::Context;
 use super::select::{Operation, Selected};
 use crate::ptr;
 use crate::sync::Mutex;
-use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
 
 /// Represents a thread blocked on a specific channel operation.
 pub(crate) struct Entry {
@@ -137,7 +137,7 @@ pub(crate) struct SyncWaker {
     inner: Mutex<Waker>,
 
     /// `true` if the waker is empty.
-    is_empty: AtomicBool,
+    is_empty: Atomic<bool>,
 }
 
 impl SyncWaker {
diff --git a/library/std/src/sync/mpmc/zero.rs b/library/std/src/sync/mpmc/zero.rs
index 577997c07a636..f1ecf80fcb9f6 100644
--- a/library/std/src/sync/mpmc/zero.rs
+++ b/library/std/src/sync/mpmc/zero.rs
@@ -10,7 +10,7 @@ use super::waker::Waker;
 use crate::cell::UnsafeCell;
 use crate::marker::PhantomData;
 use crate::sync::Mutex;
-use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
 use crate::time::Instant;
 use crate::{fmt, ptr};
 
@@ -35,7 +35,7 @@ struct Packet<T> {
     on_stack: bool,
 
     /// Equals `true` once the packet is ready for reading or writing.
-    ready: AtomicBool,
+    ready: Atomic<bool>,
 
     /// The message.
     msg: UnsafeCell<Option<T>>,
diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs
index 1b8809734b8a8..cc1d0b30152a1 100644
--- a/library/std/src/sync/poison.rs
+++ b/library/std/src/sync/poison.rs
@@ -76,7 +76,7 @@ pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
 use crate::error::Error;
 use crate::fmt;
 #[cfg(panic = "unwind")]
-use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
 #[cfg(panic = "unwind")]
 use crate::thread;
 
@@ -88,7 +88,7 @@ mod rwlock;
 
 pub(crate) struct Flag {
     #[cfg(panic = "unwind")]
-    failed: AtomicBool,
+    failed: Atomic<bool>,
 }
 
 // Note that the Ordering uses to access the `failed` field of `Flag` below is
diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs
index 0140e0d21299f..077f428ce35f6 100644
--- a/library/std/src/sync/reentrant_lock.rs
+++ b/library/std/src/sync/reentrant_lock.rs
@@ -92,9 +92,9 @@ pub struct ReentrantLock<T: ?Sized> {
 
 cfg_if!(
     if #[cfg(target_has_atomic = "64")] {
-        use crate::sync::atomic::{AtomicU64, Ordering::Relaxed};
+        use crate::sync::atomic::{Atomic, AtomicU64, Ordering::Relaxed};
 
-        struct Tid(AtomicU64);
+        struct Tid(Atomic<u64>);
 
         impl Tid {
             const fn new() -> Self {
@@ -123,6 +123,7 @@ cfg_if!(
         }
 
         use crate::sync::atomic::{
+            Atomic,
             AtomicUsize,
             Ordering,
         };
@@ -140,7 +141,7 @@ cfg_if!(
             // the current thread, or by a thread that has terminated before
             // the current thread was created. In either case, no further
             // synchronization is needed (as per <https://github.com/rust-lang/miri/issues/3450>)
-            tls_addr: AtomicUsize,
+            tls_addr: Atomic<usize>,
             tid: UnsafeCell<u64>,
         }
 
diff --git a/library/std/src/sys/alloc/sgx.rs b/library/std/src/sys/alloc/sgx.rs
index fca9d087e5bfc..c8d4ed2638958 100644
--- a/library/std/src/sys/alloc/sgx.rs
+++ b/library/std/src/sys/alloc/sgx.rs
@@ -1,6 +1,6 @@
 use crate::alloc::{GlobalAlloc, Layout, System};
 use crate::ptr;
-use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
 use crate::sys::pal::abi::mem as sgx_mem;
 use crate::sys::pal::waitqueue::SpinMutex;
 
@@ -20,7 +20,7 @@ struct Sgx;
 unsafe impl dlmalloc::Allocator for Sgx {
     /// Allocs system resources
     fn alloc(&self, _size: usize) -> (*mut u8, usize, u32) {
-        static INIT: AtomicBool = AtomicBool::new(false);
+        static INIT: Atomic<bool> = AtomicBool::new(false);
 
         // No ordering requirement since this function is protected by the global lock.
         if !INIT.swap(true, Ordering::Relaxed) {
diff --git a/library/std/src/sys/alloc/wasm.rs b/library/std/src/sys/alloc/wasm.rs
index 53fbc9529e590..c8fab992a88a7 100644
--- a/library/std/src/sys/alloc/wasm.rs
+++ b/library/std/src/sys/alloc/wasm.rs
@@ -60,10 +60,10 @@ unsafe impl GlobalAlloc for System {
 
 #[cfg(target_feature = "atomics")]
 mod lock {
-    use crate::sync::atomic::AtomicI32;
     use crate::sync::atomic::Ordering::{Acquire, Release};
+    use crate::sync::atomic::{Atomic, AtomicI32};
 
-    static LOCKED: AtomicI32 = AtomicI32::new(0);
+    static LOCKED: Atomic<i32> = AtomicI32::new(0);
 
     pub struct DropLock;
 
diff --git a/library/std/src/sys/alloc/xous.rs b/library/std/src/sys/alloc/xous.rs
index 321d30e0b11b2..3a288e5def2c9 100644
--- a/library/std/src/sys/alloc/xous.rs
+++ b/library/std/src/sys/alloc/xous.rs
@@ -49,10 +49,10 @@ unsafe impl GlobalAlloc for System {
 }
 
 mod lock {
-    use crate::sync::atomic::AtomicI32;
     use crate::sync::atomic::Ordering::{Acquire, Release};
+    use crate::sync::atomic::{Atomic, AtomicI32};
 
-    static LOCKED: AtomicI32 = AtomicI32::new(0);
+    static LOCKED: Atomic<i32> = AtomicI32::new(0);
 
     pub struct DropLock;
 
diff --git a/library/std/src/sys/pal/hermit/args.rs b/library/std/src/sys/pal/hermit/args.rs
index 4402426027730..ae155c987914a 100644
--- a/library/std/src/sys/pal/hermit/args.rs
+++ b/library/std/src/sys/pal/hermit/args.rs
@@ -1,11 +1,11 @@
 use crate::ffi::{CStr, OsString, c_char};
 use crate::os::hermit::ffi::OsStringExt;
 use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
-use crate::sync::atomic::{AtomicIsize, AtomicPtr};
+use crate::sync::atomic::{Atomic, AtomicIsize, AtomicPtr};
 use crate::{fmt, ptr, vec};
 
-static ARGC: AtomicIsize = AtomicIsize::new(0);
-static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
+static ARGC: Atomic<isize> = AtomicIsize::new(0);
+static ARGV: Atomic<*mut *const u8> = AtomicPtr::new(ptr::null_mut());
 
 /// One-time global initialization.
 pub unsafe fn init(argc: isize, argv: *const *const u8) {
diff --git a/library/std/src/sys/pal/hermit/futex.rs b/library/std/src/sys/pal/hermit/futex.rs
index 670383b45aca9..2a322fb04e3e1 100644
--- a/library/std/src/sys/pal/hermit/futex.rs
+++ b/library/std/src/sys/pal/hermit/futex.rs
@@ -1,6 +1,6 @@
 use super::hermit_abi;
 use crate::ptr::null;
-use crate::sync::atomic::AtomicU32;
+use crate::sync::atomic::Atomic;
 use crate::time::Duration;
 
 /// An atomic for use as a futex that is at least 32-bits but may be larger
@@ -13,7 +13,7 @@ pub type SmallFutex = AtomicU32;
 /// Must be the underlying type of SmallFutex
 pub type SmallPrimitive = u32;
 
-pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
+pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool {
     // Calculate the timeout as a relative timespec.
     //
     // Overflows are rounded up to an infinite timeout (None).
@@ -37,12 +37,12 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
 }
 
 #[inline]
-pub fn futex_wake(futex: &AtomicU32) -> bool {
+pub fn futex_wake(futex: &Atomic<u32>) -> bool {
     unsafe { hermit_abi::futex_wake(futex.as_ptr(), 1) > 0 }
 }
 
 #[inline]
-pub fn futex_wake_all(futex: &AtomicU32) {
+pub fn futex_wake_all(futex: &Atomic<u32>) {
     unsafe {
         hermit_abi::futex_wake(futex.as_ptr(), i32::MAX);
     }
diff --git a/library/std/src/sys/pal/itron/spin.rs b/library/std/src/sys/pal/itron/spin.rs
index 6a9a7c72deb7d..bc4f83260bbd0 100644
--- a/library/std/src/sys/pal/itron/spin.rs
+++ b/library/std/src/sys/pal/itron/spin.rs
@@ -1,12 +1,12 @@
 use super::abi;
 use crate::cell::UnsafeCell;
 use crate::mem::MaybeUninit;
-use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
+use crate::sync::atomic::{Atomic, AtomicBool, AtomicUsize, Ordering};
 
 /// A mutex implemented by `dis_dsp` (for intra-core synchronization) and a
 /// spinlock (for inter-core synchronization).
 pub struct SpinMutex<T = ()> {
-    locked: AtomicBool,
+    locked: Atomic<bool>,
     data: UnsafeCell<T>,
 }
 
@@ -19,7 +19,7 @@ impl<T> SpinMutex<T> {
     /// Acquire a lock.
     #[inline]
     pub fn with_locked<R>(&self, f: impl FnOnce(&mut T) -> R) -> R {
-        struct SpinMutexGuard<'a>(&'a AtomicBool);
+        struct SpinMutexGuard<'a>(&'a Atomic<bool>);
 
         impl Drop for SpinMutexGuard<'_> {
             #[inline]
@@ -50,7 +50,7 @@ impl<T> SpinMutex<T> {
 /// It's assumed that `0` is not a valid ID, and all kernel
 /// object IDs fall into range `1..=usize::MAX`.
 pub struct SpinIdOnceCell<T = ()> {
-    id: AtomicUsize,
+    id: Atomic<usize>,
     spin: SpinMutex<()>,
     extra: UnsafeCell<MaybeUninit<T>>,
 }
diff --git a/library/std/src/sys/pal/itron/thread.rs b/library/std/src/sys/pal/itron/thread.rs
index 04095e1a7cf99..7f24398e2df1f 100644
--- a/library/std/src/sys/pal/itron/thread.rs
+++ b/library/std/src/sys/pal/itron/thread.rs
@@ -9,7 +9,7 @@ use crate::ffi::CStr;
 use crate::mem::ManuallyDrop;
 use crate::num::NonZero;
 use crate::ptr::NonNull;
-use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sync::atomic::{Atomic, AtomicUsize, Ordering};
 use crate::time::Duration;
 use crate::{hint, io};
 
@@ -64,7 +64,7 @@ struct ThreadInner {
     ///                 '--> JOIN_FINALIZE ---'
     ///                          (-1)
     ///
-    lifecycle: AtomicUsize,
+    lifecycle: Atomic<usize>,
 }
 
 // Safety: The only `!Sync` field, `ThreadInner::start`, is only touched by
diff --git a/library/std/src/sys/pal/sgx/abi/mod.rs b/library/std/src/sys/pal/sgx/abi/mod.rs
index d8836452e7555..9bec03752c487 100644
--- a/library/std/src/sys/pal/sgx/abi/mod.rs
+++ b/library/std/src/sys/pal/sgx/abi/mod.rs
@@ -1,7 +1,7 @@
 #![cfg_attr(test, allow(unused))] // RT initialization logic is not compiled for test
 
 use core::arch::global_asm;
-use core::sync::atomic::{AtomicUsize, Ordering};
+use core::sync::atomic::{Atomic, AtomicUsize, Ordering};
 
 use crate::io::Write;
 
@@ -31,7 +31,7 @@ unsafe extern "C" fn tcs_init(secondary: bool) {
     const BUSY: usize = 1;
     const DONE: usize = 2;
     // Three-state spin-lock
-    static RELOC_STATE: AtomicUsize = AtomicUsize::new(UNINIT);
+    static RELOC_STATE: Atomic<usize> = AtomicUsize::new(UNINIT);
 
     if secondary && RELOC_STATE.load(Ordering::Relaxed) != DONE {
         rtabort!("Entered secondary TCS before main TCS!")
diff --git a/library/std/src/sys/pal/sgx/abi/tls/mod.rs b/library/std/src/sys/pal/sgx/abi/tls/mod.rs
index 34fc2f20d2214..2885a4bc141dc 100644
--- a/library/std/src/sys/pal/sgx/abi/tls/mod.rs
+++ b/library/std/src/sys/pal/sgx/abi/tls/mod.rs
@@ -3,7 +3,7 @@ mod sync_bitset;
 use self::sync_bitset::*;
 use crate::cell::Cell;
 use crate::num::NonZero;
-use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sync::atomic::{Atomic, AtomicUsize, Ordering};
 use crate::{mem, ptr};
 
 #[cfg(target_pointer_width = "64")]
@@ -14,13 +14,9 @@ const TLS_KEYS_BITSET_SIZE: usize = (TLS_KEYS + (USIZE_BITS - 1)) / USIZE_BITS;
 #[cfg_attr(test, linkage = "available_externally")]
 #[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_KEY_IN_USEE"]
 static TLS_KEY_IN_USE: SyncBitset = SYNC_BITSET_INIT;
-macro_rules! dup {
-    ((* $($exp:tt)*) $($val:tt)*) => (dup!( ($($exp)*) $($val)* $($val)* ));
-    (() $($val:tt)*) => ([$($val),*])
-}
 #[cfg_attr(test, linkage = "available_externally")]
 #[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_DESTRUCTORE"]
-static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = dup!((* * * * * * *) (AtomicUsize::new(0)));
+static TLS_DESTRUCTOR: [Atomic<usize>; TLS_KEYS] = [const { AtomicUsize::new(0) }; TLS_KEYS];
 
 extern "C" {
     fn get_tls_ptr() -> *const u8;
@@ -82,7 +78,7 @@ impl<'a> Drop for ActiveTls<'a> {
 
 impl Tls {
     pub fn new() -> Tls {
-        Tls { data: dup!((* * * * * * *) (Cell::new(ptr::null_mut()))) }
+        Tls { data: [const { Cell::new(ptr::null_mut()) }; TLS_KEYS] }
     }
 
     pub unsafe fn activate(&self) -> ActiveTls<'_> {
diff --git a/library/std/src/sys/pal/sgx/abi/tls/sync_bitset.rs b/library/std/src/sys/pal/sgx/abi/tls/sync_bitset.rs
index 4eeff8f6ef773..9087168589aa5 100644
--- a/library/std/src/sys/pal/sgx/abi/tls/sync_bitset.rs
+++ b/library/std/src/sys/pal/sgx/abi/tls/sync_bitset.rs
@@ -4,10 +4,10 @@ mod tests;
 use super::{TLS_KEYS_BITSET_SIZE, USIZE_BITS};
 use crate::iter::{Enumerate, Peekable};
 use crate::slice::Iter;
-use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sync::atomic::{Atomic, AtomicUsize, Ordering};
 
 /// A bitset that can be used synchronously.
-pub(super) struct SyncBitset([AtomicUsize; TLS_KEYS_BITSET_SIZE]);
+pub(super) struct SyncBitset([Atomic<usize>; TLS_KEYS_BITSET_SIZE]);
 
 pub(super) const SYNC_BITSET_INIT: SyncBitset =
     SyncBitset([AtomicUsize::new(0), AtomicUsize::new(0)]);
@@ -58,7 +58,7 @@ impl SyncBitset {
 }
 
 pub(super) struct SyncBitsetIter<'a> {
-    iter: Peekable<Enumerate<Iter<'a, AtomicUsize>>>,
+    iter: Peekable<Enumerate<Iter<'a, Atomic<usize>>>>,
     elem_idx: usize,
 }
 
diff --git a/library/std/src/sys/pal/sgx/args.rs b/library/std/src/sys/pal/sgx/args.rs
index a72a041da6cc9..9890a7c8ed62b 100644
--- a/library/std/src/sys/pal/sgx/args.rs
+++ b/library/std/src/sys/pal/sgx/args.rs
@@ -1,14 +1,14 @@
 use super::abi::usercalls::alloc;
 use super::abi::usercalls::raw::ByteBuffer;
 use crate::ffi::OsString;
-use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sync::atomic::{Atomic, AtomicUsize, Ordering};
 use crate::sys::os_str::Buf;
 use crate::sys_common::FromInner;
 use crate::{fmt, slice};
 
 #[cfg_attr(test, linkage = "available_externally")]
 #[export_name = "_ZN16__rust_internals3std3sys3sgx4args4ARGSE"]
-static ARGS: AtomicUsize = AtomicUsize::new(0);
+static ARGS: Atomic<usize> = AtomicUsize::new(0);
 type ArgsStore = Vec<OsString>;
 
 #[cfg_attr(test, allow(dead_code))]
diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs
index ce8a2fed4bc6b..faab8b98aec22 100644
--- a/library/std/src/sys/pal/sgx/mod.rs
+++ b/library/std/src/sys/pal/sgx/mod.rs
@@ -6,7 +6,7 @@
 #![allow(fuzzy_provenance_casts)] // FIXME: this entire module systematically confuses pointers and integers
 
 use crate::io::ErrorKind;
-use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
 
 pub mod abi;
 pub mod args;
@@ -57,7 +57,7 @@ pub fn unsupported_err() -> crate::io::Error {
 /// what happens when `SGX_INEFFECTIVE_ERROR` is set to `true`. If it is
 /// `false`, the behavior is the same as `unsupported`.
 pub fn sgx_ineffective<T>(v: T) -> crate::io::Result<T> {
-    static SGX_INEFFECTIVE_ERROR: AtomicBool = AtomicBool::new(false);
+    static SGX_INEFFECTIVE_ERROR: Atomic<bool> = AtomicBool::new(false);
     if SGX_INEFFECTIVE_ERROR.load(Ordering::Relaxed) {
         Err(crate::io::const_error!(
             ErrorKind::Uncategorized,
diff --git a/library/std/src/sys/pal/sgx/os.rs b/library/std/src/sys/pal/sgx/os.rs
index 46af710aa396c..53ed8593f23f1 100644
--- a/library/std/src/sys/pal/sgx/os.rs
+++ b/library/std/src/sys/pal/sgx/os.rs
@@ -5,7 +5,7 @@ use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::marker::PhantomData;
 use crate::path::{self, PathBuf};
-use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sync::atomic::{Atomic, AtomicUsize, Ordering};
 use crate::sync::{Mutex, Once};
 use crate::sys::{decode_error_kind, sgx_ineffective, unsupported};
 use crate::{fmt, io, str, vec};
@@ -75,7 +75,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 #[cfg_attr(test, linkage = "available_externally")]
 #[export_name = "_ZN16__rust_internals3std3sys3sgx2os3ENVE"]
-static ENV: AtomicUsize = AtomicUsize::new(0);
+static ENV: Atomic<usize> = AtomicUsize::new(0);
 #[cfg_attr(test, linkage = "available_externally")]
 #[export_name = "_ZN16__rust_internals3std3sys3sgx2os8ENV_INITE"]
 static ENV_INIT: Once = Once::new();
diff --git a/library/std/src/sys/pal/sgx/waitqueue/spin_mutex.rs b/library/std/src/sys/pal/sgx/waitqueue/spin_mutex.rs
index f6e851ccaddfa..73c7a101d601d 100644
--- a/library/std/src/sys/pal/sgx/waitqueue/spin_mutex.rs
+++ b/library/std/src/sys/pal/sgx/waitqueue/spin_mutex.rs
@@ -7,12 +7,12 @@ mod tests;
 use crate::cell::UnsafeCell;
 use crate::hint;
 use crate::ops::{Deref, DerefMut};
-use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
 
 #[derive(Default)]
 pub struct SpinMutex<T> {
     value: UnsafeCell<T>,
-    lock: AtomicBool,
+    lock: Atomic<bool>,
 }
 
 unsafe impl<T: Send> Send for SpinMutex<T> {}
diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs
index dccc137d6f561..95847aa8fe84e 100644
--- a/library/std/src/sys/pal/uefi/helpers.rs
+++ b/library/std/src/sys/pal/uefi/helpers.rs
@@ -22,7 +22,7 @@ use crate::os::uefi::{self};
 use crate::path::Path;
 use crate::ptr::NonNull;
 use crate::slice;
-use crate::sync::atomic::{AtomicPtr, Ordering};
+use crate::sync::atomic::{Atomic, AtomicPtr, Ordering};
 use crate::sys_common::wstr::WStrUnits;
 
 type BootInstallMultipleProtocolInterfaces =
@@ -190,7 +190,7 @@ pub(crate) fn device_path_to_text(path: NonNull<device_path::Protocol>) -> io::R
         Ok(path)
     }
 
-    static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
+    static LAST_VALID_HANDLE: Atomic<*mut crate::ffi::c_void> =
         AtomicPtr::new(crate::ptr::null_mut());
 
     if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
@@ -248,7 +248,7 @@ impl OwnedDevicePath {
                 .ok_or_else(|| const_error!(io::ErrorKind::InvalidFilename, "Invalid Device Path"))
         }
 
-        static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
+        static LAST_VALID_HANDLE: Atomic<*mut crate::ffi::c_void> =
             AtomicPtr::new(crate::ptr::null_mut());
 
         if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
@@ -463,7 +463,7 @@ pub(crate) fn os_string_to_raw(s: &OsStr) -> Option<Box<[r_efi::efi::Char16]>> {
 }
 
 pub(crate) fn open_shell() -> Option<NonNull<shell::Protocol>> {
-    static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
+    static LAST_VALID_HANDLE: Atomic<*mut crate::ffi::c_void> =
         AtomicPtr::new(crate::ptr::null_mut());
 
     if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs
index 111bed7a7eb64..b349a3d709bb1 100644
--- a/library/std/src/sys/pal/uefi/mod.rs
+++ b/library/std/src/sys/pal/uefi/mod.rs
@@ -37,9 +37,9 @@ pub type RawOsError = usize;
 use crate::io as std_io;
 use crate::os::uefi;
 use crate::ptr::NonNull;
-use crate::sync::atomic::{AtomicPtr, Ordering};
+use crate::sync::atomic::{Atomic, AtomicPtr, Ordering};
 
-static EXIT_BOOT_SERVICE_EVENT: AtomicPtr<crate::ffi::c_void> =
+static EXIT_BOOT_SERVICE_EVENT: Atomic<*mut crate::ffi::c_void> =
     AtomicPtr::new(crate::ptr::null_mut());
 
 /// # SAFETY
diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs
index 495ff2dc930ed..48e771d1b05d5 100644
--- a/library/std/src/sys/pal/uefi/time.rs
+++ b/library/std/src/sys/pal/uefi/time.rs
@@ -121,7 +121,7 @@ pub(crate) mod instant_internal {
     use super::*;
     use crate::mem::MaybeUninit;
     use crate::ptr::NonNull;
-    use crate::sync::atomic::{AtomicPtr, Ordering};
+    use crate::sync::atomic::{Atomic, AtomicPtr, Ordering};
     use crate::sys_common::mul_div_u64;
 
     const NS_PER_SEC: u64 = 1_000_000_000;
@@ -142,7 +142,7 @@ pub(crate) mod instant_internal {
             Some(mul_div_u64(ts, NS_PER_SEC, freq))
         }
 
-        static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
+        static LAST_VALID_HANDLE: Atomic<*mut crate::ffi::c_void> =
             AtomicPtr::new(crate::ptr::null_mut());
 
         if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
diff --git a/library/std/src/sys/pal/unix/args.rs b/library/std/src/sys/pal/unix/args.rs
index 8438a61e90feb..1b264deac363b 100644
--- a/library/std/src/sys/pal/unix/args.rs
+++ b/library/std/src/sys/pal/unix/args.rs
@@ -118,7 +118,7 @@ impl DoubleEndedIterator for Args {
 mod imp {
     use crate::ffi::c_char;
     use crate::ptr;
-    use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering};
+    use crate::sync::atomic::{Atomic, AtomicIsize, AtomicPtr, Ordering};
 
     // The system-provided argc and argv, which we store in static memory
     // here so that we can defer the work of parsing them until its actually
@@ -126,8 +126,8 @@ mod imp {
     //
     // Note that we never mutate argv/argc, the argv array, or the argv
     // strings, which allows the code in this file to be very simple.
-    static ARGC: AtomicIsize = AtomicIsize::new(0);
-    static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
+    static ARGC: Atomic<isize> = AtomicIsize::new(0);
+    static ARGV: Atomic<*mut *const u8> = AtomicPtr::new(ptr::null_mut());
 
     unsafe fn really_init(argc: isize, argv: *const *const u8) {
         // These don't need to be ordered with each other or other stores,
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs
index fdf011c19482a..35a488f786b6a 100644
--- a/library/std/src/sys/pal/unix/fs.rs
+++ b/library/std/src/sys/pal/unix/fs.rs
@@ -141,14 +141,14 @@ cfg_has_statx! {{
         flags: i32,
         mask: u32,
     ) -> Option<io::Result<FileAttr>> {
-        use crate::sync::atomic::{AtomicU8, Ordering};
+        use crate::sync::atomic::{Atomic, AtomicU8, Ordering};
 
         // Linux kernel prior to 4.11 or glibc prior to glibc 2.28 don't support `statx`.
         // We check for it on first failure and remember availability to avoid having to
         // do it again.
         #[repr(u8)]
         enum STATX_STATE{ Unknown = 0, Present, Unavailable }
-        static STATX_SAVED_STATE: AtomicU8 = AtomicU8::new(STATX_STATE::Unknown as u8);
+        static STATX_SAVED_STATE: Atomic<u8> = AtomicU8::new(STATX_STATE::Unknown as u8);
 
         syscall! {
             fn statx(
diff --git a/library/std/src/sys/pal/unix/futex.rs b/library/std/src/sys/pal/unix/futex.rs
index 0fc765dc87a5d..e640cdf16b69b 100644
--- a/library/std/src/sys/pal/unix/futex.rs
+++ b/library/std/src/sys/pal/unix/futex.rs
@@ -8,7 +8,7 @@
     target_os = "fuchsia",
 ))]
 
-use crate::sync::atomic::AtomicU32;
+use crate::sync::atomic::{Atomic, AtomicU32};
 use crate::time::Duration;
 
 /// An atomic for use as a futex that is at least 32-bits but may be larger
@@ -27,7 +27,7 @@ pub type SmallPrimitive = u32;
 ///
 /// Returns false on timeout, and true in all other cases.
 #[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))]
-pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
+pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool {
     use super::time::Timespec;
     use crate::ptr::null;
     use crate::sync::atomic::Ordering::Relaxed;
@@ -60,7 +60,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
                     let umtx_timeout_ptr = umtx_timeout.as_ref().map_or(null(), |t| t as *const _);
                     let umtx_timeout_size = umtx_timeout.as_ref().map_or(0, |t| crate::mem::size_of_val(t));
                     libc::_umtx_op(
-                        futex as *const AtomicU32 as *mut _,
+                        futex as *const Atomic<u32> as *mut _,
                         libc::UMTX_OP_WAIT_UINT_PRIVATE,
                         expected as libc::c_ulong,
                         crate::ptr::without_provenance_mut(umtx_timeout_size),
@@ -71,7 +71,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
                     // absolute time rather than a relative time.
                     libc::syscall(
                         libc::SYS_futex,
-                        futex as *const AtomicU32,
+                        futex as *const Atomic<u32>,
                         libc::FUTEX_WAIT_BITSET | libc::FUTEX_PRIVATE_FLAG,
                         expected,
                         timespec.as_ref().map_or(null(), |t| t as *const libc::timespec),
@@ -99,16 +99,16 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
 ///
 /// On some platforms, this always returns false.
 #[cfg(any(target_os = "linux", target_os = "android"))]
-pub fn futex_wake(futex: &AtomicU32) -> bool {
-    let ptr = futex as *const AtomicU32;
+pub fn futex_wake(futex: &Atomic<u32>) -> bool {
+    let ptr = futex as *const Atomic<u32>;
     let op = libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG;
     unsafe { libc::syscall(libc::SYS_futex, ptr, op, 1) > 0 }
 }
 
 /// Wakes up all threads that are waiting on `futex_wait` on this futex.
 #[cfg(any(target_os = "linux", target_os = "android"))]
-pub fn futex_wake_all(futex: &AtomicU32) {
-    let ptr = futex as *const AtomicU32;
+pub fn futex_wake_all(futex: &Atomic<u32>) {
+    let ptr = futex as *const Atomic<u32>;
     let op = libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG;
     unsafe {
         libc::syscall(libc::SYS_futex, ptr, op, i32::MAX);
@@ -117,11 +117,11 @@ pub fn futex_wake_all(futex: &AtomicU32) {
 
 // FreeBSD doesn't tell us how many threads are woken up, so this always returns false.
 #[cfg(target_os = "freebsd")]
-pub fn futex_wake(futex: &AtomicU32) -> bool {
+pub fn futex_wake(futex: &Atomic<u32>) -> bool {
     use crate::ptr::null_mut;
     unsafe {
         libc::_umtx_op(
-            futex as *const AtomicU32 as *mut _,
+            futex as *const Atomic<u32> as *mut _,
             libc::UMTX_OP_WAKE_PRIVATE,
             1,
             null_mut(),
@@ -132,11 +132,11 @@ pub fn futex_wake(futex: &AtomicU32) -> bool {
 }
 
 #[cfg(target_os = "freebsd")]
-pub fn futex_wake_all(futex: &AtomicU32) {
+pub fn futex_wake_all(futex: &Atomic<u32>) {
     use crate::ptr::null_mut;
     unsafe {
         libc::_umtx_op(
-            futex as *const AtomicU32 as *mut _,
+            futex as *const Atomic<u32> as *mut _,
             libc::UMTX_OP_WAKE_PRIVATE,
             i32::MAX as libc::c_ulong,
             null_mut(),
@@ -146,7 +146,7 @@ pub fn futex_wake_all(futex: &AtomicU32) {
 }
 
 #[cfg(target_os = "openbsd")]
-pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
+pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool {
     use super::time::Timespec;
     use crate::ptr::{null, null_mut};
 
@@ -157,7 +157,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
 
     let r = unsafe {
         libc::futex(
-            futex as *const AtomicU32 as *mut u32,
+            futex as *const Atomic<u32> as *mut u32,
             libc::FUTEX_WAIT,
             expected as i32,
             timespec.as_ref().map_or(null(), |t| t as *const libc::timespec),
@@ -169,20 +169,25 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
 }
 
 #[cfg(target_os = "openbsd")]
-pub fn futex_wake(futex: &AtomicU32) -> bool {
+pub fn futex_wake(futex: &Atomic<u32>) -> bool {
     use crate::ptr::{null, null_mut};
     unsafe {
-        libc::futex(futex as *const AtomicU32 as *mut u32, libc::FUTEX_WAKE, 1, null(), null_mut())
-            > 0
+        libc::futex(
+            futex as *const Atomic<u32> as *mut u32,
+            libc::FUTEX_WAKE,
+            1,
+            null(),
+            null_mut(),
+        ) > 0
     }
 }
 
 #[cfg(target_os = "openbsd")]
-pub fn futex_wake_all(futex: &AtomicU32) {
+pub fn futex_wake_all(futex: &Atomic<u32>) {
     use crate::ptr::{null, null_mut};
     unsafe {
         libc::futex(
-            futex as *const AtomicU32 as *mut u32,
+            futex as *const Atomic<u32> as *mut u32,
             libc::FUTEX_WAKE,
             i32::MAX,
             null(),
@@ -192,7 +197,7 @@ pub fn futex_wake_all(futex: &AtomicU32) {
 }
 
 #[cfg(target_os = "dragonfly")]
-pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
+pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool {
     // A timeout of 0 means infinite.
     // We round smaller timeouts up to 1 millisecond.
     // Overflows are rounded up to an infinite timeout.
@@ -200,7 +205,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
         timeout.and_then(|d| Some(i32::try_from(d.as_millis()).ok()?.max(1))).unwrap_or(0);
 
     let r = unsafe {
-        libc::umtx_sleep(futex as *const AtomicU32 as *const i32, expected as i32, timeout_ms)
+        libc::umtx_sleep(futex as *const Atomic<u32> as *const i32, expected as i32, timeout_ms)
     };
 
     r == 0 || super::os::errno() != libc::ETIMEDOUT
@@ -208,28 +213,28 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
 
 // DragonflyBSD doesn't tell us how many threads are woken up, so this always returns false.
 #[cfg(target_os = "dragonfly")]
-pub fn futex_wake(futex: &AtomicU32) -> bool {
-    unsafe { libc::umtx_wakeup(futex as *const AtomicU32 as *const i32, 1) };
+pub fn futex_wake(futex: &Atomic<u32>) -> bool {
+    unsafe { libc::umtx_wakeup(futex as *const Atomic<u32> as *const i32, 1) };
     false
 }
 
 #[cfg(target_os = "dragonfly")]
-pub fn futex_wake_all(futex: &AtomicU32) {
-    unsafe { libc::umtx_wakeup(futex as *const AtomicU32 as *const i32, i32::MAX) };
+pub fn futex_wake_all(futex: &Atomic<u32>) {
+    unsafe { libc::umtx_wakeup(futex as *const Atomic<u32> as *const i32, i32::MAX) };
 }
 
 #[cfg(target_os = "emscripten")]
 extern "C" {
-    fn emscripten_futex_wake(addr: *const AtomicU32, count: libc::c_int) -> libc::c_int;
+    fn emscripten_futex_wake(addr: *const Atomic<u32>, count: libc::c_int) -> libc::c_int;
     fn emscripten_futex_wait(
-        addr: *const AtomicU32,
+        addr: *const Atomic<u32>,
         val: libc::c_uint,
         max_wait_ms: libc::c_double,
     ) -> libc::c_int;
 }
 
 #[cfg(target_os = "emscripten")]
-pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
+pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool {
     unsafe {
         emscripten_futex_wait(
             futex,
@@ -240,18 +245,18 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
 }
 
 #[cfg(target_os = "emscripten")]
-pub fn futex_wake(futex: &AtomicU32) -> bool {
+pub fn futex_wake(futex: &Atomic<u32>) -> bool {
     unsafe { emscripten_futex_wake(futex, 1) > 0 }
 }
 
 #[cfg(target_os = "emscripten")]
-pub fn futex_wake_all(futex: &AtomicU32) {
+pub fn futex_wake_all(futex: &Atomic<u32>) {
     unsafe { emscripten_futex_wake(futex, i32::MAX) };
 }
 
 #[cfg(target_os = "fuchsia")]
 pub mod zircon {
-    pub type zx_futex_t = crate::sync::atomic::AtomicU32;
+    pub type zx_futex_t = crate::sync::atomic::Atomic;
     pub type zx_handle_t = u32;
     pub type zx_status_t = i32;
     pub type zx_time_t = i64;
@@ -282,7 +287,7 @@ pub mod zircon {
 }
 
 #[cfg(target_os = "fuchsia")]
-pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
+pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool {
     // Sleep forever if the timeout is longer than fits in a i64.
     let deadline = timeout
         .and_then(|d| {
@@ -300,12 +305,12 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
 
 // Fuchsia doesn't tell us how many threads are woken up, so this always returns false.
 #[cfg(target_os = "fuchsia")]
-pub fn futex_wake(futex: &AtomicU32) -> bool {
+pub fn futex_wake(futex: &Atomic<u32>) -> bool {
     unsafe { zircon::zx_futex_wake(futex, 1) };
     false
 }
 
 #[cfg(target_os = "fuchsia")]
-pub fn futex_wake_all(futex: &AtomicU32) {
+pub fn futex_wake_all(futex: &Atomic<u32>) {
     unsafe { zircon::zx_futex_wake(futex, u32::MAX) };
 }
diff --git a/library/std/src/sys/pal/unix/kernel_copy.rs b/library/std/src/sys/pal/unix/kernel_copy.rs
index bbf29f3252341..3c31c5c244f90 100644
--- a/library/std/src/sys/pal/unix/kernel_copy.rs
+++ b/library/std/src/sys/pal/unix/kernel_copy.rs
@@ -62,7 +62,7 @@ use crate::os::unix::io::{AsRawFd, FromRawFd, RawFd};
 use crate::os::unix::net::UnixStream;
 use crate::process::{ChildStderr, ChildStdin, ChildStdout};
 use crate::ptr;
-use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering};
+use crate::sync::atomic::{Atomic, AtomicBool, AtomicU8, Ordering};
 use crate::sys::cvt;
 use crate::sys::fs::CachedFileMetadata;
 use crate::sys::weak::syscall;
@@ -596,7 +596,7 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
 
     // Kernel prior to 4.5 don't have copy_file_range
     // We store the availability in a global to avoid unnecessary syscalls
-    static HAS_COPY_FILE_RANGE: AtomicU8 = AtomicU8::new(NOT_PROBED);
+    static HAS_COPY_FILE_RANGE: Atomic<u8> = AtomicU8::new(NOT_PROBED);
 
     let mut have_probed = match HAS_COPY_FILE_RANGE.load(Ordering::Relaxed) {
         NOT_PROBED => false,
@@ -721,8 +721,8 @@ enum SpliceMode {
 /// performs splice or sendfile between file descriptors
 /// Does _not_ fall back to a generic copy loop.
 fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) -> CopyResult {
-    static HAS_SENDFILE: AtomicBool = AtomicBool::new(true);
-    static HAS_SPLICE: AtomicBool = AtomicBool::new(true);
+    static HAS_SENDFILE: Atomic<bool> = AtomicBool::new(true);
+    static HAS_SPLICE: Atomic<bool> = AtomicBool::new(true);
 
     // Android builds use feature level 14, but the libc wrapper for splice is
     // gated on feature level 21+, so we have to invoke the syscall directly.
diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs
index 3cc1cae8d000e..67ea82ee83e3b 100644
--- a/library/std/src/sys/pal/unix/mod.rs
+++ b/library/std/src/sys/pal/unix/mod.rs
@@ -213,7 +213,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
     target_os = "vxworks",
     target_os = "vita",
 )))]
-static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::AtomicBool =
+static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::Atomic<bool> =
     crate::sync::atomic::AtomicBool::new(false);
 
 #[cfg(not(any(
diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs
index 2bff192a5bd83..4383821c5583e 100644
--- a/library/std/src/sys/pal/unix/process/process_unix.rs
+++ b/library/std/src/sys/pal/unix/process/process_unix.rs
@@ -438,7 +438,7 @@ impl Command {
         envp: Option<&CStringArray>,
     ) -> io::Result<Option<Process>> {
         #[cfg(target_os = "linux")]
-        use core::sync::atomic::{AtomicU8, Ordering};
+        use core::sync::atomic::{Atomic, AtomicU8, Ordering};
 
         use crate::mem::MaybeUninit;
         use crate::sys::{self, cvt_nz, on_broken_pipe_flag_used};
@@ -469,7 +469,7 @@ impl Command {
 
                 weak! { fn pidfd_getpid(libc::c_int) -> libc::c_int }
 
-                static PIDFD_SUPPORTED: AtomicU8 = AtomicU8::new(0);
+                static PIDFD_SUPPORTED: Atomic<u8> = AtomicU8::new(0);
                 const UNKNOWN: u8 = 0;
                 const SPAWN: u8 = 1;
                 // Obtaining a pidfd via the fork+exec path might work
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index db5c6bd3a1c32..e774b186620ca 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -49,7 +49,7 @@ mod imp {
     use crate::cell::Cell;
     use crate::ops::Range;
     use crate::sync::OnceLock;
-    use crate::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering};
+    use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering};
     use crate::sys::pal::unix::os;
     use crate::{io, mem, ptr, thread};
 
@@ -118,9 +118,9 @@ mod imp {
         }
     }
 
-    static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);
-    static MAIN_ALTSTACK: AtomicPtr<libc::c_void> = AtomicPtr::new(ptr::null_mut());
-    static NEED_ALTSTACK: AtomicBool = AtomicBool::new(false);
+    static PAGE_SIZE: Atomic<usize> = AtomicUsize::new(0);
+    static MAIN_ALTSTACK: Atomic<*mut libc::c_void> = AtomicPtr::new(ptr::null_mut());
+    static NEED_ALTSTACK: Atomic<bool> = AtomicBool::new(false);
 
     /// # Safety
     /// Must be called only once
diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs
index 35762f5a53b5b..26dffa139b04e 100644
--- a/library/std/src/sys/pal/unix/weak.rs
+++ b/library/std/src/sys/pal/unix/weak.rs
@@ -23,7 +23,7 @@
 
 use crate::ffi::CStr;
 use crate::marker::PhantomData;
-use crate::sync::atomic::{self, AtomicPtr, Ordering};
+use crate::sync::atomic::{self, Atomic, AtomicPtr, Ordering};
 use crate::{mem, ptr};
 
 // We can use true weak linkage on ELF targets.
@@ -73,7 +73,7 @@ pub(crate) macro dlsym {
 }
 pub(crate) struct DlsymWeak<F> {
     name: &'static str,
-    func: AtomicPtr<libc::c_void>,
+    func: Atomic<*mut libc::c_void>,
     _marker: PhantomData<F>,
 }
 
diff --git a/library/std/src/sys/pal/wasm/atomics/futex.rs b/library/std/src/sys/pal/wasm/atomics/futex.rs
index bdad0da73f0a5..b3343065d854c 100644
--- a/library/std/src/sys/pal/wasm/atomics/futex.rs
+++ b/library/std/src/sys/pal/wasm/atomics/futex.rs
@@ -3,7 +3,7 @@ use core::arch::wasm32 as wasm;
 #[cfg(target_arch = "wasm64")]
 use core::arch::wasm64 as wasm;
 
-use crate::sync::atomic::AtomicU32;
+use crate::sync::atomic::Atomic;
 use crate::time::Duration;
 
 /// An atomic for use as a futex that is at least 32-bits but may be larger
@@ -21,11 +21,14 @@ pub type SmallPrimitive = u32;
 /// Returns directly if the futex doesn't hold the expected value.
 ///
 /// Returns false on timeout, and true in all other cases.
-pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
+pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool {
     let timeout = timeout.and_then(|t| t.as_nanos().try_into().ok()).unwrap_or(-1);
     unsafe {
-        wasm::memory_atomic_wait32(futex as *const AtomicU32 as *mut i32, expected as i32, timeout)
-            < 2
+        wasm::memory_atomic_wait32(
+            futex as *const Atomic<u32> as *mut i32,
+            expected as i32,
+            timeout,
+        ) < 2
     }
 }
 
@@ -33,13 +36,13 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
 ///
 /// Returns true if this actually woke up such a thread,
 /// or false if no thread was waiting on this futex.
-pub fn futex_wake(futex: &AtomicU32) -> bool {
-    unsafe { wasm::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, 1) > 0 }
+pub fn futex_wake(futex: &Atomic<u32>) -> bool {
+    unsafe { wasm::memory_atomic_notify(futex as *const Atomic<u32> as *mut i32, 1) > 0 }
 }
 
 /// Wakes up all threads that are waiting on `futex_wait` on this futex.
-pub fn futex_wake_all(futex: &AtomicU32) {
+pub fn futex_wake_all(futex: &Atomic<u32>) {
     unsafe {
-        wasm::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, i32::MAX as u32);
+        wasm::memory_atomic_notify(futex as *const Atomic<u32> as *mut i32, i32::MAX as u32);
     }
 }
diff --git a/library/std/src/sys/pal/windows/compat.rs b/library/std/src/sys/pal/windows/compat.rs
index 42999da166451..16b2b97e384b6 100644
--- a/library/std/src/sys/pal/windows/compat.rs
+++ b/library/std/src/sys/pal/windows/compat.rs
@@ -145,7 +145,7 @@ macro_rules! compat_fn_with_fallback {
             use super::*;
             use crate::mem;
             use crate::ffi::CStr;
-            use crate::sync::atomic::{AtomicPtr, Ordering};
+            use crate::sync::atomic::{Atomic, AtomicPtr, Ordering};
             use crate::sys::compat::Module;
 
             type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
@@ -155,7 +155,7 @@ macro_rules! compat_fn_with_fallback {
             /// When that is called it attempts to load the requested symbol.
             /// If it succeeds, `PTR` is set to the address of that symbol.
             /// If it fails, then `PTR` is set to `fallback`.
-            static PTR: AtomicPtr<c_void> = AtomicPtr::new(load as *mut _);
+            static PTR: Atomic<*mut c_void> = AtomicPtr::new(load as *mut _);
 
             unsafe extern "system" fn load($($argname: $argtype),*) -> $rettype {
                 unsafe {
@@ -212,9 +212,9 @@ macro_rules! compat_fn_optional {
                 use crate::ffi::c_void;
                 use crate::mem;
                 use crate::ptr::{self, NonNull};
-                use crate::sync::atomic::{AtomicPtr, Ordering};
+                use crate::sync::atomic::{Atomic, AtomicPtr, Ordering};
 
-                pub(in crate::sys) static PTR: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
+                pub(in crate::sys) static PTR: Atomic<*mut c_void> = AtomicPtr::new(ptr::null_mut());
 
                 type F = unsafe extern "system" fn($($argtype),*) $(-> $rettype)?;
 
diff --git a/library/std/src/sys/pal/windows/fs/remove_dir_all.rs b/library/std/src/sys/pal/windows/fs/remove_dir_all.rs
index 9416049da78f8..3261d50d148a4 100644
--- a/library/std/src/sys/pal/windows/fs/remove_dir_all.rs
+++ b/library/std/src/sys/pal/windows/fs/remove_dir_all.rs
@@ -29,7 +29,7 @@
 //! race but we do make a best effort such that it *should* do so.
 
 use core::ptr;
-use core::sync::atomic::{AtomicU32, Ordering};
+use core::sync::atomic::{Atomic, AtomicU32, Ordering};
 
 use super::{AsRawHandle, DirBuff, File, FromRawHandle};
 use crate::sys::c;
@@ -87,7 +87,7 @@ fn open_link_no_reparse(
     // The `OBJ_DONT_REPARSE` attribute ensures that we haven't been
     // tricked into following a symlink. However, it may not be available in
     // earlier versions of Windows.
-    static ATTRIBUTES: AtomicU32 = AtomicU32::new(c::OBJ_DONT_REPARSE);
+    static ATTRIBUTES: Atomic<u32> = AtomicU32::new(c::OBJ_DONT_REPARSE);
 
     let result = unsafe {
         let mut path_str = c::UNICODE_STRING::from_ref(path);
diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs
index a8f6617c9dc8f..a37b7ddf2dcdf 100644
--- a/library/std/src/sys/pal/windows/pipe.rs
+++ b/library/std/src/sys/pal/windows/pipe.rs
@@ -3,8 +3,8 @@ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
 use crate::os::windows::prelude::*;
 use crate::path::Path;
 use crate::random::{DefaultRandomSource, Random};
-use crate::sync::atomic::AtomicUsize;
 use crate::sync::atomic::Ordering::Relaxed;
+use crate::sync::atomic::{Atomic, AtomicUsize};
 use crate::sys::c;
 use crate::sys::fs::{File, OpenOptions};
 use crate::sys::handle::Handle;
@@ -209,7 +209,7 @@ pub fn spawn_pipe_relay(
 }
 
 fn random_number() -> usize {
-    static N: AtomicUsize = AtomicUsize::new(0);
+    static N: Atomic<usize> = AtomicUsize::new(0);
     loop {
         if N.load(Relaxed) != 0 {
             return N.fetch_add(1, Relaxed);
diff --git a/library/std/src/sys/pal/windows/time.rs b/library/std/src/sys/pal/windows/time.rs
index d9010e3996109..68126bd8d2fa0 100644
--- a/library/std/src/sys/pal/windows/time.rs
+++ b/library/std/src/sys/pal/windows/time.rs
@@ -164,7 +164,7 @@ fn intervals2dur(intervals: u64) -> Duration {
 
 mod perf_counter {
     use super::NANOS_PER_SEC;
-    use crate::sync::atomic::{AtomicU64, Ordering};
+    use crate::sync::atomic::{Atomic, AtomicU64, Ordering};
     use crate::sys::{c, cvt};
     use crate::sys_common::mul_div_u64;
     use crate::time::Duration;
@@ -199,7 +199,7 @@ mod perf_counter {
         // uninitialized. Storing this as a single `AtomicU64` allows us to use
         // `Relaxed` operations, as we are only interested in the effects on a
         // single memory location.
-        static FREQUENCY: AtomicU64 = AtomicU64::new(0);
+        static FREQUENCY: Atomic<u64> = AtomicU64::new(0);
 
         let cached = FREQUENCY.load(Ordering::Relaxed);
         // If a previous thread has filled in this global state, use that.
diff --git a/library/std/src/sys/pal/xous/net/tcplistener.rs b/library/std/src/sys/pal/xous/net/tcplistener.rs
index 640a02a64f525..781401a169e68 100644
--- a/library/std/src/sys/pal/xous/net/tcplistener.rs
+++ b/library/std/src/sys/pal/xous/net/tcplistener.rs
@@ -1,5 +1,5 @@
 use core::convert::TryInto;
-use core::sync::atomic::{AtomicBool, AtomicU16, AtomicUsize, Ordering};
+use core::sync::atomic::{Atomic, AtomicBool, AtomicU16, AtomicUsize, Ordering};
 
 use super::*;
 use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
@@ -18,10 +18,10 @@ macro_rules! unimpl {
 
 #[derive(Clone)]
 pub struct TcpListener {
-    fd: Arc<AtomicU16>,
+    fd: Arc<Atomic<u16>>,
     local: SocketAddr,
-    handle_count: Arc<AtomicUsize>,
-    nonblocking: Arc<AtomicBool>,
+    handle_count: Arc<Atomic<usize>>,
+    nonblocking: Arc<Atomic<bool>>,
 }
 
 impl TcpListener {
diff --git a/library/std/src/sys/pal/xous/net/tcpstream.rs b/library/std/src/sys/pal/xous/net/tcpstream.rs
index 572dd6b3b6398..64dda6a078632 100644
--- a/library/std/src/sys/pal/xous/net/tcpstream.rs
+++ b/library/std/src/sys/pal/xous/net/tcpstream.rs
@@ -1,4 +1,4 @@
-use core::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering};
+use core::sync::atomic::{Atomic, AtomicBool, AtomicU32, AtomicUsize, Ordering};
 
 use super::*;
 use crate::fmt;
@@ -29,11 +29,11 @@ pub struct TcpStream {
     remote_port: u16,
     peer_addr: SocketAddr,
     // milliseconds
-    read_timeout: Arc<AtomicU32>,
+    read_timeout: Arc<Atomic<u32>>,
     // milliseconds
-    write_timeout: Arc<AtomicU32>,
-    handle_count: Arc<AtomicUsize>,
-    nonblocking: Arc<AtomicBool>,
+    write_timeout: Arc<Atomic<u32>>,
+    handle_count: Arc<Atomic<usize>>,
+    nonblocking: Arc<Atomic<bool>>,
 }
 
 fn sockaddr_to_buf(duration: Duration, addr: &SocketAddr, buf: &mut [u8]) {
diff --git a/library/std/src/sys/pal/xous/net/udp.rs b/library/std/src/sys/pal/xous/net/udp.rs
index 1b7ecac6d3a7e..d6700f15a0ee2 100644
--- a/library/std/src/sys/pal/xous/net/udp.rs
+++ b/library/std/src/sys/pal/xous/net/udp.rs
@@ -1,5 +1,5 @@
 use core::convert::TryInto;
-use core::sync::atomic::{AtomicUsize, Ordering};
+use core::sync::atomic::{Atomic, AtomicUsize, Ordering};
 
 use super::*;
 use crate::cell::Cell;
@@ -27,7 +27,7 @@ pub struct UdpSocket {
     read_timeout: Cell<u64>,
     // in milliseconds. The setting applies only to `send` calls after the timeout is set.
     write_timeout: Cell<u64>,
-    handle_count: Arc<AtomicUsize>,
+    handle_count: Arc<Atomic<usize>>,
     nonblocking: Cell<bool>,
 }
 
diff --git a/library/std/src/sys/pal/xous/os.rs b/library/std/src/sys/pal/xous/os.rs
index b0ab01a6383d2..e4331541cb81d 100644
--- a/library/std/src/sys/pal/xous/os.rs
+++ b/library/std/src/sys/pal/xous/os.rs
@@ -5,13 +5,13 @@ use crate::ffi::{OsStr, OsString};
 use crate::marker::PhantomData;
 use crate::os::xous::ffi::Error as XousError;
 use crate::path::{self, PathBuf};
-use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
+use crate::sync::atomic::{Atomic, AtomicPtr, AtomicUsize, Ordering};
 use crate::sync::{Mutex, Once};
 use crate::{fmt, io, vec};
 
 pub(crate) mod params;
 
-static PARAMS_ADDRESS: AtomicPtr<u8> = AtomicPtr::new(core::ptr::null_mut());
+static PARAMS_ADDRESS: Atomic<*mut u8> = AtomicPtr::new(core::ptr::null_mut());
 
 #[cfg(not(test))]
 #[cfg(feature = "panic_unwind")]
@@ -137,7 +137,7 @@ pub(crate) fn get_application_parameters() -> Option<params::ApplicationParamete
 }
 
 // ---------- Environment handling ---------- //
-static ENV: AtomicUsize = AtomicUsize::new(0);
+static ENV: Atomic<usize> = AtomicUsize::new(0);
 static ENV_INIT: Once = Once::new();
 type EnvStore = Mutex<HashMap<OsString, OsString>>;
 
diff --git a/library/std/src/sys/random/linux.rs b/library/std/src/sys/random/linux.rs
index e3cb79285cd15..190eb3384df12 100644
--- a/library/std/src/sys/random/linux.rs
+++ b/library/std/src/sys/random/linux.rs
@@ -64,8 +64,8 @@ use crate::fs::File;
 use crate::io::Read;
 use crate::os::fd::AsRawFd;
 use crate::sync::OnceLock;
-use crate::sync::atomic::AtomicBool;
 use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use crate::sync::atomic::{Atomic, AtomicBool};
 use crate::sys::pal::os::errno;
 use crate::sys::pal::weak::syscall;
 
@@ -81,9 +81,9 @@ fn getrandom(mut bytes: &mut [u8], insecure: bool) {
         ) -> libc::ssize_t
     }
 
-    static GETRANDOM_AVAILABLE: AtomicBool = AtomicBool::new(true);
-    static GRND_INSECURE_AVAILABLE: AtomicBool = AtomicBool::new(true);
-    static URANDOM_READY: AtomicBool = AtomicBool::new(false);
+    static GETRANDOM_AVAILABLE: Atomic<bool> = AtomicBool::new(true);
+    static GRND_INSECURE_AVAILABLE: Atomic<bool> = AtomicBool::new(true);
+    static URANDOM_READY: Atomic<bool> = AtomicBool::new(false);
     static DEVICE: OnceLock<File> = OnceLock::new();
 
     if GETRANDOM_AVAILABLE.load(Relaxed) {
diff --git a/library/std/src/sys/random/vxworks.rs b/library/std/src/sys/random/vxworks.rs
index d549ccebdb2cd..14f02e8ecd220 100644
--- a/library/std/src/sys/random/vxworks.rs
+++ b/library/std/src/sys/random/vxworks.rs
@@ -1,7 +1,7 @@
-use crate::sync::atomic::AtomicBool;
 use crate::sync::atomic::Ordering::Relaxed;
+use crate::sync::atomic::{Atomic, AtomicBool};
 
-static RNG_INIT: AtomicBool = AtomicBool::new(false);
+static RNG_INIT: Atomic<bool> = AtomicBool::new(false);
 
 pub fn fill_bytes(mut bytes: &mut [u8]) {
     while !RNG_INIT.load(Relaxed) {
diff --git a/library/std/src/sys/sync/condvar/pthread.rs b/library/std/src/sys/sync/condvar/pthread.rs
index 5bb7431eecf0c..938b7071b88a7 100644
--- a/library/std/src/sys/sync/condvar/pthread.rs
+++ b/library/std/src/sys/sync/condvar/pthread.rs
@@ -2,15 +2,15 @@
 
 use crate::pin::Pin;
 use crate::ptr;
-use crate::sync::atomic::AtomicUsize;
 use crate::sync::atomic::Ordering::Relaxed;
+use crate::sync::atomic::{Atomic, AtomicUsize};
 use crate::sys::pal::sync as pal;
 use crate::sys::sync::{Mutex, OnceBox};
 use crate::time::{Duration, Instant};
 
 pub struct Condvar {
     cvar: OnceBox<pal::Condvar>,
-    mutex: AtomicUsize,
+    mutex: Atomic<usize>,
 }
 
 impl Condvar {
diff --git a/library/std/src/sys/sync/condvar/xous.rs b/library/std/src/sys/sync/condvar/xous.rs
index b9e5f47abfcc2..21a1587214a11 100644
--- a/library/std/src/sys/sync/condvar/xous.rs
+++ b/library/std/src/sys/sync/condvar/xous.rs
@@ -1,4 +1,4 @@
-use core::sync::atomic::{AtomicUsize, Ordering};
+use core::sync::atomic::{Atomic, AtomicUsize, Ordering};
 
 use crate::os::xous::ffi::{blocking_scalar, scalar};
 use crate::os::xous::services::{TicktimerScalar, ticktimer_server};
@@ -11,8 +11,8 @@ use crate::time::Duration;
 const NOTIFY_TRIES: usize = 3;
 
 pub struct Condvar {
-    counter: AtomicUsize,
-    timed_out: AtomicUsize,
+    counter: Atomic<usize>,
+    timed_out: Atomic<usize>,
 }
 
 unsafe impl Send for Condvar {}
diff --git a/library/std/src/sys/sync/mutex/fuchsia.rs b/library/std/src/sys/sync/mutex/fuchsia.rs
index 3e871285bea01..3d388a4564a3f 100644
--- a/library/std/src/sys/sync/mutex/fuchsia.rs
+++ b/library/std/src/sys/sync/mutex/fuchsia.rs
@@ -37,8 +37,8 @@
 //!
 //! [mutex in Fuchsia's libsync]: https://cs.opensource.google/fuchsia/fuchsia/+/main:zircon/system/ulib/sync/mutex.c
 
-use crate::sync::atomic::AtomicU32;
 use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use crate::sync::atomic::{Atomic, AtomicU32};
 use crate::sys::futex::zircon::{
     ZX_ERR_BAD_HANDLE, ZX_ERR_BAD_STATE, ZX_ERR_INVALID_ARGS, ZX_ERR_TIMED_OUT, ZX_ERR_WRONG_TYPE,
     ZX_OK, ZX_TIME_INFINITE, zx_futex_wait, zx_futex_wake_single_owner, zx_handle_t,
@@ -52,7 +52,7 @@ const CONTESTED_BIT: u32 = 1;
 const UNLOCKED: u32 = 0;
 
 pub struct Mutex {
-    futex: AtomicU32,
+    futex: Atomic<u32>,
 }
 
 #[inline]
diff --git a/library/std/src/sys/sync/mutex/xous.rs b/library/std/src/sys/sync/mutex/xous.rs
index c6b954c1711e6..d16faa5aea319 100644
--- a/library/std/src/sys/sync/mutex/xous.rs
+++ b/library/std/src/sys/sync/mutex/xous.rs
@@ -1,7 +1,7 @@
 use crate::os::xous::ffi::{blocking_scalar, do_yield};
 use crate::os::xous::services::{TicktimerScalar, ticktimer_server};
 use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
-use crate::sync::atomic::{AtomicBool, AtomicUsize};
+use crate::sync::atomic::{Atomic, AtomicBool, AtomicUsize};
 
 pub struct Mutex {
     /// The "locked" value indicates how many threads are waiting on this
@@ -14,12 +14,12 @@ pub struct Mutex {
     /// for a lock, or it is locked for long periods of time. Rather than
     /// spinning, these locks send a Message to the ticktimer server
     /// requesting that they be woken up when a lock is unlocked.
-    locked: AtomicUsize,
+    locked: Atomic<usize>,
 
     /// Whether this Mutex ever was contended, and therefore made a trip
     /// to the ticktimer server. If this was never set, then we were never
     /// on the slow path and can skip deregistering the mutex.
-    contended: AtomicBool,
+    contended: Atomic<bool>,
 }
 
 impl Mutex {
diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs
index fde1e0ca51029..6a2ab0dcf1b33 100644
--- a/library/std/src/sys/sync/once/queue.rs
+++ b/library/std/src/sys/sync/once/queue.rs
@@ -57,7 +57,7 @@
 
 use crate::cell::Cell;
 use crate::sync::atomic::Ordering::{AcqRel, Acquire, Release};
-use crate::sync::atomic::{AtomicBool, AtomicPtr};
+use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr};
 use crate::sync::poison::once::ExclusiveState;
 use crate::thread::{self, Thread};
 use crate::{fmt, ptr, sync as public};
@@ -65,7 +65,7 @@ use crate::{fmt, ptr, sync as public};
 type StateAndQueue = *mut ();
 
 pub struct Once {
-    state_and_queue: AtomicPtr<()>,
+    state_and_queue: Atomic<*mut ()>,
 }
 
 pub struct OnceState {
@@ -94,7 +94,7 @@ const QUEUE_MASK: usize = !STATE_MASK;
 #[repr(align(4))] // Ensure the two lower bits are free to use as state bits.
 struct Waiter {
     thread: Thread,
-    signaled: AtomicBool,
+    signaled: Atomic<bool>,
     next: Cell<*const Waiter>,
 }
 
@@ -102,7 +102,7 @@ struct Waiter {
 // Every node is a struct on the stack of a waiting thread.
 // Will wake up the waiters when it gets dropped, i.e. also on panic.
 struct WaiterQueue<'a> {
-    state_and_queue: &'a AtomicPtr<()>,
+    state_and_queue: &'a Atomic<*mut ()>,
     set_state_on_drop_to: StateAndQueue,
 }
 
@@ -232,7 +232,7 @@ impl Once {
 }
 
 fn wait(
-    state_and_queue: &AtomicPtr<()>,
+    state_and_queue: &Atomic<*mut ()>,
     mut current: StateAndQueue,
     return_on_poisoned: bool,
 ) -> StateAndQueue {
diff --git a/library/std/src/sys/sync/once_box.rs b/library/std/src/sys/sync/once_box.rs
index 6953b91999ad1..088f51aae78e6 100644
--- a/library/std/src/sys/sync/once_box.rs
+++ b/library/std/src/sys/sync/once_box.rs
@@ -8,11 +8,11 @@
 use crate::mem::replace;
 use crate::pin::Pin;
 use crate::ptr::null_mut;
-use crate::sync::atomic::AtomicPtr;
 use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use crate::sync::atomic::{Atomic, AtomicPtr};
 
 pub(crate) struct OnceBox<T> {
-    ptr: AtomicPtr<T>,
+    ptr: Atomic<*mut T>,
 }
 
 impl<T> OnceBox<T> {
diff --git a/library/std/src/sys/sync/rwlock/queue.rs b/library/std/src/sys/sync/rwlock/queue.rs
index bd15f8ee952c9..62f084acfd259 100644
--- a/library/std/src/sys/sync/rwlock/queue.rs
+++ b/library/std/src/sys/sync/rwlock/queue.rs
@@ -117,11 +117,11 @@ use crate::hint::spin_loop;
 use crate::mem;
 use crate::ptr::{self, NonNull, null_mut, without_provenance_mut};
 use crate::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release};
-use crate::sync::atomic::{AtomicBool, AtomicPtr};
+use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr};
 use crate::thread::{self, Thread};
 
 /// The atomic lock state.
-type AtomicState = AtomicPtr<()>;
+type AtomicState = Atomic<State>;
 /// The inner lock state.
 type State = *mut ();
 
@@ -181,11 +181,11 @@ struct Node {
     tail: AtomicLink,
     write: bool,
     thread: OnceCell<Thread>,
-    completed: AtomicBool,
+    completed: Atomic<bool>,
 }
 
 /// An atomic node pointer with relaxed operations.
-struct AtomicLink(AtomicPtr<Node>);
+struct AtomicLink(Atomic<*mut Node>);
 
 impl AtomicLink {
     fn new(v: Option<NonNull<Node>>) -> AtomicLink {
diff --git a/library/std/src/sys/sync/thread_parking/darwin.rs b/library/std/src/sys/sync/thread_parking/darwin.rs
index 0553c5e19a91f..5a6ed669aafb7 100644
--- a/library/std/src/sys/sync/thread_parking/darwin.rs
+++ b/library/std/src/sys/sync/thread_parking/darwin.rs
@@ -13,8 +13,8 @@
 #![allow(non_camel_case_types)]
 
 use crate::pin::Pin;
-use crate::sync::atomic::AtomicI8;
 use crate::sync::atomic::Ordering::{Acquire, Release};
+use crate::sync::atomic::{Atomic, AtomicI8};
 use crate::time::Duration;
 
 type dispatch_semaphore_t = *mut crate::ffi::c_void;
@@ -38,7 +38,7 @@ const PARKED: i8 = -1;
 
 pub struct Parker {
     semaphore: dispatch_semaphore_t,
-    state: AtomicI8,
+    state: Atomic<i8>,
 }
 
 unsafe impl Sync for Parker {}
diff --git a/library/std/src/sys/sync/thread_parking/id.rs b/library/std/src/sys/sync/thread_parking/id.rs
index 6496435183770..fcc6ecca62867 100644
--- a/library/std/src/sys/sync/thread_parking/id.rs
+++ b/library/std/src/sys/sync/thread_parking/id.rs
@@ -10,12 +10,12 @@
 use crate::cell::UnsafeCell;
 use crate::pin::Pin;
 use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
-use crate::sync::atomic::{AtomicI8, fence};
+use crate::sync::atomic::{Atomic, AtomicI8, fence};
 use crate::sys::thread_parking::{ThreadId, current, park, park_timeout, unpark};
 use crate::time::Duration;
 
 pub struct Parker {
-    state: AtomicI8,
+    state: Atomic<i8>,
     tid: UnsafeCell<Option<ThreadId>>,
 }
 
diff --git a/library/std/src/sys/sync/thread_parking/pthread.rs b/library/std/src/sys/sync/thread_parking/pthread.rs
index 19cabd7dd75c8..14bc793c15de2 100644
--- a/library/std/src/sys/sync/thread_parking/pthread.rs
+++ b/library/std/src/sys/sync/thread_parking/pthread.rs
@@ -1,8 +1,8 @@
 //! Thread parking without `futex` using the `pthread` synchronization primitives.
 
 use crate::pin::Pin;
-use crate::sync::atomic::AtomicUsize;
 use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use crate::sync::atomic::{Atomic, AtomicUsize};
 use crate::sys::pal::sync::{Condvar, Mutex};
 use crate::time::Duration;
 
@@ -11,7 +11,7 @@ const PARKED: usize = 1;
 const NOTIFIED: usize = 2;
 
 pub struct Parker {
-    state: AtomicUsize,
+    state: Atomic<usize>,
     lock: Mutex,
     cvar: Condvar,
 }
diff --git a/library/std/src/sys/sync/thread_parking/windows7.rs b/library/std/src/sys/sync/thread_parking/windows7.rs
index f7585e882f055..ccc84392a71ac 100644
--- a/library/std/src/sys/sync/thread_parking/windows7.rs
+++ b/library/std/src/sys/sync/thread_parking/windows7.rs
@@ -60,13 +60,13 @@
 use core::ffi::c_void;
 
 use crate::pin::Pin;
-use crate::sync::atomic::AtomicI8;
 use crate::sync::atomic::Ordering::{Acquire, Release};
+use crate::sync::atomic::{Atomic, AtomicI8};
 use crate::sys::{c, dur2timeout};
 use crate::time::Duration;
 
 pub struct Parker {
-    state: AtomicI8,
+    state: Atomic<i8>,
 }
 
 const PARKED: i8 = -1;
@@ -186,8 +186,8 @@ impl Parker {
 mod keyed_events {
     use core::pin::Pin;
     use core::ptr;
-    use core::sync::atomic::AtomicPtr;
     use core::sync::atomic::Ordering::{Acquire, Relaxed};
+    use core::sync::atomic::{Atomic, AtomicPtr};
     use core::time::Duration;
 
     use super::{EMPTY, NOTIFIED, Parker};
@@ -244,7 +244,7 @@ mod keyed_events {
 
     fn keyed_event_handle() -> c::HANDLE {
         const INVALID: c::HANDLE = ptr::without_provenance_mut(!0);
-        static HANDLE: AtomicPtr<crate::ffi::c_void> = AtomicPtr::new(INVALID);
+        static HANDLE: Atomic<*mut crate::ffi::c_void> = AtomicPtr::new(INVALID);
         match HANDLE.load(Relaxed) {
             INVALID => {
                 let mut handle = c::INVALID_HANDLE_VALUE;
diff --git a/library/std/src/sys/sync/thread_parking/xous.rs b/library/std/src/sys/sync/thread_parking/xous.rs
index 28c90249dc2c2..0f451c0ac29f9 100644
--- a/library/std/src/sys/sync/thread_parking/xous.rs
+++ b/library/std/src/sys/sync/thread_parking/xous.rs
@@ -2,8 +2,8 @@ use crate::os::xous::ffi::{blocking_scalar, scalar};
 use crate::os::xous::services::{TicktimerScalar, ticktimer_server};
 use crate::pin::Pin;
 use crate::ptr;
-use crate::sync::atomic::AtomicI8;
 use crate::sync::atomic::Ordering::{Acquire, Release};
+use crate::sync::atomic::{Atomic, AtomicI8};
 use crate::time::Duration;
 
 const NOTIFIED: i8 = 1;
@@ -11,7 +11,7 @@ const EMPTY: i8 = 0;
 const PARKED: i8 = -1;
 
 pub struct Parker {
-    state: AtomicI8,
+    state: Atomic<i8>,
 }
 
 impl Parker {
diff --git a/library/std/src/sys/thread_local/key/racy.rs b/library/std/src/sys/thread_local/key/racy.rs
index e1bc08eabb358..a12ff7ac36ba5 100644
--- a/library/std/src/sys/thread_local/key/racy.rs
+++ b/library/std/src/sys/thread_local/key/racy.rs
@@ -6,7 +6,7 @@
 //! should be more lightweight and avoids circular dependencies with the rest of
 //! `std`.
 
-use crate::sync::atomic::{self, AtomicUsize, Ordering};
+use crate::sync::atomic::{Atomic, AtomicUsize, Ordering};
 
 /// A type for TLS keys that are statically allocated.
 ///
@@ -14,7 +14,7 @@ use crate::sync::atomic::{self, AtomicUsize, Ordering};
 /// dependencies with the rest of `std`.
 pub struct LazyKey {
     /// Inner static TLS key (internals).
-    key: AtomicUsize,
+    key: Atomic<usize>,
     /// Destructor for the TLS value.
     dtor: Option<unsafe extern "C" fn(*mut u8)>,
 }
@@ -31,7 +31,7 @@ const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1;
 
 impl LazyKey {
     pub const fn new(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> LazyKey {
-        LazyKey { key: atomic::AtomicUsize::new(KEY_SENTVAL), dtor }
+        LazyKey { key: AtomicUsize::new(KEY_SENTVAL), dtor }
     }
 
     #[inline]
diff --git a/library/std/src/sys/thread_local/key/windows.rs b/library/std/src/sys/thread_local/key/windows.rs
index f4e0f25a476ee..c34c7bc204fd4 100644
--- a/library/std/src/sys/thread_local/key/windows.rs
+++ b/library/std/src/sys/thread_local/key/windows.rs
@@ -27,7 +27,7 @@
 use crate::cell::UnsafeCell;
 use crate::ptr;
 use crate::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release};
-use crate::sync::atomic::{AtomicPtr, AtomicU32};
+use crate::sync::atomic::{Atomic, AtomicPtr, AtomicU32};
 use crate::sys::c;
 use crate::sys::thread_local::guard;
 
@@ -38,9 +38,9 @@ pub struct LazyKey {
     /// The key value shifted up by one. Since TLS_OUT_OF_INDEXES == u32::MAX
     /// is not a valid key value, this allows us to use zero as sentinel value
     /// without risking overflow.
-    key: AtomicU32,
+    key: Atomic<Key>,
     dtor: Option<Dtor>,
-    next: AtomicPtr<LazyKey>,
+    next: Atomic<*mut LazyKey>,
     /// Currently, destructors cannot be unregistered, so we cannot use racy
     /// initialization for keys. Instead, we need synchronize initialization.
     /// Use the Windows-provided `Once` since it does not require TLS.
@@ -142,7 +142,7 @@ pub unsafe fn get(key: Key) -> *mut u8 {
     unsafe { c::TlsGetValue(key).cast() }
 }
 
-static DTORS: AtomicPtr<LazyKey> = AtomicPtr::new(ptr::null_mut());
+static DTORS: Atomic<*mut LazyKey> = AtomicPtr::new(ptr::null_mut());
 
 /// Should only be called once per key, otherwise loops or breaks may occur in
 /// the linked list.
diff --git a/library/std/src/sys/thread_local/key/xous.rs b/library/std/src/sys/thread_local/key/xous.rs
index 2ab4bba7d8e98..d5a490b5b8435 100644
--- a/library/std/src/sys/thread_local/key/xous.rs
+++ b/library/std/src/sys/thread_local/key/xous.rs
@@ -42,7 +42,7 @@ use crate::mem::ManuallyDrop;
 use crate::os::xous::ffi::{MemoryFlags, map_memory, unmap_memory};
 use crate::ptr;
 use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
-use crate::sync::atomic::{AtomicPtr, AtomicUsize};
+use crate::sync::atomic::{Atomic, AtomicPtr, AtomicUsize};
 
 pub type Key = usize;
 pub type Dtor = unsafe extern "C" fn(*mut u8);
@@ -52,19 +52,19 @@ const TLS_MEMORY_SIZE: usize = 4096;
 /// TLS keys start at `1`. Index `0` is unused
 #[cfg(not(test))]
 #[export_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key13TLS_KEY_INDEXE"]
-static TLS_KEY_INDEX: AtomicUsize = AtomicUsize::new(1);
+static TLS_KEY_INDEX: Atomic<usize> = AtomicUsize::new(1);
 
 #[cfg(not(test))]
 #[export_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key9DTORSE"]
-static DTORS: AtomicPtr<Node> = AtomicPtr::new(ptr::null_mut());
+static DTORS: Atomic<*mut Node> = AtomicPtr::new(ptr::null_mut());
 
 #[cfg(test)]
 extern "Rust" {
     #[link_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key13TLS_KEY_INDEXE"]
-    static TLS_KEY_INDEX: AtomicUsize;
+    static TLS_KEY_INDEX: Atomic<usize>;
 
     #[link_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key9DTORSE"]
-    static DTORS: AtomicPtr<Node>;
+    static DTORS: Atomic<*mut Node>;
 }
 
 fn tls_ptr_addr() -> *mut *mut u8 {
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 59b395336f2e3..282a25c0381d1 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -166,7 +166,7 @@ use crate::mem::{self, ManuallyDrop, forget};
 use crate::num::NonZero;
 use crate::pin::Pin;
 use crate::sync::Arc;
-use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sync::atomic::{Atomic, AtomicUsize, Ordering};
 use crate::sys::sync::Parker;
 use crate::sys::thread as imp;
 use crate::sys_common::{AsInner, IntoInner};
@@ -481,7 +481,7 @@ impl Builder {
         let Builder { name, stack_size, no_hooks } = self;
 
         let stack_size = stack_size.unwrap_or_else(|| {
-            static MIN: AtomicUsize = AtomicUsize::new(0);
+            static MIN: Atomic<usize> = AtomicUsize::new(0);
 
             match MIN.load(Ordering::Relaxed) {
                 0 => {}
@@ -1195,9 +1195,9 @@ impl ThreadId {
 
         cfg_if::cfg_if! {
             if #[cfg(target_has_atomic = "64")] {
-                use crate::sync::atomic::AtomicU64;
+                use crate::sync::atomic::{Atomic, AtomicU64};
 
-                static COUNTER: AtomicU64 = AtomicU64::new(0);
+                static COUNTER: Atomic<u64> = AtomicU64::new(0);
 
                 let mut last = COUNTER.load(Ordering::Relaxed);
                 loop {
@@ -1302,10 +1302,10 @@ pub(crate) mod main_thread {
     cfg_if::cfg_if! {
         if #[cfg(target_has_atomic = "64")] {
             use super::ThreadId;
-            use crate::sync::atomic::AtomicU64;
+            use crate::sync::atomic::{Atomic, AtomicU64};
             use crate::sync::atomic::Ordering::Relaxed;
 
-            static MAIN: AtomicU64 = AtomicU64::new(0);
+            static MAIN: Atomic<u64> = AtomicU64::new(0);
 
             pub(super) fn get() -> Option<ThreadId> {
                 ThreadId::from_u64(MAIN.load(Relaxed))
@@ -1319,10 +1319,10 @@ pub(crate) mod main_thread {
         } else {
             use super::ThreadId;
             use crate::mem::MaybeUninit;
-            use crate::sync::atomic::AtomicBool;
+            use crate::sync::atomic::{Atomic, AtomicBool};
             use crate::sync::atomic::Ordering::{Acquire, Release};
 
-            static INIT: AtomicBool = AtomicBool::new(false);
+            static INIT: Atomic<bool> = AtomicBool::new(false);
             static mut MAIN: MaybeUninit<ThreadId> = MaybeUninit::uninit();
 
             pub(super) fn get() -> Option<ThreadId> {
diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs
index 0033fc3a73283..a4c0ca5417d00 100644
--- a/library/std/src/thread/scoped.rs
+++ b/library/std/src/thread/scoped.rs
@@ -2,7 +2,7 @@ use super::{Builder, JoinInner, Result, Thread, current_or_unnamed};
 use crate::marker::PhantomData;
 use crate::panic::{AssertUnwindSafe, catch_unwind, resume_unwind};
 use crate::sync::Arc;
-use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
+use crate::sync::atomic::{Atomic, AtomicBool, AtomicUsize, Ordering};
 use crate::{fmt, io};
 
 /// A scope to spawn scoped threads in.
@@ -35,8 +35,8 @@ pub struct Scope<'scope, 'env: 'scope> {
 pub struct ScopedJoinHandle<'scope, T>(JoinInner<'scope, T>);
 
 pub(super) struct ScopeData {
-    num_running_threads: AtomicUsize,
-    a_thread_panicked: AtomicBool,
+    num_running_threads: Atomic<usize>,
+    a_thread_panicked: Atomic<bool>,
     main_thread: Thread,
 }