Merge f8fc262150fb8a250f77deeb7c6285d6ccbb2bd4 on remote branch

Change-Id: I60b56cef16512fe87bcd9e61b13e6214686b8c4e
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 1f53d5d..0d40a83 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "6d4cdd4daf9a897deef6cde9569f2fbf12c29bc5"
-  }
-}
+    "sha1": "2988f873f87d2263a7fd2b9465fb9c28f43a6490"
+  },
+  "path_in_vcs": "crossbeam-utils"
+}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 60ccb4e..5f17007 100644
--- a/Android.bp
+++ b/Android.bp
@@ -44,7 +44,7 @@
     host_supported: true,
     crate_name: "crossbeam_utils",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.8.5",
+    cargo_pkg_version: "0.8.7",
     srcs: ["src/lib.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
@@ -62,13 +62,14 @@
         "liblazy_static",
         "librand",
     ],
+    proc_macros: ["librustversion"],
 }
 
 rust_defaults {
     name: "crossbeam-utils_test_defaults",
     crate_name: "crossbeam_utils",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.8.5",
+    cargo_pkg_version: "0.8.7",
     test_suites: ["general-tests"],
     auto_gen_config: true,
     edition: "2018",
@@ -83,6 +84,7 @@
         "liblazy_static",
         "librand",
     ],
