Snap for 8564071 from cff857dd15d4e02379b3dba00804c84bf8c4049f to mainline-wifi-release

Change-Id: I50f9de03a56e9b2d0b180fbabbeb195be42adaf3
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 1d9c34d..0d40a83 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "d841a2028dc72b4e09739116f07e865db60f3690"
-  }
-}
+    "sha1": "2988f873f87d2263a7fd2b9465fb9c28f43a6490"
+  },
+  "path_in_vcs": "crossbeam-utils"
+}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 1a2c24f..5f17007 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,4 @@
-// This file is generated by cargo2android.py --run --device --dependencies --tests.
+// This file is generated by cargo2android.py --config cargo2android.json.
 // Do not modify this file as changes will be overridden on upgrade.
 
 package {
@@ -39,47 +39,37 @@
     ],
 }
 
-rust_defaults {
-    name: "crossbeam-utils_defaults",
+rust_test {
+    name: "crossbeam-utils_test_src_lib",
+    host_supported: true,
     crate_name: "crossbeam_utils",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.8.7",
     srcs: ["src/lib.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
+    test_options: {
+        unit_test: true,
+    },
     edition: "2018",
     features: [
         "default",
         "lazy_static",
         "std",
     ],
-    cfgs: [
-        "has_atomic_u16",
-        "has_atomic_u32",
-        "has_atomic_u64",
-        "has_atomic_u8",
-    ],
     rustlibs: [
         "libcfg_if",
         "liblazy_static",
         "librand",
     ],
-}
-
-rust_test_host {
-    name: "crossbeam-utils_host_test_src_lib",
-    defaults: ["crossbeam-utils_defaults"],
-    test_options: {
-        unit_test: true,
-    },
-}
-
-rust_test {
-    name: "crossbeam-utils_device_test_src_lib",
-    defaults: ["crossbeam-utils_defaults"],
+    proc_macros: ["librustversion"],
 }
 
 rust_defaults {
-    name: "crossbeam-utils_defaults_crossbeam_utils",
+    name: "crossbeam-utils_test_defaults",
     crate_name: "crossbeam_utils",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.8.7",
     test_suites: ["general-tests"],
     auto_gen_config: true,
     edition: "2018",
@@ -88,23 +78,19 @@
         "lazy_static",
         "std",
     ],
-    cfgs: [
-        "has_atomic_u16",
-        "has_atomic_u32",
-        "has_atomic_u64",
-        "has_atomic_u8",
-    ],
     rustlibs: [
         "libcfg_if",
         "libcrossbeam_utils",
         "liblazy_static",
         "librand",
     ],
+    proc_macros: ["librustversion"],
 }
 
-rust_test_host {
-    name: "crossbeam-utils_host_test_tests_atomic_cell",
-    defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
+rust_test {
+    name: "crossbeam-utils_test_tests_atomic_cell",
+    defaults: ["crossbeam-utils_test_defaults"],
+    host_supported: true,
     srcs: ["tests/atomic_cell.rs"],
     test_options: {
         unit_test: true,
@@ -112,14 +98,9 @@
 }
 
 rust_test {
-    name: "crossbeam-utils_device_test_tests_atomic_cell",
-    defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
-    srcs: ["tests/atomic_cell.rs"],
-}
-
-rust_test_host {
-    name: "crossbeam-utils_host_test_tests_cache_padded",
-    defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
+    name: "crossbeam-utils_test_tests_cache_padded",
+    defaults: ["crossbeam-utils_test_defaults"],
+    host_supported: true,
     srcs: ["tests/cache_padded.rs"],
     test_options: {
         unit_test: true,
@@ -127,14 +108,9 @@
 }
 
 rust_test {
-    name: "crossbeam-utils_device_test_tests_cache_padded",
-    defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
-    srcs: ["tests/cache_padded.rs"],
-}
-
-rust_test_host {
-    name: "crossbeam-utils_host_test_tests_parker",
-    defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
+    name: "crossbeam-utils_test_tests_parker",
+    defaults: ["crossbeam-utils_test_defaults"],
+    host_supported: true,
     srcs: ["tests/parker.rs"],
     test_options: {
         unit_test: true,
@@ -142,14 +118,9 @@
 }
 
 rust_test {
-    name: "crossbeam-utils_device_test_tests_parker",
-    defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
-    srcs: ["tests/parker.rs"],
-}
-
-rust_test_host {
-    name: "crossbeam-utils_host_test_tests_sharded_lock",
-    defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
+    name: "crossbeam-utils_test_tests_sharded_lock",
+    defaults: ["crossbeam-utils_test_defaults"],
+    host_supported: true,
     srcs: ["tests/sharded_lock.rs"],
     test_options: {
         unit_test: true,
@@ -157,14 +128,9 @@
 }
 
 rust_test {
-    name: "crossbeam-utils_device_test_tests_sharded_lock",
-    defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
-    srcs: ["tests/sharded_lock.rs"],
-}
-
-rust_test_host {
-    name: "crossbeam-utils_host_test_tests_thread",
-    defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
+    name: "crossbeam-utils_test_tests_thread",
+    defaults: ["crossbeam-utils_test_defaults"],
+    host_supported: true,
     srcs: ["tests/thread.rs"],
     test_options: {
         unit_test: true,
@@ -172,30 +138,21 @@
 }
 
 rust_test {
-    name: "crossbeam-utils_device_test_tests_thread",
-    defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
-    srcs: ["tests/thread.rs"],
-}
-
-rust_test_host {
-    name: "crossbeam-utils_host_test_tests_wait_group",
-    defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
+    name: "crossbeam-utils_test_tests_wait_group",
+    defaults: ["crossbeam-utils_test_defaults"],
+    host_supported: true,
     srcs: ["tests/wait_group.rs"],
     test_options: {
         unit_test: true,
     },
 }
 
-rust_test {
-    name: "crossbeam-utils_device_test_tests_wait_group",
-    defaults: ["crossbeam-utils_defaults_crossbeam_utils"],
-    srcs: ["tests/wait_group.rs"],
-}
-
 rust_library {
     name: "libcrossbeam_utils",
     host_supported: true,
     crate_name: "crossbeam_utils",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.8.7",
     srcs: ["src/lib.rs"],
     edition: "2018",
     features: [
@@ -203,25 +160,12 @@
         "lazy_static",
         "std",
     ],
-    cfgs: [
-        "has_atomic_u16",
-        "has_atomic_u32",
-        "has_atomic_u64",
-        "has_atomic_u8",
-    ],
     rustlibs: [
         "libcfg_if",
         "liblazy_static",
     ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.virt",
+    ],
 }
-
-// dependent_library ["feature_list"]
-//   autocfg-1.0.1
-//   cfg-if-1.0.0
-//   getrandom-0.2.2 "std"
-//   lazy_static-1.4.0
-//   libc-0.2.93
-//   ppv-lite86-0.2.10 "simd,std"
-//   rand-0.8.3 "alloc,default,getrandom,libc,rand_chacha,rand_hc,std,std_rng"
-//   rand_chacha-0.3.0 "std"
-//   rand_core-0.6.2 "alloc,getrandom,std"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c4a92bf..98088c5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,23 @@
+# 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)
+
+# Version 0.8.4
+
+- Bump `loom` dependency to version 0.5. (#686)
+
 # Version 0.8.3
 
 - Make `loom` dependency optional. (#666)
diff --git a/Cargo.toml b/Cargo.toml
index a7d694c..10d3240 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,40 +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.3"
-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"
-[build-dependencies.autocfg]
-version = "1.0.0"
+
+[dev-dependencies.rustversion]
+version = "1"
 
 [features]
 default = ["std"]
 nightly = []
 std = ["lazy_static"]
+
 [target."cfg(crossbeam_loom)".dependencies.loom]
-version = "0.4"
+version = "0.5"
 optional = true
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 30697d2..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.3"
-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"]
@@ -22,10 +21,13 @@
 # This is enabled by default.
 std = ["lazy_static"]
 
+# These features are no longer used.
+# TODO: remove in the next major version.
 # Enable to use of unstable functionality.
 # This is disabled by default and requires recent nightly compiler.
-# Note that this is outside of the normal semver guarantees and minor versions
-# of crossbeam may make breaking changes to them at any time.
+#
+# NOTE: This feature is outside of the normal semver guarantees and minor or
+# patch versions of crossbeam may make breaking changes to them at any time.
 nightly = []
 
 [dependencies]
@@ -34,13 +36,11 @@
 
 # Enable the use of loom for concurrency testing.
 #
-# This configuration option is outside of the normal semver guarantees: minor
-# versions of crossbeam may make breaking changes to it at any time.
+# NOTE: This feature is outside of the normal semver guarantees and minor or
+# patch versions of crossbeam may make breaking changes to them at any time.
 [target.'cfg(crossbeam_loom)'.dependencies]
-loom = { version = "0.4", optional = true }
-
-[build-dependencies]
-autocfg = "1.0.0"
+loom = { version = "0.5", optional = true }
 
 [dev-dependencies]
 rand = "0.8"
+rustversion = "1"
diff --git a/METADATA b/METADATA
index e66f8d0..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.3.crate"
+    value: "https://static.crates.io/crates/crossbeam-utils/crossbeam-utils-0.8.7.crate"
   }
-  version: "0.8.3"
+  version: "0.8.7"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
-    month: 4
+    year: 2022
+    month: 3
     day: 1
   }
 }
diff --git a/README.md b/README.md
index fd0943b..6e9a8e4 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@
 https://docs.rs/crossbeam-utils)
 [![Rust 1.36+](https://img.shields.io/badge/rust-1.36+-lightgray.svg)](
 https://www.rust-lang.org)
-[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.gg/BBYwKq)
+[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ)
 
 This crate provides miscellaneous tools for concurrent programming:
 
diff --git a/TEST_MAPPING b/TEST_MAPPING
index a68b776..eb8da39 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,32 +1,78 @@
 // Generated by update_crate_tests.py for tests that depend on this crate.
 {
+  "imports": [
+    {
+      "path": "external/rust/crates/base64"
+    },
+    {
+      "path": "external/rust/crates/crossbeam-deque"
+    },
+    {
+      "path": "external/rust/crates/crossbeam-epoch"
+    },
+    {
+      "path": "external/rust/crates/crossbeam-queue"
+    },
+    {
+      "path": "external/rust/crates/once_cell"
+    },
+    {
+      "path": "external/rust/crates/tinytemplate"
+    },
+    {
+      "path": "external/rust/crates/tinyvec"
+    },
+    {
+      "path": "external/rust/crates/unicode-xid"
+    },
+    {
+      "path": "external/rust/crates/vulkano"
+    }
+  ],
   "presubmit": [
     {
-      "name": "crossbeam-epoch_device_test_src_lib"
+      "name": "crossbeam-utils_test_src_lib"
     },
     {
-      "name": "crossbeam-epoch_device_test_tests_loom"
+      "name": "crossbeam-utils_test_tests_atomic_cell"
     },
     {
-      "name": "crossbeam-utils_device_test_src_lib"
+      "name": "crossbeam-utils_test_tests_cache_padded"
     },
     {
-      "name": "crossbeam-utils_device_test_tests_atomic_cell"
+      "name": "crossbeam-utils_test_tests_parker"
     },
     {
-      "name": "crossbeam-utils_device_test_tests_cache_padded"
+      "name": "crossbeam-utils_test_tests_sharded_lock"
     },
     {
-      "name": "crossbeam-utils_device_test_tests_parker"
+      "name": "crossbeam-utils_test_tests_thread"
     },
     {
-      "name": "crossbeam-utils_device_test_tests_sharded_lock"
+      "name": "crossbeam-utils_test_tests_wait_group"
+    }
+  ],
+  "presubmit-rust": [
+    {
+      "name": "crossbeam-utils_test_src_lib"
     },
     {
-      "name": "crossbeam-utils_device_test_tests_thread"
+      "name": "crossbeam-utils_test_tests_atomic_cell"
     },
     {
-      "name": "crossbeam-utils_device_test_tests_wait_group"
+      "name": "crossbeam-utils_test_tests_cache_padded"
+    },
+    {
+      "name": "crossbeam-utils_test_tests_parker"
+    },
+    {
+      "name": "crossbeam-utils_test_tests_sharded_lock"
+    },
+    {
+      "name": "crossbeam-utils_test_tests_thread"
+    },
+    {
+      "name": "crossbeam-utils_test_tests_wait_group"
     }
   ]
 }
diff --git a/build.rs b/build.rs
index 3e51021..a7557fd 100644
--- a/build.rs
+++ b/build.rs
@@ -1,23 +1,61 @@
-use autocfg::AutoCfg;
+// 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.
 
-// 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.
+#![warn(rust_2018_idioms)]
+
+use std::env;
+
+include!("no_atomic.rs");
+
 fn main() {
-    let cfg = match AutoCfg::new() {
-        Ok(cfg) => cfg,
+    let target = match env::var("TARGET") {
+        Ok(target) => target,
         Err(e) => {
             println!(
-                "cargo:warning=crossbeam-utils: unable to determine rustc version: {}",
+                "cargo:warning={}: unable to get TARGET environment variable: {}",
+                env!("CARGO_PKG_NAME"),
                 e
             );
             return;
         }
     };
 
-    cfg.emit_type_cfg("core::sync::atomic::AtomicU8", "has_atomic_u8");
-    cfg.emit_type_cfg("core::sync::atomic::AtomicU16", "has_atomic_u16");
-    cfg.emit_type_cfg("core::sync::atomic::AtomicU32", "has_atomic_u32");
-    cfg.emit_type_cfg("core::sync::atomic::AtomicU64", "has_atomic_u64");
-    cfg.emit_type_cfg("core::sync::atomic::AtomicU128", "has_atomic_u128");
+    // Note that this is `no_*`, not `has_*`. This allows treating
+    // `cfg(target_has_atomic = "ptr")` as true when the build script doesn't
+    // run. This is needed for compatibility with non-cargo build systems that
+    // don't run the build script.
+    if NO_ATOMIC_CAS.contains(&&*target) {
+        println!("cargo:rustc-cfg=crossbeam_no_atomic_cas");
+    }
+    if NO_ATOMIC.contains(&&*target) {
+        println!("cargo:rustc-cfg=crossbeam_no_atomic");
+        println!("cargo:rustc-cfg=crossbeam_no_atomic_64");
+    } else if NO_ATOMIC_64.contains(&&*target) {
+        println!("cargo:rustc-cfg=crossbeam_no_atomic_64");
+    } else {
+        // Otherwise, assuming `"max-atomic-width" == 64` or `"max-atomic-width" == 128`.
+    }
+
+    println!("cargo:rerun-if-changed=no_atomic.rs");
 }
diff --git a/cargo2android.json b/cargo2android.json
new file mode 100644
index 0000000..6e516e0
--- /dev/null
+++ b/cargo2android.json
@@ -0,0 +1,9 @@
+{
+  "apex-available": [
+    "//apex_available:platform",
+    "com.android.virt"
+  ],
+  "device": true,
+  "run": true,
+  "tests": true
+}
\ No newline at end of file
diff --git a/no_atomic.rs b/no_atomic.rs
new file mode 100644
index 0000000..90ac60a
--- /dev/null
+++ b/no_atomic.rs
@@ -0,0 +1,71 @@
+// This file is @generated by no_atomic.sh.
+// It is not intended for manual editing.
+
+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)] // Only crossbeam-utils uses this.
+const NO_ATOMIC_64: &[&str] = &[
+    "arm-linux-androideabi",
+    "armebv7r-none-eabi",
+    "armebv7r-none-eabihf",
+    "armv4t-unknown-linux-gnueabi",
+    "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",
+    "powerpc-unknown-netbsd",
+    "powerpc-unknown-openbsd",
+    "powerpc-wrs-vxworks",
+    "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",
+];
+
+#[allow(dead_code)] // Only crossbeam-utils uses this.
+const NO_ATOMIC: &[&str] = &[
+    "avr-unknown-gnu-atmega328",
+    "msp430-none-elf",
+    "riscv32i-unknown-none-elf",
+    "riscv32imc-unknown-none-elf",
+];
diff --git a/patches/disable_panic_tests_on_android.patch b/patches/disable_panic_tests_on_android.patch
index 49e4758..3306735 100644
--- a/patches/disable_panic_tests_on_android.patch
+++ b/patches/disable_panic_tests_on_android.patch
@@ -1,5 +1,5 @@
---- tests/sharded_lock.rs
-+++ tests/sharded_lock.rs
+--- a/tests/sharded_lock.rs
++++ b/tests/sharded_lock.rs
 @@ -46,6 +46,8 @@ fn frob() {
  }
  
@@ -63,8 +63,8 @@
  fn test_get_mut_poison() {
      let m = Arc::new(ShardedLock::new(NonCopy(10)));
      let m2 = m.clone();
---- tests/thread.rs
-+++ tests/thread.rs
+--- a/tests/thread.rs
++++ b/tests/thread.rs
 @@ -9,6 +9,8 @@ const THREADS: usize = 10;
  const SMALL_STACK_SIZE: usize = 20;
  
diff --git a/src/atomic/atomic_cell.rs b/src/atomic/atomic_cell.rs
index ad094b2..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;
@@ -258,10 +258,44 @@
     pub fn compare_exchange(&self, current: T, new: T) -> Result<T, T> {
         unsafe { atomic_compare_exchange_weak(self.value.get(), current, new) }
     }
+
+    /// Fetches the value, and applies a function to it that returns an optional
+    /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
+    /// `Err(previous_value)`.
+    ///
+    /// Note: This may call the function multiple times if the value has been changed from other threads in
+    /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
+    /// only once to the stored value.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// use crossbeam_utils::atomic::AtomicCell;
+    ///
+    /// let a = AtomicCell::new(7);
+    /// assert_eq!(a.fetch_update(|_| None), Err(7));
+    /// assert_eq!(a.fetch_update(|a| Some(a + 1)), Ok(7));
+    /// assert_eq!(a.fetch_update(|a| Some(a + 1)), Ok(8));
+    /// assert_eq!(a.load(), 9);
+    /// ```
+    #[inline]
+    pub fn fetch_update<F>(&self, mut f: F) -> Result<T, T>
+    where
+        F: FnMut(T) -> Option<T>,
+    {
+        let mut prev = self.load();
+        while let Some(next) = f(prev) {
+            match self.compare_exchange(prev, next) {
+                x @ Ok(_) => return x,
+                Err(next_prev) => prev = next_prev,
+            }
+        }
+        Err(prev)
+    }
 }
 
 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.
             ///
@@ -279,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;
@@ -307,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;
@@ -333,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;
@@ -345,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
@@ -359,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;
@@ -385,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;
@@ -396,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) => {
@@ -416,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.
@@ -436,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.
@@ -454,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.
@@ -472,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.
@@ -490,40 +726,124 @@
             /// ```
             #[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
+                    }
+                }
             }
         }
     };
 }
 
-#[cfg(has_atomic_u8)]
 impl_arithmetic!(u8, atomic::AtomicU8, "let a = AtomicCell::new(7u8);");
-#[cfg(all(has_atomic_u8, not(crossbeam_loom)))]
 impl_arithmetic!(i8, atomic::AtomicI8, "let a = AtomicCell::new(7i8);");
-#[cfg(has_atomic_u16)]
 impl_arithmetic!(u16, atomic::AtomicU16, "let a = AtomicCell::new(7u16);");
-#[cfg(all(has_atomic_u16, not(crossbeam_loom)))]
 impl_arithmetic!(i16, atomic::AtomicI16, "let a = AtomicCell::new(7i16);");
-#[cfg(has_atomic_u32)]
 impl_arithmetic!(u32, atomic::AtomicU32, "let a = AtomicCell::new(7u32);");
-#[cfg(all(has_atomic_u32, not(crossbeam_loom)))]
 impl_arithmetic!(i32, atomic::AtomicI32, "let a = AtomicCell::new(7i32);");
-#[cfg(has_atomic_u64)]
+#[cfg(not(crossbeam_no_atomic_64))]
 impl_arithmetic!(u64, atomic::AtomicU64, "let a = AtomicCell::new(7u64);");
-#[cfg(all(has_atomic_u64, not(crossbeam_loom)))]
+#[cfg(not(crossbeam_no_atomic_64))]
 impl_arithmetic!(i64, atomic::AtomicI64, "let a = AtomicCell::new(7i64);");
-#[cfg(all(has_atomic_u128, not(crossbeam_loom)))]
-impl_arithmetic!(u128, atomic::AtomicU128, "let a = AtomicCell::new(7u128);");
-#[cfg(all(has_atomic_u128, not(crossbeam_loom)))]
-impl_arithmetic!(i128, atomic::AtomicI128, "let  a = AtomicCell::new(7i128);");
+#[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,
     atomic::AtomicUsize,
     "let a = AtomicCell::new(7usize);"
 );