+    proc_macros: ["librustversion"],
 }
 
 rust_test {
@@ -150,7 +152,7 @@
     host_supported: true,
     crate_name: "crossbeam_utils",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.8.5",
+    cargo_pkg_version: "0.8.7",
     srcs: ["src/lib.rs"],
     edition: "2018",
     features: [
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c485ef..98088c5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,18 @@
+# Version 0.8.7
+
+- Add `AtomicCell<{i*,u*}>::{fetch_max,fetch_min}`. (#785)
+- Add `AtomicCell<{i*,u*,bool}>::fetch_nand`. (#785)
+- Fix unsoundness of `AtomicCell<{i,u}64>` arithmetics on 32-bit targets that support `Atomic{I,U}64` (#781)
+
+# Version 0.8.6
+
+- Re-add `AtomicCell<{i,u}64>::{fetch_add,fetch_sub,fetch_and,fetch_or,fetch_xor}` that were accidentally removed in 0.8.0 on targets that do not support `Atomic{I,U}64`. (#767)
+- Re-add `AtomicCell<{i,u}128>::{fetch_add,fetch_sub,fetch_and,fetch_or,fetch_xor}` that were accidentally removed in 0.8.0. (#767)
+
 # Version 0.8.5
 
-- Add `AtomicCell::fetch_update` (#704)
-- Support targets that do not have atomic CAS on stable Rust (#698)
+- Add `AtomicCell::fetch_update`. (#704)
+- Support targets that do not have atomic CAS on stable Rust. (#698)
 
 # Version 0.8.4
 
diff --git a/Cargo.toml b/Cargo.toml
index 0b32b46..10d3240 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,38 +3,52 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
 edition = "2018"
+rust-version = "1.36"
 name = "crossbeam-utils"
-version = "0.8.5"
-authors = ["The Crossbeam Project Developers"]
+version = "0.8.7"
 description = "Utilities for concurrent programming"
 homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils"
-documentation = "https://docs.rs/crossbeam-utils"
-keywords = ["scoped", "thread", "atomic", "cache"]
-categories = ["algorithms", "concurrency", "data-structures", "no-std"]
+keywords = [
+    "scoped",
+    "thread",
+    "atomic",
+    "cache",
+]
+categories = [
+    "algorithms",
+    "concurrency",
+    "data-structures",
+    "no-std",
+]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/crossbeam-rs/crossbeam"
+
 [dependencies.cfg-if]
 version = "1"
 
 [dependencies.lazy_static]
 version = "1.4.0"
 optional = true
+
 [dev-dependencies.rand]
 version = "0.8"
 
+[dev-dependencies.rustversion]
+version = "1"
+
 [features]
 default = ["std"]
 nightly = []
 std = ["lazy_static"]
+
 [target."cfg(crossbeam_loom)".dependencies.loom]
 version = "0.5"
 optional = true
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 16488cb..73508a9 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -4,13 +4,12 @@
 # - Update CHANGELOG.md
 # - Update README.md
 # - Create "crossbeam-utils-X.Y.Z" git tag
-version = "0.8.5"
-authors = ["The Crossbeam Project Developers"]
+version = "0.8.7"
 edition = "2018"
+rust-version = "1.36"
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/crossbeam-rs/crossbeam"
 homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils"
-documentation = "https://docs.rs/crossbeam-utils"
 description = "Utilities for concurrent programming"
 keywords = ["scoped", "thread", "atomic", "cache"]
 categories = ["algorithms", "concurrency", "data-structures", "no-std"]
@@ -44,3 +43,4 @@
 
 [dev-dependencies]
 rand = "0.8"
+rustversion = "1"
diff --git a/METADATA b/METADATA
index e332569..2c55b77 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/crossbeam-utils/crossbeam-utils-0.8.5.crate"
+    value: "https://static.crates.io/crates/crossbeam-utils/crossbeam-utils-0.8.7.crate"
   }
-  version: "0.8.5"
+  version: "0.8.7"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
-    month: 6
-    day: 21
+    year: 2022
+    month: 3
+    day: 1
   }
 }
diff --git a/build.rs b/build.rs
index 9c924ad..a7557fd 100644
--- a/build.rs
+++ b/build.rs
@@ -1,12 +1,33 @@
+// The rustc-cfg listed below are considered public API, but it is *unstable*
+// and outside of the normal semver guarantees:
+//
+// - `crossbeam_no_atomic_cas`
+//      Assume the target does *not* support atomic CAS operations.
+//      This is usually detected automatically by the build script, but you may
+//      need to enable it manually when building for custom targets or using
+//      non-cargo build systems that don't run the build script.
+//
+// - `crossbeam_no_atomic`
+//      Assume the target does *not* support any atomic operations.
+//      This is usually detected automatically by the build script, but you may
+//      need to enable it manually when building for custom targets or using
+//      non-cargo build systems that don't run the build script.
+//
+// - `crossbeam_no_atomic_64`
+//      Assume the target does *not* support AtomicU64/AtomicI64.
+//      This is usually detected automatically by the build script, but you may
+//      need to enable it manually when building for custom targets or using
+//      non-cargo build systems that don't run the build script.
+//
+// With the exceptions mentioned above, the rustc-cfg emitted by the build
+// script are *not* public API.
+
 #![warn(rust_2018_idioms)]
 
 use std::env;
 
 include!("no_atomic.rs");
 
-// The rustc-cfg strings below are *not* public API. Please let us know by
-// opening a GitHub issue if your build environment requires some way to enable
-// these cfgs other than by executing our build script.
 fn main() {
     let target = match env::var("TARGET") {
         Ok(target) => target,
@@ -33,7 +54,7 @@
     } else if NO_ATOMIC_64.contains(&&*target) {
         println!("cargo:rustc-cfg=crossbeam_no_atomic_64");
     } else {
-        // Otherwise, assuming `"max-atomic-width" == 64`.
+        // Otherwise, assuming `"max-atomic-width" == 64` or `"max-atomic-width" == 128`.
     }
 
     println!("cargo:rerun-if-changed=no_atomic.rs");
diff --git a/no_atomic.rs b/no_atomic.rs
index 522b3b8..90ac60a 100644
--- a/no_atomic.rs
+++ b/no_atomic.rs
@@ -3,13 +3,16 @@
 
 const NO_ATOMIC_CAS: &[&str] = &[
     "avr-unknown-gnu-atmega328",
+    "bpfeb-unknown-none",
+    "bpfel-unknown-none",
     "msp430-none-elf",
     "riscv32i-unknown-none-elf",
     "riscv32imc-unknown-none-elf",
     "thumbv4t-none-eabi",
     "thumbv6m-none-eabi",
 ];
-#[allow(dead_code)]
+
+#[allow(dead_code)] // Only crossbeam-utils uses this.
 const NO_ATOMIC_64: &[&str] = &[
     "arm-linux-androideabi",
     "armebv7r-none-eabi",
@@ -18,18 +21,24 @@
     "armv5te-unknown-linux-gnueabi",
     "armv5te-unknown-linux-musleabi",
     "armv5te-unknown-linux-uclibceabi",
+    "armv6k-nintendo-3ds",
     "armv7r-none-eabi",
     "armv7r-none-eabihf",
+    "avr-unknown-gnu-atmega328",
     "hexagon-unknown-linux-musl",
+    "m68k-unknown-linux-gnu",
     "mips-unknown-linux-gnu",
     "mips-unknown-linux-musl",
     "mips-unknown-linux-uclibc",
+    "mipsel-sony-psp",
     "mipsel-unknown-linux-gnu",
     "mipsel-unknown-linux-musl",
     "mipsel-unknown-linux-uclibc",
     "mipsel-unknown-none",
     "mipsisa32r6-unknown-linux-gnu",
     "mipsisa32r6el-unknown-linux-gnu",
+    "msp430-none-elf",
+    "powerpc-unknown-freebsd",
     "powerpc-unknown-linux-gnu",
     "powerpc-unknown-linux-gnuspe",
     "powerpc-unknown-linux-musl",
@@ -39,18 +48,21 @@
     "powerpc-wrs-vxworks-spe",
     "riscv32gc-unknown-linux-gnu",
     "riscv32gc-unknown-linux-musl",
+    "riscv32i-unknown-none-elf",
     "riscv32imac-unknown-none-elf",
+    "riscv32imc-esp-espidf",
+    "riscv32imc-unknown-none-elf",
+    "thumbv4t-none-eabi",
+    "thumbv6m-none-eabi",
     "thumbv7em-none-eabi",
     "thumbv7em-none-eabihf",
     "thumbv7m-none-eabi",
     "thumbv8m.base-none-eabi",
     "thumbv8m.main-none-eabi",
     "thumbv8m.main-none-eabihf",
-    "mipsel-sony-psp",
-    "thumbv4t-none-eabi",
-    "thumbv6m-none-eabi",
 ];
-#[allow(dead_code)]
+
+#[allow(dead_code)] // Only crossbeam-utils uses this.
 const NO_ATOMIC: &[&str] = &[
     "avr-unknown-gnu-atmega328",
     "msp430-none-elf",
diff --git a/src/atomic/atomic_cell.rs b/src/atomic/atomic_cell.rs
index 1a1c464..8a49464 100644
--- a/src/atomic/atomic_cell.rs
+++ b/src/atomic/atomic_cell.rs
@@ -1,9 +1,9 @@
 // Necessary for implementing atomic methods for `AtomicUnit`
 #![allow(clippy::unit_arg)]
-#![allow(clippy::let_unit_value)]
 
 use crate::primitive::sync::atomic::{self, AtomicBool};
 use core::cell::UnsafeCell;
+use core::cmp;
 use core::fmt;
 use core::mem;
 use core::sync::atomic::Ordering;
@@ -295,7 +295,7 @@
 }
 
 macro_rules! impl_arithmetic {
-    ($t:ty, $example:tt) => {
+    ($t:ty, fallback, $example:tt) => {
         impl AtomicCell<$t> {
             /// Increments the current value by `val` and returns the previous value.
             ///
@@ -313,10 +313,13 @@
             /// ```
             #[inline]
             pub fn fetch_add(&self, val: $t) -> $t {
-                if can_transmute::<$t, atomic::AtomicUsize>() {
-                    let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
-                    a.fetch_add(val as usize, Ordering::AcqRel) as $t
-                } else {
+                #[cfg(crossbeam_loom)]
+                {
+                    let _ = val;
+                    unimplemented!("loom does not support non-atomic atomic ops");
+                }
+                #[cfg(not(crossbeam_loom))]
+                {
                     let _guard = lock(self.value.get() as usize).write();
                     let value = unsafe { &mut *(self.value.get()) };
                     let old = *value;
@@ -341,10 +344,13 @@
             /// ```
             #[inline]
             pub fn fetch_sub(&self, val: $t) -> $t {
-                if can_transmute::<$t, atomic::AtomicUsize>() {
-                    let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
-                    a.fetch_sub(val as usize, Ordering::AcqRel) as $t
-                } else {
+                #[cfg(crossbeam_loom)]
+                {
+                    let _ = val;
+                    unimplemented!("loom does not support non-atomic atomic ops");
+                }
+                #[cfg(not(crossbeam_loom))]
+                {
                     let _guard = lock(self.value.get() as usize).write();
                     let value = unsafe { &mut *(self.value.get()) };
                     let old = *value;
@@ -367,10 +373,13 @@
             /// ```
             #[inline]
             pub fn fetch_and(&self, val: $t) -> $t {
-                if can_transmute::<$t, atomic::AtomicUsize>() {
-                    let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
-                    a.fetch_and(val as usize, Ordering::AcqRel) as $t
-                } else {
+                #[cfg(crossbeam_loom)]
+                {
+                    let _ = val;
+                    unimplemented!("loom does not support non-atomic atomic ops");
+                }
+                #[cfg(not(crossbeam_loom))]
+                {
                     let _guard = lock(self.value.get() as usize).write();
                     let value = unsafe { &mut *(self.value.get()) };
                     let old = *value;
@@ -379,6 +388,35 @@
                 }
             }
 
+            /// Applies bitwise "nand" to the current value and returns the previous value.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use crossbeam_utils::atomic::AtomicCell;
+            ///
+            #[doc = $example]
+            ///
+            /// assert_eq!(a.fetch_nand(3), 7);
+            /// assert_eq!(a.load(), !(7 & 3));
+            /// ```
+            #[inline]
+            pub fn fetch_nand(&self, val: $t) -> $t {
+                #[cfg(crossbeam_loom)]
+                {
+                    let _ = val;
+                    unimplemented!("loom does not support non-atomic atomic ops");
+                }
+                #[cfg(not(crossbeam_loom))]
+                {
+                    let _guard = lock(self.value.get() as usize).write();
+                    let value = unsafe { &mut *(self.value.get()) };
+                    let old = *value;
+                    *value = !(old & val);
+                    old
+                }
+            }
+
             /// Applies bitwise "or" to the current value and returns the previous value.
             ///
             /// # Examples
@@ -393,10 +431,13 @@
             /// ```
             #[inline]
             pub fn fetch_or(&self, val: $t) -> $t {
-                if can_transmute::<$t, atomic::AtomicUsize>() {
-                    let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
-                    a.fetch_or(val as usize, Ordering::AcqRel) as $t
-                } else {
+                #[cfg(crossbeam_loom)]
+                {
+                    let _ = val;
+                    unimplemented!("loom does not support non-atomic atomic ops");
+                }
+                #[cfg(not(crossbeam_loom))]
+                {
                     let _guard = lock(self.value.get() as usize).write();
                     let value = unsafe { &mut *(self.value.get()) };
                     let old = *value;
@@ -419,10 +460,13 @@
             /// ```
             #[inline]
             pub fn fetch_xor(&self, val: $t) -> $t {
-                if can_transmute::<$t, atomic::AtomicUsize>() {
-                    let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
-                    a.fetch_xor(val as usize, Ordering::AcqRel) as $t
-                } else {
+                #[cfg(crossbeam_loom)]
+                {
+                    let _ = val;
+                    unimplemented!("loom does not support non-atomic atomic ops");
+                }
+                #[cfg(not(crossbeam_loom))]
+                {
                     let _guard = lock(self.value.get() as usize).write();
                     let value = unsafe { &mut *(self.value.get()) };
                     let old = *value;
@@ -430,6 +474,66 @@
                     old
                 }
             }
+
+            /// Compares and sets the maximum of the current value and `val`,
+            /// and returns the previous value.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use crossbeam_utils::atomic::AtomicCell;
+            ///
+            #[doc = $example]
+            ///
+            /// assert_eq!(a.fetch_max(2), 7);
+            /// assert_eq!(a.load(), 7);
+            /// ```
+            #[inline]
+            pub fn fetch_max(&self, val: $t) -> $t {
+                #[cfg(crossbeam_loom)]
+                {
+                    let _ = val;
+                    unimplemented!("loom does not support non-atomic atomic ops");
+                }
+                #[cfg(not(crossbeam_loom))]
+                {
+                    let _guard = lock(self.value.get() as usize).write();
+                    let value = unsafe { &mut *(self.value.get()) };
+                    let old = *value;
+                    *value = cmp::max(old, val);
+                    old
+                }
+            }
+
+            /// Compares and sets the minimum of the current value and `val`,
+            /// and returns the previous value.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use crossbeam_utils::atomic::AtomicCell;
+            ///
+            #[doc = $example]
+            ///
+            /// assert_eq!(a.fetch_min(2), 7);
+            /// assert_eq!(a.load(), 2);
+            /// ```
+            #[inline]
+            pub fn fetch_min(&self, val: $t) -> $t {
+                #[cfg(crossbeam_loom)]
+                {
+                    let _ = val;
+                    unimplemented!("loom does not support non-atomic atomic ops");
+                }
+                #[cfg(not(crossbeam_loom))]
+                {
+                    let _guard = lock(self.value.get() as usize).write();
+                    let value = unsafe { &mut *(self.value.get()) };
+                    let old = *value;
+                    *value = cmp::min(old, val);
+                    old
+                }
+            }
         }
     };
     ($t:ty, $atomic:ty, $example:tt) => {
@@ -450,8 +554,24 @@
             /// ```
             #[inline]
             pub fn fetch_add(&self, val: $t) -> $t {
-                let a = unsafe { &*(self.value.get() as *const $atomic) };
-                a.fetch_add(val, Ordering::AcqRel)
+                if can_transmute::<$t, $atomic>() {
+                    let a = unsafe { &*(self.value.get() as *const $atomic) };
+                    a.fetch_add(val, Ordering::AcqRel)
+                } else {
+                    #[cfg(crossbeam_loom)]
+                    {
+                        let _ = val;
+                        unimplemented!("loom does not support non-atomic atomic ops");
+                    }
+                    #[cfg(not(crossbeam_loom))]
+                    {
+                        let _guard = lock(self.value.get() as usize).write();
+                        let value = unsafe { &mut *(self.value.get()) };
+                        let old = *value;
+                        *value = value.wrapping_add(val);
+                        old
+                    }
+                }
             }
 
             /// Decrements the current value by `val` and returns the previous value.
@@ -470,8 +590,24 @@
             /// ```
             #[inline]
             pub fn fetch_sub(&self, val: $t) -> $t {
-                let a = unsafe { &*(self.value.get() as *const $atomic) };
-                a.fetch_sub(val, Ordering::AcqRel)
+                if can_transmute::<$t, $atomic>() {
+                    let a = unsafe { &*(self.value.get() as *const $atomic) };
+                    a.fetch_sub(val, Ordering::AcqRel)
+                } else {
+                    #[cfg(crossbeam_loom)]
+                    {
+                        let _ = val;
+                        unimplemented!("loom does not support non-atomic atomic ops");
+                    }
+                    #[cfg(not(crossbeam_loom))]
+                    {
+                        let _guard = lock(self.value.get() as usize).write();
+                        let value = unsafe { &mut *(self.value.get()) };
+                        let old = *value;
+                        *value = value.wrapping_sub(val);
+                        old
+                    }
+                }
             }
 
             /// Applies bitwise "and" to the current value and returns the previous value.
@@ -488,8 +624,58 @@
             /// ```
             #[inline]
             pub fn fetch_and(&self, val: $t) -> $t {
-                let a = unsafe { &*(self.value.get() as *const $atomic) };
-                a.fetch_and(val, Ordering::AcqRel)
+                if can_transmute::<$t, $atomic>() {
+                    let a = unsafe { &*(self.value.get() as *const $atomic) };
+                    a.fetch_and(val, Ordering::AcqRel)
+                } else {
+                    #[cfg(crossbeam_loom)]
+                    {
+                        let _ = val;
+                        unimplemented!("loom does not support non-atomic atomic ops");
+                    }
+                    #[cfg(not(crossbeam_loom))]
+                    {
+                        let _guard = lock(self.value.get() as usize).write();
+                        let value = unsafe { &mut *(self.value.get()) };
+                        let old = *value;
+                        *value &= val;
+                        old
+                    }
+                }
+            }
+
+            /// Applies bitwise "nand" to the current value and returns the previous value.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use crossbeam_utils::atomic::AtomicCell;
+            ///
+            #[doc = $example]
+            ///
+            /// assert_eq!(a.fetch_nand(3), 7);
+            /// assert_eq!(a.load(), !(7 & 3));
+            /// ```
+            #[inline]
+            pub fn fetch_nand(&self, val: $t) -> $t {
+                if can_transmute::<$t, $atomic>() {
+                    let a = unsafe { &*(self.value.get() as *const $atomic) };
+                    a.fetch_nand(val, Ordering::AcqRel)
+                } else {
+                    #[cfg(crossbeam_loom)]
+                    {
+                        let _ = val;
+                        unimplemented!("loom does not support non-atomic atomic ops");
+                    }
+                    #[cfg(not(crossbeam_loom))]
+                    {
+                        let _guard = lock(self.value.get() as usize).write();
+                        let value = unsafe { &mut *(self.value.get()) };
+                        let old = *value;
+                        *value = !(old & val);
+                        old
+                    }
+                }
             }
 
             /// Applies bitwise "or" to the current value and returns the previous value.
@@ -506,8 +692,24 @@
             /// ```
             #[inline]
             pub fn fetch_or(&self, val: $t) -> $t {
-                let a = unsafe { &*(self.value.get() as *const $atomic) };
-                a.fetch_or(val, Ordering::AcqRel)
+                if can_transmute::<$t, $atomic>() {
+                    let a = unsafe { &*(self.value.get() as *const $atomic) };
+                    a.fetch_or(val, Ordering::AcqRel)
+                } else {
+                    #[cfg(crossbeam_loom)]
+                    {
+                        let _ = val;
+                        unimplemented!("loom does not support non-atomic atomic ops");
+                    }
+                    #[cfg(not(crossbeam_loom))]
+                    {
+                        let _guard = lock(self.value.get() as usize).write();
+                        let value = unsafe { &mut *(self.value.get()) };
+                        let old = *value;
+                        *value |= val;
+                        old
+                    }
+                }
             }
 
             /// Applies bitwise "xor" to the current value and returns the previous value.
@@ -524,8 +726,94 @@
             /// ```
             #[inline]
             pub fn fetch_xor(&self, val: $t) -> $t {
-                let a = unsafe { &*(self.value.get() as *const $atomic) };
-                a.fetch_xor(val, Ordering::AcqRel)
+                if can_transmute::<$t, $atomic>() {
+                    let a = unsafe { &*(self.value.get() as *const $atomic) };
+                    a.fetch_xor(val, Ordering::AcqRel)
+                } else {
+                    #[cfg(crossbeam_loom)]
+                    {
+                        let _ = val;
+                        unimplemented!("loom does not support non-atomic atomic ops");
+                    }
+                    #[cfg(not(crossbeam_loom))]
+                    {
+                        let _guard = lock(self.value.get() as usize).write();
+                        let value = unsafe { &mut *(self.value.get()) };
+                        let old = *value;
+                        *value ^= val;
+                        old
+                    }
+                }
+            }
+
+            /// Compares and sets the maximum of the current value and `val`,
+            /// and returns the previous value.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use crossbeam_utils::atomic::AtomicCell;
+            ///
+            #[doc = $example]
+            ///
+            /// assert_eq!(a.fetch_max(9), 7);
+            /// assert_eq!(a.load(), 9);
+            /// ```
+            #[inline]
+            pub fn fetch_max(&self, val: $t) -> $t {
+                if can_transmute::<$t, $atomic>() {
+                    // TODO: Atomic*::fetch_max requires Rust 1.45.
+                    self.fetch_update(|old| Some(cmp::max(old, val))).unwrap()
+                } else {
+                    #[cfg(crossbeam_loom)]
+                    {
+                        let _ = val;
+                        unimplemented!("loom does not support non-atomic atomic ops");
+                    }
+                    #[cfg(not(crossbeam_loom))]
+                    {
+                        let _guard = lock(self.value.get() as usize).write();
+                        let value = unsafe { &mut *(self.value.get()) };
+                        let old = *value;
+                        *value = cmp::max(old, val);
+                        old
+                    }
+                }
+            }
+
+            /// Compares and sets the minimum of the current value and `val`,
+            /// and returns the previous value.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// use crossbeam_utils::atomic::AtomicCell;
+            ///
+            #[doc = $example]
+            ///
+            /// assert_eq!(a.fetch_min(2), 7);
+            /// assert_eq!(a.load(), 2);
+            /// ```
+            #[inline]
+            pub fn fetch_min(&self, val: $t) -> $t {
+                if can_transmute::<$t, $atomic>() {
+                    // TODO: Atomic*::fetch_min requires Rust 1.45.
+                    self.fetch_update(|old| Some(cmp::min(old, val))).unwrap()
+                } else {
+                    #[cfg(crossbeam_loom)]
+                    {
+                        let _ = val;
+                        unimplemented!("loom does not support non-atomic atomic ops");
+                    }
+                    #[cfg(not(crossbeam_loom))]
+                    {
+                        let _guard = lock(self.value.get() as usize).write();
+                        let value = unsafe { &mut *(self.value.get()) };
+                        let old = *value;
+                        *value = cmp::min(old, val);
+                        old
+                    }
+                }
             }
         }
     };
@@ -541,9 +829,15 @@
 impl_arithmetic!(u64, atomic::AtomicU64, "let a = AtomicCell::new(7u64);");
 #[cfg(not(crossbeam_no_atomic_64))]
 impl_arithmetic!(i64, atomic::AtomicI64, "let a = AtomicCell::new(7i64);");
+#[cfg(crossbeam_no_atomic_64)]
+impl_arithmetic!(u64, fallback, "let a = AtomicCell::new(7u64);");
+#[cfg(crossbeam_no_atomic_64)]
+impl_arithmetic!(i64, fallback, "let a = AtomicCell::new(7i64);");
 // TODO: AtomicU128 is unstable
 // impl_arithmetic!(u128, atomic::AtomicU128, "let a = AtomicCell::new(7u128);");
 // impl_arithmetic!(i128, atomic::AtomicI128, "let a = AtomicCell::new(7i128);");
+impl_arithmetic!(u128, fallback, "let a = AtomicCell::new(7u128);");
+impl_arithmetic!(i128, fallback, "let a = AtomicCell::new(7i128);");
 
 impl_arithmetic!(
     usize,
@@ -578,6 +872,30 @@
         a.fetch_and(val, Ordering::AcqRel)
     }
 
+    /// Applies logical "nand" to the current value and returns the previous value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_utils::atomic::AtomicCell;
+    ///
+    /// let a = AtomicCell::new(true);
+    ///
+    /// assert_eq!(a.fetch_nand(false), true);
+    /// assert_eq!(a.load(), true);
+    ///
+    /// assert_eq!(a.fetch_nand(true), true);
+    /// assert_eq!(a.load(), false);
+    ///
+    /// assert_eq!(a.fetch_nand(false), false);
+    /// assert_eq!(a.load(), true);
+    /// ```
+    #[inline]
+    pub fn fetch_nand(&self, val: bool) -> bool {
+        let a = unsafe { &*(self.value.get() as *const AtomicBool) };
+        a.fetch_nand(val, Ordering::AcqRel)
+    }
+
     /// Applies logical "or" to the current value and returns the previous value.
     ///
     /// # Examples
@@ -683,105 +1001,13 @@
     // stored at addresses that are multiples of 3. It'd be too bad if `LEN` was divisible by 3.
     // In order to protect from such cases, we simply choose a large prime number for `LEN`.
     const LEN: usize = 97;
-
+    #[allow(clippy::declare_interior_mutable_const)]
+    const L: SeqLock = SeqLock::new();
     static LOCKS: [SeqLock; LEN] = [
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
-        SeqLock::new(),
+        L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L,
+        L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L,
+        L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L,
+        L, L, L, L, L, L, L,
     ];
 
     // If the modulus is a constant number, the compiler will use crazy math to transform this into
@@ -804,7 +1030,6 @@
     #[inline]
     fn swap(&self, _val: (), _order: Ordering) {}
 
-    #[allow(clippy::unnecessary_wraps)] // This is intentional.
     #[inline]
     fn compare_exchange_weak(
         &self,
@@ -833,7 +1058,6 @@
     ($t:ty, $a:ident, $atomic_op:expr, $fallback_op:expr) => {
         loop {
             atomic!(@check, $t, AtomicUnit, $a, $atomic_op);
-            atomic!(@check, $t, atomic::AtomicUsize, $a, $atomic_op);
 
             atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op);
             atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op);
@@ -855,7 +1079,6 @@
 const fn atomic_is_lock_free<T>() -> bool {
     // HACK(taiki-e): This is equivalent to `atomic! { T, _a, true, false }`, but can be used in const fn even in Rust 1.36.
     let is_lock_free = can_transmute::<T, AtomicUnit>()
-        | can_transmute::<T, atomic::AtomicUsize>()
         | can_transmute::<T, atomic::AtomicU8>()
         | can_transmute::<T, atomic::AtomicU16>()
         | can_transmute::<T, atomic::AtomicU32>();
diff --git a/src/sync/parker.rs b/src/sync/parker.rs
index aefa515..531f5a5 100644
--- a/src/sync/parker.rs
+++ b/src/sync/parker.rs
@@ -175,6 +175,7 @@
     ///
     /// let p = Parker::new();
     /// let raw = Parker::into_raw(p);
+    /// # let _ = unsafe { Parker::from_raw(raw) };
     /// ```
     pub fn into_raw(this: Parker) -> *const () {
         Unparker::into_raw(this.unparker)
@@ -258,6 +259,7 @@
     /// let p = Parker::new();
     /// let u = p.unparker().clone();
     /// let raw = Unparker::into_raw(u);
+    /// # let _ = unsafe { Unparker::from_raw(raw) };
     /// ```
     pub fn into_raw(this: Unparker) -> *const () {
         Arc::into_raw(this.inner) as *const ()
diff --git a/src/thread.rs b/src/thread.rs
index c57d076..a59a4f5 100644
--- a/src/thread.rs
+++ b/src/thread.rs
@@ -446,7 +446,7 @@
                     unsafe { mem::transmute(closure) };
 
                 // Finally, spawn the closure.
-                self.builder.spawn(move || closure())?
+                self.builder.spawn(closure)?
             };
 
             let thread = handle.thread().clone();
diff --git a/tests/atomic_cell.rs b/tests/atomic_cell.rs
index 28208ee..da7a6e1 100644
--- a/tests/atomic_cell.rs
+++ b/tests/atomic_cell.rs
@@ -264,3 +264,69 @@
     CELL.store(1);
     assert_eq!(CELL.load(), 1);
 }
+
+// https://github.com/crossbeam-rs/crossbeam/pull/767
+macro_rules! test_arithmetic {
+    ($test_name:ident, $ty:ident) => {
+        #[test]
+        fn $test_name() {
+            let a: AtomicCell<$ty> = AtomicCell::new(7);
+
+            assert_eq!(a.fetch_add(3), 7);
+            assert_eq!(a.load(), 10);
+
+            assert_eq!(a.fetch_sub(3), 10);
+            assert_eq!(a.load(), 7);
+
+            assert_eq!(a.fetch_and(3), 7);
+            assert_eq!(a.load(), 3);
+
+            assert_eq!(a.fetch_or(16), 3);
+            assert_eq!(a.load(), 19);
+
+            assert_eq!(a.fetch_xor(2), 19);
+            assert_eq!(a.load(), 17);
+
+            assert_eq!(a.fetch_max(18), 17);
+            assert_eq!(a.load(), 18);
+
+            assert_eq!(a.fetch_min(17), 18);
+            assert_eq!(a.load(), 17);
+
+            assert_eq!(a.fetch_nand(7), 17);
+            assert_eq!(a.load(), !(17 & 7));
+        }
+    };
+}
+test_arithmetic!(arithmetic_u8, u8);
+test_arithmetic!(arithmetic_i8, i8);
+test_arithmetic!(arithmetic_u16, u16);
+test_arithmetic!(arithmetic_i16, i16);
+test_arithmetic!(arithmetic_u32, u32);
+test_arithmetic!(arithmetic_i32, i32);
+test_arithmetic!(arithmetic_u64, u64);
+test_arithmetic!(arithmetic_i64, i64);
+test_arithmetic!(arithmetic_u128, u128);
+test_arithmetic!(arithmetic_i128, i128);
+
+// https://github.com/crossbeam-rs/crossbeam/issues/748
+#[cfg_attr(miri, ignore)] // TODO
+#[rustversion::since(1.37)] // #[repr(align(N))] requires Rust 1.37
+#[test]
+fn issue_748() {
+    #[allow(dead_code)]
+    #[repr(align(8))]
+    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
+    enum Test {
+        Field(u32),
+        FieldLess,
+    }
+
+    assert_eq!(mem::size_of::<Test>(), 8);
+    assert_eq!(
+        AtomicCell::<Test>::is_lock_free(),
+        cfg!(not(crossbeam_no_atomic_64))
+    );
+    let x = AtomicCell::new(Test::FieldLess);
+    assert_eq!(x.load(), Test::FieldLess);
+}
diff --git a/tests/sharded_lock.rs b/tests/sharded_lock.rs
index d999008..0718b44 100644
--- a/tests/sharded_lock.rs
+++ b/tests/sharded_lock.rs
@@ -21,6 +21,9 @@
 #[test]
 fn frob() {
     const N: u32 = 10;
+    #[cfg(miri)]
+    const M: usize = 100;
+    #[cfg(not(miri))]
     const M: usize = 1000;
 
     let r = Arc::new(ShardedLock::new(()));