-#[cfg(not(crossbeam_loom))]
 impl_arithmetic!(
     isize,
     atomic::AtomicIsize,
@@ -552,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
@@ -657,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
@@ -778,7 +1030,6 @@
     #[inline]
     fn swap(&self, _val: (), _order: Ordering) {}
 
-    #[allow(clippy::unnecessary_wraps)] // This is intentional.
     #[inline]
     fn compare_exchange_weak(
         &self,
@@ -807,18 +1058,14 @@
     ($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);
 
-            #[cfg(has_atomic_u8)]
             atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op);
-            #[cfg(has_atomic_u16)]
             atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op);
-            #[cfg(has_atomic_u32)]
             atomic!(@check, $t, atomic::AtomicU32, $a, $atomic_op);
-            #[cfg(has_atomic_u64)]
+            #[cfg(not(crossbeam_no_atomic_64))]
             atomic!(@check, $t, atomic::AtomicU64, $a, $atomic_op);
-            #[cfg(has_atomic_u128)]
-            atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op);
+            // TODO: AtomicU128 is unstable
+            // atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op);
 
             #[cfg(crossbeam_loom)]
             unimplemented!("loom does not support non-atomic atomic ops");
@@ -831,17 +1078,14 @@
 /// Returns `true` if operations on `AtomicCell<T>` are lock-free.
 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>();
-    #[cfg(has_atomic_u8)]
-    let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU8>();
-    #[cfg(has_atomic_u16)]
-    let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU16>();
-    #[cfg(has_atomic_u32)]
-    let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU32>();
-    #[cfg(has_atomic_u64)]
+    let is_lock_free = can_transmute::<T, AtomicUnit>()
+        | can_transmute::<T, atomic::AtomicU8>()
+        | can_transmute::<T, atomic::AtomicU16>()
+        | can_transmute::<T, atomic::AtomicU32>();
+    #[cfg(not(crossbeam_no_atomic_64))]
     let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU64>();
-    #[cfg(has_atomic_u128)]
-    let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU128>();
+    // TODO: AtomicU128 is unstable
+    // let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU128>();
     is_lock_free
 }
 
diff --git a/src/atomic/consume.rs b/src/atomic/consume.rs
index 0fbd93e..277b370 100644
--- a/src/atomic/consume.rs
+++ b/src/atomic/consume.rs
@@ -1,5 +1,6 @@
 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
 use crate::primitive::sync::atomic::compiler_fence;
+#[cfg(not(crossbeam_no_atomic))]
 use core::sync::atomic::Ordering;
 
 /// Trait which allows reading from primitive atomic types with "consume" ordering.
@@ -25,6 +26,7 @@
     fn load_consume(&self) -> Self::Val;
 }
 
+#[cfg(not(crossbeam_no_atomic))]
 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
 macro_rules! impl_consume {
     () => {
@@ -37,6 +39,7 @@
     };
 }
 
+#[cfg(not(crossbeam_no_atomic))]
 #[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
 macro_rules! impl_consume {
     () => {
@@ -49,12 +52,13 @@
 
 macro_rules! impl_atomic {
     ($atomic:ident, $val:ty) => {
-        impl AtomicConsume for ::core::sync::atomic::$atomic {
+        #[cfg(not(crossbeam_no_atomic))]
+        impl AtomicConsume for core::sync::atomic::$atomic {
             type Val = $val;
             impl_consume!();
         }
         #[cfg(crossbeam_loom)]
-        impl AtomicConsume for ::loom::sync::atomic::$atomic {
+        impl AtomicConsume for loom::sync::atomic::$atomic {
             type Val = $val;
             impl_consume!();
         }
@@ -63,32 +67,26 @@
 
 impl_atomic!(AtomicBool, bool);
 impl_atomic!(AtomicUsize, usize);
-#[cfg(not(crossbeam_loom))]
 impl_atomic!(AtomicIsize, isize);
-#[cfg(has_atomic_u8)]
 impl_atomic!(AtomicU8, u8);
-#[cfg(has_atomic_u8)]
 impl_atomic!(AtomicI8, i8);
-#[cfg(has_atomic_u16)]
 impl_atomic!(AtomicU16, u16);
-#[cfg(has_atomic_u16)]
 impl_atomic!(AtomicI16, i16);
-#[cfg(has_atomic_u32)]
 impl_atomic!(AtomicU32, u32);
-#[cfg(has_atomic_u32)]
 impl_atomic!(AtomicI32, i32);
-#[cfg(has_atomic_u64)]
+#[cfg(not(crossbeam_no_atomic_64))]
 impl_atomic!(AtomicU64, u64);
-#[cfg(has_atomic_u64)]
+#[cfg(not(crossbeam_no_atomic_64))]
 impl_atomic!(AtomicI64, i64);
 
-impl<T> AtomicConsume for ::core::sync::atomic::AtomicPtr<T> {
+#[cfg(not(crossbeam_no_atomic))]
+impl<T> AtomicConsume for core::sync::atomic::AtomicPtr<T> {
     type Val = *mut T;
     impl_consume!();
 }
 
 #[cfg(crossbeam_loom)]
-impl<T> AtomicConsume for ::loom::sync::atomic::AtomicPtr<T> {
+impl<T> AtomicConsume for loom::sync::atomic::AtomicPtr<T> {
     type Val = *mut T;
     impl_consume!();
 }
diff --git a/src/atomic/mod.rs b/src/atomic/mod.rs
index 874eaf2..fc713fc 100644
--- a/src/atomic/mod.rs
+++ b/src/atomic/mod.rs
@@ -3,11 +3,9 @@
 //! * [`AtomicCell`], a thread-safe mutable memory location.
 //! * [`AtomicConsume`], for reading from primitive atomic types with "consume" ordering.
 
+#[cfg(not(crossbeam_no_atomic_cas))]
 #[cfg(not(crossbeam_loom))]
-use cfg_if::cfg_if;
-
-#[cfg(not(crossbeam_loom))]
-cfg_if! {
+cfg_if::cfg_if! {
     // Use "wide" sequence lock if the pointer width <= 32 for preventing its counter against wrap
     // around.
     //
@@ -25,8 +23,10 @@
     }
 }
 
+#[cfg(not(crossbeam_no_atomic_cas))]
 mod atomic_cell;
 mod consume;
 
+#[cfg(not(crossbeam_no_atomic_cas))]
 pub use self::atomic_cell::AtomicCell;
 pub use self::consume::AtomicConsume;
diff --git a/src/lib.rs b/src/lib.rs
index 880d37e..191c5a1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -38,7 +38,6 @@
     unreachable_pub
 )]
 #![cfg_attr(not(feature = "std"), no_std)]
-#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]
 
 #[cfg(crossbeam_loom)]
 #[allow(unused_imports)]
@@ -47,7 +46,8 @@
         pub(crate) mod atomic {
             pub(crate) use loom::sync::atomic::spin_loop_hint;
             pub(crate) use loom::sync::atomic::{
-                AtomicBool, AtomicU16, AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
+                AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16,
+                AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
             };
 
             // FIXME: loom does not support compiler_fence at the moment.
@@ -70,15 +70,13 @@
             // use [`core::hint::spin_loop`] instead.
             #[allow(deprecated)]
             pub(crate) use core::sync::atomic::spin_loop_hint;
-            pub(crate) use core::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize};
-            #[cfg(has_atomic_u16)]
-            pub(crate) use core::sync::atomic::{AtomicI16, AtomicU16};
-            #[cfg(has_atomic_u32)]
-            pub(crate) use core::sync::atomic::{AtomicI32, AtomicU32};
-            #[cfg(has_atomic_u64)]
+            #[cfg(not(crossbeam_no_atomic))]
+            pub(crate) use core::sync::atomic::{
+                AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
+                AtomicU8, AtomicUsize,
+            };
+            #[cfg(not(crossbeam_no_atomic_64))]
             pub(crate) use core::sync::atomic::{AtomicI64, AtomicU64};
-            #[cfg(has_atomic_u8)]
-            pub(crate) use core::sync::atomic::{AtomicI8, AtomicU8};
         }
 
         #[cfg(feature = "std")]
@@ -86,15 +84,6 @@
     }
 }
 
-cfg_if! {
-    if #[cfg(feature = "alloc")] {
-        extern crate alloc;
-    } else if #[cfg(feature = "std")] {
-        extern crate std as alloc;
-    }
-}
-
-#[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))]
 pub mod atomic;
 
 mod cache_padded;
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 3d91d81..da7a6e1 100644
--- a/tests/atomic_cell.rs
+++ b/tests/atomic_cell.rs
@@ -1,3 +1,4 @@
+use std::mem;
 use std::sync::atomic::AtomicUsize;
 use std::sync::atomic::Ordering::SeqCst;
 
@@ -8,18 +9,47 @@
     struct UsizeWrap(usize);
     struct U8Wrap(bool);
     struct I16Wrap(i16);
+    #[repr(align(8))]
+    struct U64Align8(u64);
 
-    assert_eq!(AtomicCell::<usize>::is_lock_free(), true);
-    assert_eq!(AtomicCell::<isize>::is_lock_free(), true);
-    assert_eq!(AtomicCell::<UsizeWrap>::is_lock_free(), true);
+    assert!(AtomicCell::<usize>::is_lock_free());
+    assert!(AtomicCell::<isize>::is_lock_free());
+    assert!(AtomicCell::<UsizeWrap>::is_lock_free());
 
-    assert_eq!(AtomicCell::<u8>::is_lock_free(), cfg!(has_atomic_u8));
-    assert_eq!(AtomicCell::<bool>::is_lock_free(), cfg!(has_atomic_u8));
-    assert_eq!(AtomicCell::<U8Wrap>::is_lock_free(), cfg!(has_atomic_u8));
+    assert!(AtomicCell::<()>::is_lock_free());
 
-    assert_eq!(AtomicCell::<I16Wrap>::is_lock_free(), cfg!(has_atomic_u16));
+    assert!(AtomicCell::<u8>::is_lock_free());
+    assert!(AtomicCell::<i8>::is_lock_free());
+    assert!(AtomicCell::<bool>::is_lock_free());
+    assert!(AtomicCell::<U8Wrap>::is_lock_free());
 
-    assert_eq!(AtomicCell::<u128>::is_lock_free(), cfg!(has_atomic_u128));
+    assert!(AtomicCell::<u16>::is_lock_free());
+    assert!(AtomicCell::<i16>::is_lock_free());
+    assert!(AtomicCell::<I16Wrap>::is_lock_free());
+
+    assert!(AtomicCell::<u32>::is_lock_free());
+    assert!(AtomicCell::<i32>::is_lock_free());
+
+    // Sizes of both types must be equal, and the alignment of `u64` must be greater or equal than
+    // that of `AtomicU64`. In i686-unknown-linux-gnu, the alignment of `u64` is `4` and alignment
+    // of `AtomicU64` is `8`, so `AtomicCell<u64>` is not lock-free.
+    assert_eq!(
+        AtomicCell::<u64>::is_lock_free(),
+        cfg!(not(crossbeam_no_atomic_64))
+            && cfg!(any(
+                target_pointer_width = "64",
+                target_pointer_width = "128"
+            ))
+    );
+    assert_eq!(mem::size_of::<U64Align8>(), 8);
+    assert_eq!(mem::align_of::<U64Align8>(), 8);
+    assert_eq!(
+        AtomicCell::<U64Align8>::is_lock_free(),
+        cfg!(not(crossbeam_no_atomic_64))
+    );
+
+    // AtomicU128 is unstable
+    assert!(!AtomicCell::<u128>::is_lock_free());
 }
 
 #[test]
@@ -234,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/cache_padded.rs b/tests/cache_padded.rs
index c9e7687..86e9a77 100644
--- a/tests/cache_padded.rs
+++ b/tests/cache_padded.rs
@@ -85,6 +85,7 @@
     assert_eq!(count.get(), 2);
 }
 
+#[allow(clippy::clone_on_copy)] // This is intentional.
 #[test]
 fn clone() {
     let a = CachePadded::new(17);
diff --git a/tests/sharded_lock.rs b/tests/sharded_lock.rs
index b4b8565..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(()));
@@ -148,7 +151,7 @@
 fn arc_access_in_unwind() {
     let arc = Arc::new(ShardedLock::new(1));
     let arc2 = arc.clone();
-    let _ = thread::spawn(move || -> () {
+    let _ = thread::spawn(move || {
         struct Unwinder {
             i: Arc<ShardedLock<isize>>,
         }