[fbl] Only allow fbl::atomic in the kernel

Userspace should now always be using <atomic>. The kernel will migrate
to a ktl-exposed subset shortly.

Bug: ZX-3357 #comment
Test: no functional change
Change-Id: Idc986ef47a996d2080d15ab680dc0b2255bb5c8d
diff --git a/system/ulib/fbl/include/fbl/atomic.h b/kernel/lib/fbl/include/fbl/atomic.h
similarity index 100%
rename from system/ulib/fbl/include/fbl/atomic.h
rename to kernel/lib/fbl/include/fbl/atomic.h
diff --git a/system/dev/display/dummy/dummy-display.h b/system/dev/display/dummy/dummy-display.h
index e7a518f..00e531b 100644
--- a/system/dev/display/dummy/dummy-display.h
+++ b/system/dev/display/dummy/dummy-display.h
@@ -18,7 +18,6 @@
 #include <ddktl/device.h>
 #include <ddktl/protocol/display/controller.h>
 
-#include <fbl/atomic.h>
 #include <fbl/auto_lock.h>
 #include <fbl/mutex.h>
 #include <fbl/unique_ptr.h>
diff --git a/system/ulib/inspect/include/lib/inspect/state.h b/system/ulib/inspect/include/lib/inspect/state.h
index 096f06b..f4d3d7b 100644
--- a/system/ulib/inspect/include/lib/inspect/state.h
+++ b/system/ulib/inspect/include/lib/inspect/state.h
@@ -4,7 +4,6 @@
 
 #pragma once
 
-#include <fbl/atomic.h>
 #include <fbl/mutex.h>
 #include <fbl/ref_ptr.h>
 #include <lib/inspect/block.h>
diff --git a/system/ulib/inspect/state.cpp b/system/ulib/inspect/state.cpp
index 0012985..a8a26cf 100644
--- a/system/ulib/inspect/state.cpp
+++ b/system/ulib/inspect/state.cpp
@@ -26,7 +26,7 @@
     // any changes to the buffer.
     void Acquire(Block* block) {
         uint64_t* ptr = &block->payload.u64;
-        __atomic_fetch_add(ptr, 1, fbl::memory_order_acq_rel);
+        __atomic_fetch_add(ptr, 1, std::memory_order_acq_rel);
     }
 
     // Release the generation count lock.
@@ -35,7 +35,7 @@
     // the buffer are committed.
     void Release(Block* block) {
         uint64_t* ptr = &block->payload.u64;
-        __atomic_fetch_add(ptr, 1, fbl::memory_order_release);
+        __atomic_fetch_add(ptr, 1, std::memory_order_release);
     }
     BlockIndex target_;
     Heap* heap_;
diff --git a/system/utest/core/pthread/pthread.cpp b/system/utest/core/pthread/pthread.cpp
index cc7bac0..397b204 100644
--- a/system/utest/core/pthread/pthread.cpp
+++ b/system/utest/core/pthread/pthread.cpp
@@ -12,7 +12,8 @@
 #include <time.h>
 #include <unistd.h>
 
-#include <fbl/atomic.h>
+#include <atomic>
+
 #include <zircon/syscalls.h>
 #include <unittest/unittest.h>
 
@@ -20,7 +21,7 @@
 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
 // This is accessed by by both the cond_threads, and the main
 // thread. The latter does so not under the mutex.
-static fbl::atomic_int thread_waked = 0;
+static std::atomic_int thread_waked = 0;
 static int thread_with_lock = 0;
 
 static void log(const char* str) {
diff --git a/system/utest/core/pthread/rules.mk b/system/utest/core/pthread/rules.mk
index a401417..f3f9347 100644
--- a/system/utest/core/pthread/rules.mk
+++ b/system/utest/core/pthread/rules.mk
@@ -18,6 +18,4 @@
 MODULE_LIBS := \
     system/ulib/unittest system/ulib/fdio system/ulib/zircon system/ulib/c
 
-MODULE_STATIC_LIBS := system/ulib/fbl
-
 include make/module.mk
diff --git a/system/utest/fbl/atomic_tests.cpp b/system/utest/fbl/atomic_tests.cpp
deleted file mode 100644
index 2c1547b..0000000
--- a/system/utest/fbl/atomic_tests.cpp
+++ /dev/null
@@ -1,1406 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <fbl/atomic.h>
-
-#include <limits>
-#include <unittest/unittest.h>
-
-namespace {
-
-// A struct with an interesting size for pointer arithmetic tests.
-struct S {
-    char bytes[48];
-};
-
-using function_pointer = void(*)();
-
-bool atomic_explicit_declarations_test() {
-    BEGIN_TEST;
-
-    [[gnu::unused]] fbl::atomic<char> zero_char(0);
-    [[gnu::unused]] fbl::atomic<signed char> zero_schar(0);
-    [[gnu::unused]] fbl::atomic<unsigned char> zero_uchar(0);
-    [[gnu::unused]] fbl::atomic<short> zero_short(0);
-    [[gnu::unused]] fbl::atomic<unsigned short> zero_ushort(0);
-    [[gnu::unused]] fbl::atomic<int> zero_int(0);
-    [[gnu::unused]] fbl::atomic<unsigned int> zero_uint(0);
-    [[gnu::unused]] fbl::atomic<long> zero_long(0);
-    [[gnu::unused]] fbl::atomic<unsigned long> zero_ulong(0);
-    [[gnu::unused]] fbl::atomic<long long> zero_llong(0);
-    [[gnu::unused]] fbl::atomic<unsigned long long> zero_ullong(0);
-
-    [[gnu::unused]] fbl::atomic<intptr_t> zero_intptr_t(0);
-    [[gnu::unused]] fbl::atomic<uintptr_t> zero_uintptr_t(0);
-    [[gnu::unused]] fbl::atomic<size_t> zero_size_t(0);
-    [[gnu::unused]] fbl::atomic<ptrdiff_t> zero_ptrdiff_t(0);
-    [[gnu::unused]] fbl::atomic<intmax_t> zero_intmax_t(0);
-    [[gnu::unused]] fbl::atomic<uintmax_t> zero_uintmax_t(0);
-
-    [[gnu::unused]] fbl::atomic<int8_t> zero_int8_t(0);
-    [[gnu::unused]] fbl::atomic<uint8_t> zero_uint8_t(0);
-    [[gnu::unused]] fbl::atomic<int16_t> zero_int16_t(0);
-    [[gnu::unused]] fbl::atomic<uint16_t> zero_uint16_t(0);
-    [[gnu::unused]] fbl::atomic<int32_t> zero_int32_t(0);
-    [[gnu::unused]] fbl::atomic<uint32_t> zero_uint32_t(0);
-    [[gnu::unused]] fbl::atomic<int64_t> zero_int64_t(0);
-    [[gnu::unused]] fbl::atomic<uint64_t> zero_uint64_t(0);
-
-    [[gnu::unused]] fbl::atomic<int_least8_t> zero_int_least8_t(0);
-    [[gnu::unused]] fbl::atomic<uint_least8_t> zero_uint_least8_t(0);
-    [[gnu::unused]] fbl::atomic<int_least16_t> zero_int_least16_t(0);
-    [[gnu::unused]] fbl::atomic<uint_least16_t> zero_uint_least16_t(0);
-    [[gnu::unused]] fbl::atomic<int_least32_t> zero_int_least32_t(0);
-    [[gnu::unused]] fbl::atomic<uint_least32_t> zero_uint_least32_t(0);
-    [[gnu::unused]] fbl::atomic<int_least64_t> zero_int_least64_t(0);
-    [[gnu::unused]] fbl::atomic<uint_least64_t> zero_uint_least64_t(0);
-    [[gnu::unused]] fbl::atomic<int_fast8_t> zero_int_fast8_t(0);
-    [[gnu::unused]] fbl::atomic<uint_fast8_t> zero_uint_fast8_t(0);
-    [[gnu::unused]] fbl::atomic<int_fast16_t> zero_int_fast16_t(0);
-    [[gnu::unused]] fbl::atomic<uint_fast16_t> zero_uint_fast16_t(0);
-    [[gnu::unused]] fbl::atomic<int_fast32_t> zero_int_fast32_t(0);
-    [[gnu::unused]] fbl::atomic<uint_fast32_t> zero_uint_fast32_t(0);
-    [[gnu::unused]] fbl::atomic<int_fast64_t> zero_int_fast64_t(0);
-    [[gnu::unused]] fbl::atomic<uint_fast64_t> zero_uint_fast64_t(0);
-
-    [[gnu::unused]] fbl::atomic<bool> zero_bool(false);
-
-    [[gnu::unused]] fbl::atomic<void*> zero_void_pointer(nullptr);
-    [[gnu::unused]] fbl::atomic<const void*> zero_const_void_pointer(nullptr);
-    [[gnu::unused]] fbl::atomic<volatile void*> zero_volatile_void_pointer(nullptr);
-    [[gnu::unused]] fbl::atomic<const volatile void*> zero_const_volatile_void_pointer(nullptr);
-    [[gnu::unused]] fbl::atomic<int*> zero_int_pointer(nullptr);
-    [[gnu::unused]] fbl::atomic<const int*> zero_const_int_pointer(nullptr);
-    [[gnu::unused]] fbl::atomic<volatile int*> zero_volatile_int_pointer(nullptr);
-    [[gnu::unused]] fbl::atomic<const volatile int*> zero_const_volatile_int_pointer(nullptr);
-    [[gnu::unused]] fbl::atomic<S*> zero_S_pointer(nullptr);
-    [[gnu::unused]] fbl::atomic<const S*> zero_const_S_pointer(nullptr);
-    [[gnu::unused]] fbl::atomic<volatile S*> zero_volatile_S_pointer(nullptr);
-    [[gnu::unused]] fbl::atomic<const volatile S*> zero_const_volatile_S_pointer(nullptr);
-    [[gnu::unused]] fbl::atomic<function_pointer> zero_function_pointer(nullptr);
-
-    END_TEST;
-}
-
-bool atomic_using_declarations_test() {
-    BEGIN_TEST;
-
-    [[gnu::unused]] fbl::atomic_char zero_char(0);
-    [[gnu::unused]] fbl::atomic_schar zero_schar(0);
-    [[gnu::unused]] fbl::atomic_uchar zero_uchar(0);
-    [[gnu::unused]] fbl::atomic_short zero_short(0);
-    [[gnu::unused]] fbl::atomic_ushort zero_ushort(0);
-    [[gnu::unused]] fbl::atomic_int zero_int(0);
-    [[gnu::unused]] fbl::atomic_uint zero_uint(0);
-    [[gnu::unused]] fbl::atomic_long zero_long(0);
-    [[gnu::unused]] fbl::atomic_ulong zero_ulong(0);
-    [[gnu::unused]] fbl::atomic_llong zero_llong(0);
-    [[gnu::unused]] fbl::atomic_ullong zero_ullong(0);
-
-    [[gnu::unused]] fbl::atomic_intptr_t zero_intptr_t(0);
-    [[gnu::unused]] fbl::atomic_uintptr_t zero_uintptr_t(0);
-    [[gnu::unused]] fbl::atomic_size_t zero_size_t(0);
-    [[gnu::unused]] fbl::atomic_ptrdiff_t zero_ptrdiff_t(0);
-    [[gnu::unused]] fbl::atomic_intmax_t zero_intmax_t(0);
-    [[gnu::unused]] fbl::atomic_uintmax_t zero_uintmax_t(0);
-
-    [[gnu::unused]] fbl::atomic_int8_t zero_int8_t(0);
-    [[gnu::unused]] fbl::atomic_uint8_t zero_uint8_t(0);
-    [[gnu::unused]] fbl::atomic_int16_t zero_int16_t(0);
-    [[gnu::unused]] fbl::atomic_uint16_t zero_uint16_t(0);
-    [[gnu::unused]] fbl::atomic_int32_t zero_int32_t(0);
-    [[gnu::unused]] fbl::atomic_uint32_t zero_uint32_t(0);
-    [[gnu::unused]] fbl::atomic_int64_t zero_int64_t(0);
-    [[gnu::unused]] fbl::atomic_uint64_t zero_uint64_t(0);
-
-    [[gnu::unused]] fbl::atomic_int_least8_t zero_int_least8_t(0);
-    [[gnu::unused]] fbl::atomic_uint_least8_t zero_uint_least8_t(0);
-    [[gnu::unused]] fbl::atomic_int_least16_t zero_int_least16_t(0);
-    [[gnu::unused]] fbl::atomic_uint_least16_t zero_uint_least16_t(0);
-    [[gnu::unused]] fbl::atomic_int_least32_t zero_int_least32_t(0);
-    [[gnu::unused]] fbl::atomic_uint_least32_t zero_uint_least32_t(0);
-    [[gnu::unused]] fbl::atomic_int_least64_t zero_int_least64_t(0);
-    [[gnu::unused]] fbl::atomic_uint_least64_t zero_uint_least64_t(0);
-    [[gnu::unused]] fbl::atomic_int_fast8_t zero_int_fast8_t(0);
-    [[gnu::unused]] fbl::atomic_uint_fast8_t zero_uint_fast8_t(0);
-    [[gnu::unused]] fbl::atomic_int_fast16_t zero_int_fast16_t(0);
-    [[gnu::unused]] fbl::atomic_uint_fast16_t zero_uint_fast16_t(0);
-    [[gnu::unused]] fbl::atomic_int_fast32_t zero_int_fast32_t(0);
-    [[gnu::unused]] fbl::atomic_uint_fast32_t zero_uint_fast32_t(0);
-    [[gnu::unused]] fbl::atomic_int_fast64_t zero_int_fast64_t(0);
-    [[gnu::unused]] fbl::atomic_uint_fast64_t zero_uint_fast64_t(0);
-
-    [[gnu::unused]] fbl::atomic_bool zero_bool(false);
-
-    END_TEST;
-}
-
-// To increase test readability after this point, static_assert that
-// most of these are the same as fbl::atomic<some other type>. That
-// way no one has to read a million lines of test code about
-// fbl::atomic_uint_least32_t.
-
-template <typename T>
-constexpr bool IsSameAsSomeBuiltin() {
-    return fbl::is_same<T, fbl::atomic_char>::value ||
-           fbl::is_same<T, fbl::atomic_schar>::value ||
-           fbl::is_same<T, fbl::atomic_uchar>::value ||
-           fbl::is_same<T, fbl::atomic_short>::value ||
-           fbl::is_same<T, fbl::atomic_ushort>::value ||
-           fbl::is_same<T, fbl::atomic_int>::value ||
-           fbl::is_same<T, fbl::atomic_uint>::value ||
-           fbl::is_same<T, fbl::atomic_long>::value ||
-           fbl::is_same<T, fbl::atomic_ulong>::value ||
-           fbl::is_same<T, fbl::atomic_llong>::value ||
-           fbl::is_same<T, fbl::atomic_ullong>::value ||
-           fbl::is_same<T, fbl::atomic_bool>::value;
-}
-
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_intptr_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_uintptr_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_size_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_ptrdiff_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_intmax_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_uintmax_t>(), "");
-
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_int8_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_uint8_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_int16_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_uint16_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_int32_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_uint32_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_int64_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_uint64_t>(), "");
-
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_int_least8_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_uint_least8_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_int_least16_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_uint_least16_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_int_least32_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_uint_least32_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_int_least64_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_uint_least64_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_int_fast8_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_uint_fast8_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_int_fast16_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_uint_fast16_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_int_fast32_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_uint_fast32_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_int_fast64_t>(), "");
-static_assert(IsSameAsSomeBuiltin<fbl::atomic_uint_fast64_t>(), "");
-
-// We should be able to instantiate fbl::atomics of enum type as well.
-
-enum unspecified_enum {
-    kUnspecifiedValue = 23,
-};
-__UNUSED fbl::atomic<unspecified_enum> atomic_unspecified_enum;
-
-enum specified_enum_char : char {
-    kSpecifiedValue_char = 23,
-};
-__UNUSED fbl::atomic<specified_enum_char> atomic_specified_enum_char;
-
-enum specified_enum_signed_char : signed char {
-    kSpecifiedValue_signed_char = 23,
-};
-__UNUSED fbl::atomic<specified_enum_signed_char> atomic_specified_enum_signed_char;
-
-enum specified_enum_unsigned_char : unsigned char {
-    kSpecifiedValue_unsigned_char = 23,
-};
-__UNUSED fbl::atomic<specified_enum_unsigned_char> atomic_specified_enum_unsigned_char;
-
-enum specified_enum_short : short {
-    kSpecifiedValue_short = 23,
-};
-__UNUSED fbl::atomic<specified_enum_short> atomic_specified_enum_short;
-
-enum specified_enum_unsigned_short : unsigned short {
-    kSpecifiedValue_unsigned_short = 23,
-};
-__UNUSED fbl::atomic<specified_enum_unsigned_short> atomic_specified_enum_unsigned_short;
-
-enum specified_enum_int : int {
-    kSpecifiedValue_int = 23,
-};
-__UNUSED fbl::atomic<specified_enum_int> atomic_specified_enum_int;
-
-enum specified_enum_unsigned_int : unsigned int {
-    kSpecifiedValue_unsigned_int = 23,
-};
-__UNUSED fbl::atomic<specified_enum_unsigned_int> atomic_specified_enum_unsigned_int;
-
-enum specified_enum_long : long {
-    kSpecifiedValue_long = 23,
-};
-__UNUSED fbl::atomic<specified_enum_long> atomic_specified_enum_long;
-
-enum specified_enum_unsigned_long : unsigned long{
-    kSpecifiedValue_unsigned_long = 23,
-};
-__UNUSED fbl::atomic<specified_enum_unsigned_long> atomic_specified_enum_unsigned_long;
-
-enum specified_enum_long_long : long long {
-    kSpecifiedValue_long_long = 23,
-};
-__UNUSED fbl::atomic<specified_enum_long_long> atomic_specified_enum_long_long;
-
-enum specified_enum_unsigned_long_long : unsigned long long {
-    kSpecifiedValue_unsigned_long_long = 23,
-};
-__UNUSED fbl::atomic<specified_enum_unsigned_long_long> atomic_specified_enum_unsigned_long_long;
-
-enum specified_enum_bool : bool {
-    kSpecifiedValue_bool = true,
-};
-__UNUSED fbl::atomic<specified_enum_bool> atomic_specified_enum_bool;
-
-enum struct unspecified_struct_enum {
-    kUnspecifiedValueStruct = 23,
-};
-__UNUSED fbl::atomic<unspecified_struct_enum> atomic_unspecified_struct_enum;
-
-enum struct specified_struct_enum_char : char {
-    kSpecifiedStructValue_char = 23,
-};
-__UNUSED fbl::atomic<specified_struct_enum_char> atomic_specified_struct_enum_char;
-
-enum struct specified_struct_enum_signed_char : signed char {
-    kSpecifiedStructValue_signed_char = 23,
-};
-__UNUSED fbl::atomic<specified_struct_enum_signed_char> atomic_specified_struct_enum_signed_char;
-
-enum struct specified_struct_enum_unsigned_char : unsigned char {
-    kSpecifiedStructValue_unsigned_char = 23,
-};
-__UNUSED fbl::atomic<specified_struct_enum_unsigned_char> atomic_specified_struct_enum_unsigned_char;
-
-enum struct specified_struct_enum_short : short {
-    kSpecifiedStructValue_short = 23,
-};
-__UNUSED fbl::atomic<specified_struct_enum_short> atomic_specified_struct_enum_short;
-
-enum struct specified_struct_enum_unsigned_short : unsigned short {
-    kSpecifiedStructValue_unsigned_short = 23,
-};
-__UNUSED fbl::atomic<specified_struct_enum_unsigned_short> atomic_specified_struct_enum_unsigned_short;
-
-enum struct specified_struct_enum_int : int {
-    kSpecifiedStructValue_int = 23,
-};
-__UNUSED fbl::atomic<specified_struct_enum_int> atomic_specified_struct_enum_int;
-
-enum struct specified_struct_enum_unsigned_int : unsigned int {
-    kSpecifiedStructValue_unsigned_int = 23,
-};
-__UNUSED fbl::atomic<specified_struct_enum_unsigned_int> atomic_specified_struct_enum_unsigned_int;
-
-enum struct specified_struct_enum_long : long {
-    kSpecifiedStructValue_long = 23,
-};
-__UNUSED fbl::atomic<specified_struct_enum_long> atomic_specified_struct_enum_long;
-
-enum struct specified_struct_enum_unsigned_long : unsigned long{
-    kSpecifiedStructValue_unsigned_long = 23,
-};
-__UNUSED fbl::atomic<specified_struct_enum_unsigned_long> atomic_specified_struct_enum_unsigned_long;
-
-enum struct specified_struct_enum_long_long : long long {
-    kSpecifiedStructValue_long_long = 23,
-};
-__UNUSED fbl::atomic<specified_struct_enum_long_long> atomic_specified_struct_enum_long_long;
-
-enum struct specified_struct_enum_unsigned_long_long : unsigned long long {
-    kSpecifiedStructValue_unsigned_long_long = 23,
-};
-__UNUSED fbl::atomic<specified_struct_enum_unsigned_long_long> atomic_specified_struct_enum_unsigned_long_long;
-
-enum struct specified_struct_enum_bool : bool {
-    kSpecifiedStructValue_bool = true,
-};
-__UNUSED fbl::atomic<specified_struct_enum_bool> atomic_specified_struct_enum_bool;
-
-bool atomic_wont_compile_test() {
-    BEGIN_TEST;
-
-    // fbl::atomic only supports integer, enum, and pointer types.
-
-#if TEST_WILL_NOT_COMPILE || 0
-    struct not_integral {};
-    fbl::atomic<not_integral> not_integral;
-#endif
-
-#if TEST_WILL_NOT_COMPILE || 0
-    fbl::atomic<float> not_integral;
-#endif
-
-#if TEST_WILL_NOT_COMPILE || 0
-    fbl::atomic<double> not_integral;
-#endif
-
-    END_TEST;
-}
-
-fbl::memory_order orders[] = {
-    fbl::memory_order_relaxed,
-    fbl::memory_order_acquire,
-    fbl::memory_order_release,
-    fbl::memory_order_acq_rel,
-    fbl::memory_order_seq_cst,
-};
-
-// Bunch of machinery for arithmetic tests.
-template <typename T>
-using ordinary_op = T (*)(T*, T);
-
-template <typename T>
-using atomic_op = T (*)(fbl::atomic<T>*, T, fbl::memory_order);
-
-template <typename T>
-using volatile_op = T (*)(volatile fbl::atomic<T>*, T, fbl::memory_order);
-
-template <typename T>
-struct TestCase {
-    ordinary_op<T> ordinary;
-    atomic_op<T> nonmember_atomic;
-    atomic_op<T> member_atomic;
-    volatile_op<T> nonmember_volatile;
-    volatile_op<T> member_volatile;
-};
-
-template <typename T>
-T test_values[] = {
-    0,
-    1,
-    23,
-    std::numeric_limits<T>::min() / 4,
-    std::numeric_limits<T>::max() / 4,
-};
-
-template <>
-bool test_values<bool>[] = {
-    false,
-    true,
-    true,
-    false,
-    true,
-};
-
-template <>
-void* test_values<void*>[] = {
-    &test_values<int>[0],
-    &test_values<int>[1],
-    &test_values<int>[2],
-    &test_values<int>[3],
-    &test_values<int>[4],
-};
-
-template <>
-const void* test_values<const void*>[] = {
-    &test_values<int>[0],
-    &test_values<int>[1],
-    &test_values<int>[2],
-    &test_values<int>[3],
-    &test_values<int>[4],
-};
-
-template <>
-volatile void* test_values<volatile void*>[] = {
-    &test_values<int>[0],
-    &test_values<int>[1],
-    &test_values<int>[2],
-    &test_values<int>[3],
-    &test_values<int>[4],
-};
-
-template <>
-const volatile void* test_values<const volatile void*>[] = {
-    &test_values<int>[0],
-    &test_values<int>[1],
-    &test_values<int>[2],
-    &test_values<int>[3],
-    &test_values<int>[4],
-};
-
-template <>
-int* test_values<int*>[] = {
-    &test_values<int>[0],
-    &test_values<int>[1],
-    &test_values<int>[2],
-    &test_values<int>[3],
-    &test_values<int>[4],
-};
-
-template <>
-const int* test_values<const int*>[] = {
-    &test_values<int>[0],
-    &test_values<int>[1],
-    &test_values<int>[2],
-    &test_values<int>[3],
-    &test_values<int>[4],
-};
-
-template <>
-volatile int* test_values<volatile int*>[] = {
-    &test_values<int>[0],
-    &test_values<int>[1],
-    &test_values<int>[2],
-    &test_values<int>[3],
-    &test_values<int>[4],
-};
-
-template <>
-const volatile int* test_values<const volatile int*>[] = {
-    &test_values<int>[0],
-    &test_values<int>[1],
-    &test_values<int>[2],
-    &test_values<int>[3],
-    &test_values<int>[4],
-};
-
-S test_values_of_S[] = { {}, {}, {}, {} };
-
-template <>
-S* test_values<S*>[] = {
-    &test_values_of_S[0],
-    &test_values_of_S[1],
-    &test_values_of_S[2],
-    &test_values_of_S[3],
-    nullptr,
-};
-
-template <>
-const S* test_values<const S*>[] = {
-    &test_values_of_S[0],
-    &test_values_of_S[1],
-    &test_values_of_S[2],
-    &test_values_of_S[3],
-    nullptr,
-};
-
-template <>
-volatile S* test_values<volatile S*>[] = {
-    &test_values_of_S[0],
-    &test_values_of_S[1],
-    &test_values_of_S[2],
-    &test_values_of_S[3],
-    nullptr,
-};
-
-template <>
-const volatile S* test_values<const volatile S*>[] = {
-    &test_values_of_S[0],
-    &test_values_of_S[1],
-    &test_values_of_S[2],
-    &test_values_of_S[3],
-    nullptr,
-};
-
-// Try to force each of these to be different so that the test
-// continues working under ICF. The CAS tests compare function pointer
-// values, so it's important that these have different addresses.
-static volatile int volatile_0;
-void nothing_0() {
-    volatile_0 = 0;
-}
-static volatile int volatile_1;
-void nothing_1() {
-    volatile_1 = 1;
-}
-static volatile int volatile_2;
-void nothing_2() {
-    volatile_2 = 2;
-}
-static volatile int volatile_3;
-void nothing_3() {
-    volatile_3 = 3;
-}
-
-template <>
-function_pointer test_values<function_pointer>[] = {
-    &nothing_0,
-    &nothing_1,
-    &nothing_2,
-    &nothing_3,
-    nullptr,
-};
-
-template <typename T>
-TestCase<T> test_cases[] = {
-    {
-        [](T* ptr_to_a, T b) -> T {
-            T a = *ptr_to_a;
-            *ptr_to_a = static_cast<T>(a + b);
-            return a;
-        },
-        fbl::atomic_fetch_add<T>,
-        [](fbl::atomic<T>* ptr_to_atomic_a, T b, fbl::memory_order order) -> T {
-            return ptr_to_atomic_a->fetch_add(b, order);
-        },
-        fbl::atomic_fetch_add<T>,
-        [](volatile fbl::atomic<T>* ptr_to_atomic_a, T b, fbl::memory_order order) -> T {
-            return ptr_to_atomic_a->fetch_add(b, order);
-        },
-    },
-    {
-        [](T* ptr_to_a, T b) -> T {
-            T a = *ptr_to_a;
-            *ptr_to_a = static_cast<T>(a & b);
-            return a;
-        },
-        fbl::atomic_fetch_and<T>,
-        [](fbl::atomic<T>* ptr_to_atomic_a, T b, fbl::memory_order order) -> T {
-            return ptr_to_atomic_a->fetch_and(b, order);
-        },
-        fbl::atomic_fetch_and<T>,
-        [](volatile fbl::atomic<T>* ptr_to_atomic_a, T b, fbl::memory_order order) -> T {
-            return ptr_to_atomic_a->fetch_and(b, order);
-        },
-    },
-    {
-        [](T* ptr_to_a, T b) -> T {
-            T a = *ptr_to_a;
-            *ptr_to_a = static_cast<T>(a | b);
-            return a;
-        },
-        fbl::atomic_fetch_or<T>,
-        [](fbl::atomic<T>* ptr_to_atomic_a, T b, fbl::memory_order order) -> T {
-            return ptr_to_atomic_a->fetch_or(b, order);
-        },
-        fbl::atomic_fetch_or<T>,
-        [](volatile fbl::atomic<T>* ptr_to_atomic_a, T b, fbl::memory_order order) -> T {
-            return ptr_to_atomic_a->fetch_or(b, order);
-        },
-    },
-    {
-        [](T* ptr_to_a, T b) -> T {
-            T a = *ptr_to_a;
-            *ptr_to_a = static_cast<T>(a ^ b);
-            return a;
-        },
-        fbl::atomic_fetch_xor<T>,
-        [](fbl::atomic<T>* ptr_to_atomic_a, T b, fbl::memory_order order) -> T {
-            return ptr_to_atomic_a->fetch_xor(b, order);
-        },
-        fbl::atomic_fetch_xor<T>,
-        [](volatile fbl::atomic<T>* ptr_to_atomic_a, T b, fbl::memory_order order) -> T {
-            return ptr_to_atomic_a->fetch_xor(b, order);
-        },
-    },
-};
-
-template <typename T>
-TestCase<T> subtraction_test_case = {
-    [](T* ptr_to_a, T b) -> T {
-        T a = *ptr_to_a;
-        *ptr_to_a = static_cast<T>(a - b);
-        return a;
-    },
-    fbl::atomic_fetch_sub,
-    [](fbl::atomic<T>* ptr_to_atomic_a, T b, fbl::memory_order order) -> T {
-        return ptr_to_atomic_a->fetch_sub(b, order);
-    },
-    fbl::atomic_fetch_sub,
-    [](volatile fbl::atomic<T>* ptr_to_atomic_a, T b, fbl::memory_order order) -> T {
-        return ptr_to_atomic_a->fetch_sub(b, order);
-    },
-};
-
-template <typename T>
-bool math_test() {
-    for (const T original_left : test_values<T>) {
-        for (T right : test_values<T>) {
-            for (const auto& order : orders) {
-                for (auto test_case : test_cases<T>) {
-                    {
-                        fbl::atomic<T> atomic_left(original_left);
-                        T left = original_left;
-                        ASSERT_EQ(test_case.ordinary(&left, right),
-                                  test_case.member_atomic(&atomic_left, right, order),
-                                  "Atomic and ordinary math differ");
-                        ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-                    }
-                    {
-                        fbl::atomic<T> atomic_left(original_left);
-                        T left = original_left;
-                        ASSERT_EQ(test_case.ordinary(&left, right),
-                                  test_case.nonmember_atomic(&atomic_left, right, order),
-                                  "Atomic and ordinary math differ");
-                        ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-                    }
-                    {
-                        volatile fbl::atomic<T> atomic_left(original_left);
-                        T left = original_left;
-                        ASSERT_EQ(test_case.ordinary(&left, right),
-                                  test_case.member_volatile(&atomic_left, right, order),
-                                  "Atomic and ordinary math differ");
-                        ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-                    }
-                    {
-                        volatile fbl::atomic<T> atomic_left(original_left);
-                        T left = original_left;
-                        ASSERT_EQ(test_case.ordinary(&left, right),
-                                  test_case.nonmember_volatile(&atomic_left, right, order),
-                                  "Atomic and ordinary math differ");
-                        ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-                    }
-                }
-                // Let's not worry about signed subtraction UB.
-                if (fbl::is_unsigned<T>::value) {
-                    {
-                        fbl::atomic<T> atomic_left(original_left);
-                        T left = original_left;
-                        ASSERT_EQ(subtraction_test_case<T>.ordinary(&left, right),
-                                  subtraction_test_case<T>.member_atomic(&atomic_left, right, order),
-                                  "Atomic and ordinary math differ");
-                        ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-                    }
-                    {
-                        fbl::atomic<T> atomic_left(original_left);
-                        T left = original_left;
-                        ASSERT_EQ(subtraction_test_case<T>.ordinary(&left, right),
-                                  subtraction_test_case<T>.nonmember_atomic(&atomic_left, right, order),
-                                  "Atomic and ordinary math differ");
-                        ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-                    }
-                    {
-                        volatile fbl::atomic<T> atomic_left(original_left);
-                        T left = original_left;
-                        ASSERT_EQ(subtraction_test_case<T>.ordinary(&left, right),
-                                  subtraction_test_case<T>.member_volatile(&atomic_left, right, order),
-                                  "Atomic and ordinary math differ");
-                        ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-                    }
-                    {
-                        volatile fbl::atomic<T> atomic_left(original_left);
-                        T left = original_left;
-                        ASSERT_EQ(subtraction_test_case<T>.ordinary(&left, right),
-                                  subtraction_test_case<T>.nonmember_volatile(&atomic_left, right, order),
-                                  "Atomic and ordinary math differ");
-                        ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-                    }
-                }
-            }
-        }
-    }
-
-    return true;
-}
-
-template <typename T>
-using ordinary_pointer_op = T (*)(T*, ptrdiff_t);
-
-template <typename T>
-using atomic_pointer_op = T (*)(fbl::atomic<T>*, ptrdiff_t, fbl::memory_order);
-
-template <typename T>
-using volatile_pointer_op = T (*)(volatile fbl::atomic<T>*, ptrdiff_t, fbl::memory_order);
-
-template <typename T>
-struct PointerTestCase {
-    ordinary_pointer_op<T> ordinary;
-    atomic_pointer_op<T> nonmember_atomic;
-    atomic_pointer_op<T> member_atomic;
-    volatile_pointer_op<T> nonmember_volatile;
-    volatile_pointer_op<T> member_volatile;
-};
-
-template <typename T>
-PointerTestCase<T> pointer_add_test_case = {
-    [](T* ptr_to_a, ptrdiff_t d) -> T {
-        T a = *ptr_to_a;
-        *ptr_to_a = a + d;
-        return a;
-    },
-    [](fbl::atomic<T>* ptr_to_atomic_a, ptrdiff_t d, fbl::memory_order order) -> T {
-        return fbl::atomic_fetch_add(ptr_to_atomic_a, d, order);
-    },
-    [](fbl::atomic<T>* ptr_to_atomic_a, ptrdiff_t d, fbl::memory_order order) -> T {
-        return ptr_to_atomic_a->fetch_add(d, order);
-    },
-    [](volatile fbl::atomic<T>* ptr_to_atomic_a, ptrdiff_t d, fbl::memory_order order) -> T {
-        return fbl::atomic_fetch_add(ptr_to_atomic_a, d, order);
-    },
-    [](volatile fbl::atomic<T>* ptr_to_atomic_a, ptrdiff_t d, fbl::memory_order order) -> T {
-        return ptr_to_atomic_a->fetch_add(d, order);
-    },
-};
-
-template <typename T>
-PointerTestCase<T> pointer_sub_test_case = {
-    [](T* ptr_to_a, ptrdiff_t d) -> T {
-        T a = *ptr_to_a;
-        *ptr_to_a = a - d;
-        return a;
-    },
-    [](fbl::atomic<T>* ptr_to_atomic_a, ptrdiff_t d, fbl::memory_order order) -> T {
-        return fbl::atomic_fetch_sub(ptr_to_atomic_a, d, order);
-    },
-    [](fbl::atomic<T>* ptr_to_atomic_a, ptrdiff_t d, fbl::memory_order order) -> T {
-        return ptr_to_atomic_a->fetch_sub(d, order);
-    },
-    [](volatile fbl::atomic<T>* ptr_to_atomic_a, ptrdiff_t d, fbl::memory_order order) -> T {
-        return fbl::atomic_fetch_sub(ptr_to_atomic_a, d, order);
-    },
-    [](volatile fbl::atomic<T>* ptr_to_atomic_a, ptrdiff_t d, fbl::memory_order order) -> T {
-        return ptr_to_atomic_a->fetch_sub(d, order);
-    },
-};
-
-template <typename T>
-bool pointer_add_test() {
-    static_assert(fbl::is_pointer<T>::value, "");
-    ptrdiff_t right = 2;
-    const auto& test_case = pointer_add_test_case<T>;
-    for (const T original_left : test_values<T>) {
-        for (const auto& order : orders) {
-            {
-                fbl::atomic<T> atomic_left(original_left);
-                T left = original_left;
-                ASSERT_EQ(test_case.ordinary(&left, right),
-                          test_case.member_atomic(&atomic_left, right, order),
-                          "Atomic and ordinary math differ");
-                ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-            }
-            {
-                fbl::atomic<T> atomic_left(original_left);
-                T left = original_left;
-                ASSERT_EQ(test_case.ordinary(&left, right),
-                          test_case.nonmember_atomic(&atomic_left, right, order),
-                          "Atomic and ordinary math differ");
-                ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-            }
-            {
-                volatile fbl::atomic<T> atomic_left(original_left);
-                T left = original_left;
-                ASSERT_EQ(test_case.ordinary(&left, right),
-                          test_case.member_volatile(&atomic_left, right, order),
-                          "Atomic and ordinary math differ");
-                ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-            }
-            {
-                volatile fbl::atomic<T> atomic_left(original_left);
-                T left = original_left;
-                ASSERT_EQ(test_case.ordinary(&left, right),
-                          test_case.nonmember_volatile(&atomic_left, right, order),
-                          "Atomic and ordinary math differ");
-                ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-            }
-        }
-
-        right -= 1;
-    }
-
-    return true;
-}
-
-template <typename T>
-bool pointer_sub_test() {
-    static_assert(fbl::is_pointer<T>::value, "");
-    ptrdiff_t right = -2;
-    const auto& test_case = pointer_sub_test_case<T>;
-    for (const T original_left : test_values<T>) {
-        for (const auto& order : orders) {
-            {
-                fbl::atomic<T> atomic_left(original_left);
-                T left = original_left;
-                ASSERT_EQ(test_case.ordinary(&left, right),
-                          test_case.member_atomic(&atomic_left, right, order),
-                          "Atomic and ordinary math differ");
-                ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-            }
-            {
-                fbl::atomic<T> atomic_left(original_left);
-                T left = original_left;
-                ASSERT_EQ(test_case.ordinary(&left, right),
-                          test_case.nonmember_atomic(&atomic_left, right, order),
-                          "Atomic and ordinary math differ");
-                ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-            }
-            {
-                volatile fbl::atomic<T> atomic_left(original_left);
-                T left = original_left;
-                ASSERT_EQ(test_case.ordinary(&left, right),
-                          test_case.member_volatile(&atomic_left, right, order),
-                          "Atomic and ordinary math differ");
-                ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-            }
-            {
-                volatile fbl::atomic<T> atomic_left(original_left);
-                T left = original_left;
-                ASSERT_EQ(test_case.ordinary(&left, right),
-                          test_case.nonmember_volatile(&atomic_left, right, order),
-                          "Atomic and ordinary math differ");
-                ASSERT_EQ(left, atomic_load(&atomic_left), "Atomic and ordinary math differ");
-            }
-        }
-
-        right += 1;
-    }
-
-    return true;
-}
-
-template <typename T>
-bool load_store_test() {
-    fbl::atomic<T> atomic_value;
-
-    for (T value : test_values<T>) {
-        atomic_value.store(value);
-        ASSERT_EQ(atomic_value.load(), value, "Member load/store busted");
-    }
-
-    for (T value : test_values<T>) {
-        fbl::atomic_store(&atomic_value, value);
-        ASSERT_EQ(atomic_load(&atomic_value), value, "Nonmember load/store busted");
-    }
-
-    volatile fbl::atomic<T> volatile_value;
-
-    for (T value : test_values<T>) {
-        volatile_value.store(value);
-        ASSERT_EQ(volatile_value.load(), value, "Member load/store busted");
-    }
-
-    for (T value : test_values<T>) {
-        fbl::atomic_store(&volatile_value, value);
-        ASSERT_EQ(atomic_load(&volatile_value), value, "Nonmember load/store busted");
-    }
-
-    return true;
-}
-
-template <typename T>
-bool exchange_test() {
-    T last_value = test_values<T>[0];
-    fbl::atomic<T> atomic_value(last_value);
-
-    for (T value : test_values<T>) {
-        ASSERT_EQ(atomic_value.load(), last_value, "Member exchange busted");
-        ASSERT_EQ(atomic_value.exchange(value), last_value, "Member exchange busted");
-        last_value = value;
-    }
-
-    last_value = test_values<T>[0];
-    atomic_value.store(last_value);
-
-    for (T value : test_values<T>) {
-        ASSERT_EQ(fbl::atomic_load(&atomic_value), last_value, "Nonmember exchange busted");
-        ASSERT_EQ(fbl::atomic_exchange(&atomic_value, value), last_value, "Nonmember exchange busted");
-        last_value = value;
-    }
-
-    last_value = test_values<T>[0];
-    volatile fbl::atomic<T> volatile_value(last_value);
-
-    for (T value : test_values<T>) {
-        ASSERT_EQ(volatile_value.load(), last_value, "Member exchange busted");
-        ASSERT_EQ(volatile_value.exchange(value), last_value, "Member exchange busted");
-        last_value = value;
-    }
-
-    last_value = test_values<T>[0];
-    volatile_value.store(last_value);
-
-    for (T value : test_values<T>) {
-        ASSERT_EQ(fbl::atomic_load(&volatile_value), last_value, "Nonmember exchange busted");
-        ASSERT_EQ(fbl::atomic_exchange(&volatile_value, value), last_value, "Nonmember exchange busted");
-        last_value = value;
-    }
-
-    return true;
-}
-
-template <typename T>
-struct cas_function {
-    bool (*function)(fbl::atomic<T>* atomic_ptr, T* expected, T desired,
-                     fbl::memory_order success_order, fbl::memory_order failure_order);
-    bool can_spuriously_fail;
-};
-
-template <typename T>
-cas_function<T> cas_functions[] = {
-    {fbl::atomic_compare_exchange_weak, true},
-    {fbl::atomic_compare_exchange_strong, false},
-    {[](fbl::atomic<T>* atomic_ptr, T* expected, T desired,
-        fbl::memory_order success_order, fbl::memory_order failure_order) {
-         return atomic_ptr->compare_exchange_weak(expected, desired, success_order, failure_order);
-     },
-     true},
-    {[](fbl::atomic<T>* atomic_ptr, T* expected, T desired,
-        fbl::memory_order success_order, fbl::memory_order failure_order) {
-         return atomic_ptr->compare_exchange_strong(expected, desired, success_order, failure_order);
-     },
-     false},
-};
-
-template <typename T>
-struct volatile_cas_function {
-    bool (*function)(volatile fbl::atomic<T>* atomic_ptr, T* expected, T desired,
-                     fbl::memory_order success_order, fbl::memory_order failure_order);
-    bool can_spuriously_fail;
-};
-
-template <typename T>
-volatile_cas_function<T> volatile_cas_functions[] = {
-    {fbl::atomic_compare_exchange_weak, true},
-    {fbl::atomic_compare_exchange_strong, false},
-    {[](volatile fbl::atomic<T>* atomic_ptr, T* expected, T desired,
-        fbl::memory_order success_order, fbl::memory_order failure_order) {
-         return atomic_ptr->compare_exchange_weak(expected, desired, success_order, failure_order);
-     },
-     true},
-    {[](volatile fbl::atomic<T>* atomic_ptr, T* expected, T desired,
-        fbl::memory_order success_order, fbl::memory_order failure_order) {
-         return atomic_ptr->compare_exchange_strong(expected, desired, success_order, failure_order);
-     },
-     false}};
-
-enum cas_slots {
-    kExpected = 0,
-    kActual = 1,
-    kDesired = 2,
-};
-
-template <typename T>
-T cas_test_values[] = {
-    22,
-    23,
-    24,
-};
-
-template <>
-bool cas_test_values<bool>[] = {
-    false,
-    true,
-    false,
-};
-
-template <>
-void* cas_test_values<void*>[] = {
-    &cas_test_values<int>[0],
-    &cas_test_values<int>[1],
-    &cas_test_values<int>[2],
-};
-
-template <>
-const void* cas_test_values<const void*>[] = {
-    &cas_test_values<int>[0],
-    &cas_test_values<int>[1],
-    &cas_test_values<int>[2],
-};
-
-template <>
-volatile void* cas_test_values<volatile void*>[] = {
-    &cas_test_values<int>[0],
-    &cas_test_values<int>[1],
-    &cas_test_values<int>[2],
-};
-
-template <>
-const volatile void* cas_test_values<const volatile void*>[] = {
-    &cas_test_values<int>[0],
-    &cas_test_values<int>[1],
-    &cas_test_values<int>[2],
-};
-
-template <>
-int* cas_test_values<int*>[] = {
-    &cas_test_values<int>[0],
-    &cas_test_values<int>[1],
-    &cas_test_values<int>[2],
-};
-
-template <>
-const int* cas_test_values<const int*>[] = {
-    &cas_test_values<int>[0],
-    &cas_test_values<int>[1],
-    &cas_test_values<int>[2],
-};
-
-template <>
-volatile int* cas_test_values<volatile int*>[] = {
-    &cas_test_values<int>[0],
-    &cas_test_values<int>[1],
-    &cas_test_values<int>[2],
-};
-
-template <>
-const volatile int* cas_test_values<const volatile int*>[] = {
-    &cas_test_values<int>[0],
-    &cas_test_values<int>[1],
-    &cas_test_values<int>[2],
-};
-
-S cas_test_values_of_S[] = { {}, {} };
-
-template <>
-S* cas_test_values<S*>[] = {
-    &cas_test_values_of_S[0],
-    &cas_test_values_of_S[1],
-    nullptr,
-};
-
-template <>
-const S* cas_test_values<const S*>[] = {
-    &cas_test_values_of_S[0],
-    &cas_test_values_of_S[1],
-    nullptr,
-};
-
-template <>
-volatile S* cas_test_values<volatile S*>[] = {
-    &cas_test_values_of_S[0],
-    &cas_test_values_of_S[1],
-    nullptr,
-};
-
-template <>
-const volatile S* cas_test_values<const volatile S*>[] = {
-    &cas_test_values_of_S[0],
-    &cas_test_values_of_S[1],
-    nullptr,
-};
-
-template <>
-function_pointer cas_test_values<function_pointer>[] = {
-    &nothing_0,
-    &nothing_1,
-    nullptr,
-};
-
-template <typename T>
-bool compare_exchange_test() {
-    for (auto cas : cas_functions<T>) {
-        for (const auto& success_order : orders) {
-            for (const auto& failure_order : orders) {
-                {
-                    // Failure case
-                    T actual = cas_test_values<T>[kActual];
-                    fbl::atomic<T> atomic_value(actual);
-                    T expected = cas_test_values<T>[kExpected];
-                    T desired = cas_test_values<T>[kDesired];
-                    EXPECT_FALSE(cas.function(&atomic_value, &expected, desired,
-                                              success_order, failure_order),
-                                 "compare-exchange shouldn't have succeeded!");
-                    EXPECT_EQ(expected, actual, "compare-exchange didn't report actual value!");
-                }
-                {
-                    // Success case
-                    T actual = cas_test_values<T>[kActual];
-                    fbl::atomic<T> atomic_value(actual);
-                    T expected = actual;
-                    T desired = cas_test_values<T>[kDesired];
-                    // Some compare-and-swap functions can spuriously fail.
-                    bool succeeded = cas.function(&atomic_value, &expected, desired,
-                                                  success_order, failure_order);
-                    if (!cas.can_spuriously_fail) {
-                        EXPECT_TRUE(succeeded, "compare-exchange should've succeeded!");
-                    }
-                    EXPECT_EQ(expected, actual, "compare-exchange didn't report actual value!");
-                }
-            }
-        }
-    }
-
-    for (auto cas : volatile_cas_functions<T>) {
-        for (const auto& success_order : orders) {
-            for (const auto& failure_order : orders) {
-                {
-                    // Failure case
-                    T actual = cas_test_values<T>[kActual];
-                    fbl::atomic<T> atomic_value(actual);
-                    T expected = cas_test_values<T>[kExpected];
-                    T desired = cas_test_values<T>[kDesired];
-                    EXPECT_FALSE(cas.function(&atomic_value, &expected, desired,
-                                              success_order, failure_order),
-                                 "compare-exchange shouldn't have succeeded!");
-                    EXPECT_EQ(expected, actual, "compare-exchange didn't report actual value!");
-                }
-                {
-                    // Success case
-                    T actual = cas_test_values<T>[kActual];
-                    fbl::atomic<T> atomic_value(actual);
-                    T expected = actual;
-                    T desired = cas_test_values<T>[kDesired];
-                    // Compare-and-swap can spuriously fail.
-                    // Some compare-and-swap functions can spuriously fail.
-                    bool succeeded = cas.function(&atomic_value, &expected, desired,
-                                                  success_order, failure_order);
-                    if (!cas.can_spuriously_fail) {
-                        EXPECT_TRUE(succeeded, "compare-exchange should've succeeded!");
-                    }
-                    EXPECT_EQ(expected, actual, "compare-exchange didn't report actual value!");
-                }
-            }
-        }
-    }
-
-    return true;
-}
-
-// Actual test cases on operations for each builtin type.
-bool atomic_math_test() {
-    BEGIN_TEST;
-
-    ASSERT_TRUE(math_test<char>());
-    ASSERT_TRUE(math_test<signed char>());
-    ASSERT_TRUE(math_test<unsigned char>());
-    ASSERT_TRUE(math_test<short>());
-    ASSERT_TRUE(math_test<unsigned short>());
-    ASSERT_TRUE(math_test<int>());
-    ASSERT_TRUE(math_test<unsigned int>());
-    ASSERT_TRUE(math_test<long>());
-    ASSERT_TRUE(math_test<unsigned long>());
-    ASSERT_TRUE(math_test<long long>());
-    ASSERT_TRUE(math_test<unsigned long long>());
-
-    END_TEST;
-}
-
-bool atomic_pointer_math_test() {
-    BEGIN_TEST;
-
-    ASSERT_TRUE(pointer_add_test<int*>());
-    ASSERT_TRUE(pointer_add_test<const int*>());
-    ASSERT_TRUE(pointer_add_test<volatile int*>());
-    ASSERT_TRUE(pointer_add_test<const volatile int*>());
-    ASSERT_TRUE(pointer_add_test<S*>());
-    ASSERT_TRUE(pointer_add_test<const S*>());
-    ASSERT_TRUE(pointer_add_test<volatile S*>());
-    ASSERT_TRUE(pointer_add_test<const volatile S*>());
-
-    ASSERT_TRUE(pointer_sub_test<int*>());
-    ASSERT_TRUE(pointer_sub_test<const int*>());
-    ASSERT_TRUE(pointer_sub_test<volatile int*>());
-    ASSERT_TRUE(pointer_sub_test<const volatile int*>());
-    ASSERT_TRUE(pointer_sub_test<S*>());
-    ASSERT_TRUE(pointer_sub_test<const S*>());
-    ASSERT_TRUE(pointer_sub_test<volatile S*>());
-    ASSERT_TRUE(pointer_sub_test<const volatile S*>());
-
-    // Note that there is no void pointer or function pointer math,
-    // and so no tests of them.
-
-    END_TEST;
-}
-
-bool atomic_load_store_test() {
-    BEGIN_TEST;
-
-    ASSERT_TRUE(load_store_test<char>());
-    ASSERT_TRUE(load_store_test<signed char>());
-    ASSERT_TRUE(load_store_test<unsigned char>());
-    ASSERT_TRUE(load_store_test<short>());
-    ASSERT_TRUE(load_store_test<unsigned short>());
-    ASSERT_TRUE(load_store_test<int>());
-    ASSERT_TRUE(load_store_test<unsigned int>());
-    ASSERT_TRUE(load_store_test<long>());
-    ASSERT_TRUE(load_store_test<unsigned long>());
-    ASSERT_TRUE(load_store_test<long long>());
-    ASSERT_TRUE(load_store_test<unsigned long long>());
-    ASSERT_TRUE(load_store_test<bool>());
-
-    ASSERT_TRUE(load_store_test<void*>());
-    ASSERT_TRUE(load_store_test<const void*>());
-    ASSERT_TRUE(load_store_test<volatile void*>());
-    ASSERT_TRUE(load_store_test<const volatile void*>());
-    ASSERT_TRUE(load_store_test<int*>());
-    ASSERT_TRUE(load_store_test<const int*>());
-    ASSERT_TRUE(load_store_test<volatile int*>());
-    ASSERT_TRUE(load_store_test<const volatile int*>());
-    ASSERT_TRUE(load_store_test<function_pointer>());
-
-    END_TEST;
-}
-
-bool atomic_exchange_test() {
-    BEGIN_TEST;
-
-    ASSERT_TRUE(exchange_test<char>());
-    ASSERT_TRUE(exchange_test<signed char>());
-    ASSERT_TRUE(exchange_test<unsigned char>());
-    ASSERT_TRUE(exchange_test<short>());
-    ASSERT_TRUE(exchange_test<unsigned short>());
-    ASSERT_TRUE(exchange_test<int>());
-    ASSERT_TRUE(exchange_test<unsigned int>());
-    ASSERT_TRUE(exchange_test<long>());
-    ASSERT_TRUE(exchange_test<unsigned long>());
-    ASSERT_TRUE(exchange_test<long long>());
-    ASSERT_TRUE(exchange_test<unsigned long long>());
-    ASSERT_TRUE(exchange_test<bool>());
-
-    ASSERT_TRUE(exchange_test<void*>());
-    ASSERT_TRUE(exchange_test<const void*>());
-    ASSERT_TRUE(exchange_test<volatile void*>());
-    ASSERT_TRUE(exchange_test<const volatile void*>());
-    ASSERT_TRUE(exchange_test<int*>());
-    ASSERT_TRUE(exchange_test<const int*>());
-    ASSERT_TRUE(exchange_test<volatile int*>());
-    ASSERT_TRUE(exchange_test<const volatile int*>());
-    ASSERT_TRUE(exchange_test<S*>());
-    ASSERT_TRUE(exchange_test<const S*>());
-    ASSERT_TRUE(exchange_test<volatile S*>());
-    ASSERT_TRUE(exchange_test<const volatile S*>());
-    ASSERT_TRUE(exchange_test<function_pointer>());
-
-    END_TEST;
-}
-
-bool atomic_compare_exchange_test() {
-    BEGIN_TEST;
-
-    ASSERT_TRUE(compare_exchange_test<char>());
-    ASSERT_TRUE(compare_exchange_test<signed char>());
-    ASSERT_TRUE(compare_exchange_test<unsigned char>());
-    ASSERT_TRUE(compare_exchange_test<short>());
-    ASSERT_TRUE(compare_exchange_test<unsigned short>());
-    ASSERT_TRUE(compare_exchange_test<int>());
-    ASSERT_TRUE(compare_exchange_test<unsigned int>());
-    ASSERT_TRUE(compare_exchange_test<long>());
-    ASSERT_TRUE(compare_exchange_test<unsigned long>());
-    ASSERT_TRUE(compare_exchange_test<long long>());
-    ASSERT_TRUE(compare_exchange_test<unsigned long long>());
-    ASSERT_TRUE(compare_exchange_test<bool>());
-
-    ASSERT_TRUE(compare_exchange_test<void*>());
-    ASSERT_TRUE(compare_exchange_test<const void*>());
-    ASSERT_TRUE(compare_exchange_test<volatile void*>());
-    ASSERT_TRUE(compare_exchange_test<const volatile void*>());
-    ASSERT_TRUE(compare_exchange_test<int*>());
-    ASSERT_TRUE(compare_exchange_test<const int*>());
-    ASSERT_TRUE(compare_exchange_test<volatile int*>());
-    ASSERT_TRUE(compare_exchange_test<const volatile int*>());
-    ASSERT_TRUE(compare_exchange_test<S*>());
-    ASSERT_TRUE(compare_exchange_test<const S*>());
-    ASSERT_TRUE(compare_exchange_test<volatile S*>());
-    ASSERT_TRUE(compare_exchange_test<const volatile S*>());
-    ASSERT_TRUE(compare_exchange_test<function_pointer>());
-
-    END_TEST;
-}
-
-// Code wants to rely on the ABI of fbl::atomic types. This means
-// matching the underlying types' size and alignment, and the class
-// being standard layout.
-
-static_assert(sizeof(fbl::atomic<char>) == sizeof(char), "");
-static_assert(sizeof(fbl::atomic<signed char>) == sizeof(signed char), "");
-static_assert(sizeof(fbl::atomic<unsigned char>) == sizeof(unsigned char), "");
-static_assert(sizeof(fbl::atomic<short>) == sizeof(short), "");
-static_assert(sizeof(fbl::atomic<unsigned short>) == sizeof(unsigned short), "");
-static_assert(sizeof(fbl::atomic<int>) == sizeof(int), "");
-static_assert(sizeof(fbl::atomic<unsigned int>) == sizeof(unsigned int), "");
-static_assert(sizeof(fbl::atomic<long>) == sizeof(long), "");
-static_assert(sizeof(fbl::atomic<unsigned long>) == sizeof(unsigned long), "");
-static_assert(sizeof(fbl::atomic<long long>) == sizeof(long long), "");
-static_assert(sizeof(fbl::atomic<unsigned long long>) == sizeof(unsigned long long), "");
-static_assert(sizeof(fbl::atomic<bool>) == sizeof(bool), "");
-static_assert(sizeof(fbl::atomic<void*>) == sizeof(void*), "");
-static_assert(sizeof(fbl::atomic<const void*>) == sizeof(const void*), "");
-static_assert(sizeof(fbl::atomic<volatile void*>) == sizeof(volatile void*), "");
-static_assert(sizeof(fbl::atomic<const volatile void*>) == sizeof(const volatile void*), "");
-static_assert(sizeof(fbl::atomic<int*>) == sizeof(int*), "");
-static_assert(sizeof(fbl::atomic<const int*>) == sizeof(const int*), "");
-static_assert(sizeof(fbl::atomic<volatile int*>) == sizeof(volatile int*), "");
-static_assert(sizeof(fbl::atomic<const volatile int*>) == sizeof(const volatile int*), "");
-static_assert(sizeof(fbl::atomic<S*>) == sizeof(S*), "");
-static_assert(sizeof(fbl::atomic<const S*>) == sizeof(const S*), "");
-static_assert(sizeof(fbl::atomic<volatile S*>) == sizeof(volatile S*), "");
-static_assert(sizeof(fbl::atomic<const volatile S*>) == sizeof(const volatile S*), "");
-static_assert(sizeof(fbl::atomic<function_pointer>) == sizeof(function_pointer), "");
-
-static_assert(alignof(fbl::atomic<char>) == alignof(char), "");
-static_assert(alignof(fbl::atomic<signed char>) == alignof(signed char), "");
-static_assert(alignof(fbl::atomic<unsigned char>) == alignof(unsigned char), "");
-static_assert(alignof(fbl::atomic<short>) == alignof(short), "");
-static_assert(alignof(fbl::atomic<unsigned short>) == alignof(unsigned short), "");
-static_assert(alignof(fbl::atomic<int>) == alignof(int), "");
-static_assert(alignof(fbl::atomic<unsigned int>) == alignof(unsigned int), "");
-static_assert(alignof(fbl::atomic<long>) == alignof(long), "");
-static_assert(alignof(fbl::atomic<unsigned long>) == alignof(unsigned long), "");
-static_assert(alignof(fbl::atomic<long long>) == alignof(long long), "");
-static_assert(alignof(fbl::atomic<unsigned long long>) == alignof(unsigned long long), "");
-static_assert(alignof(fbl::atomic<bool>) == alignof(bool), "");
-static_assert(alignof(fbl::atomic<void*>) == alignof(void*), "");
-static_assert(alignof(fbl::atomic<const void*>) == alignof(const void*), "");
-static_assert(alignof(fbl::atomic<volatile void*>) == alignof(volatile void*), "");
-static_assert(alignof(fbl::atomic<const volatile void*>) == alignof(const volatile void*), "");
-static_assert(alignof(fbl::atomic<int*>) == alignof(int*), "");
-static_assert(alignof(fbl::atomic<const int*>) == alignof(const int*), "");
-static_assert(alignof(fbl::atomic<volatile int*>) == alignof(volatile int*), "");
-static_assert(alignof(fbl::atomic<const volatile int*>) == alignof(const volatile int*), "");
-static_assert(alignof(fbl::atomic<S*>) == alignof(S*), "");
-static_assert(alignof(fbl::atomic<const S*>) == alignof(const S*), "");
-static_assert(alignof(fbl::atomic<volatile S*>) == alignof(volatile S*), "");
-static_assert(alignof(fbl::atomic<const volatile S*>) == alignof(const volatile S*), "");
-static_assert(alignof(fbl::atomic<function_pointer>) == alignof(function_pointer), "");
-
-static_assert(fbl::is_standard_layout<fbl::atomic<char>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<signed char>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<unsigned char>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<short>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<unsigned short>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<int>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<unsigned int>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<long>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<unsigned long>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<long long>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<unsigned long long>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<bool>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<void*>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<const void*>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<volatile void*>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<const volatile void*>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<void*>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<const int*>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<volatile int*>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<const volatile int*>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<S*>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<const S*>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<volatile S*>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<const volatile S*>>::value, "");
-static_assert(fbl::is_standard_layout<fbl::atomic<function_pointer>>::value, "");
-
-bool atomic_fence_test() {
-    BEGIN_TEST;
-
-    for (const auto& order : orders) {
-        atomic_thread_fence(order);
-        atomic_signal_fence(order);
-    }
-
-    END_TEST;
-}
-
-bool atomic_init_test() {
-    BEGIN_TEST;
-
-    fbl::atomic_uint32_t atomic1;
-    fbl::atomic_init(&atomic1, 1u);
-    EXPECT_EQ(1u, atomic1.load());
-
-    fbl::atomic_uint32_t atomic2;
-    volatile fbl::atomic_uint32_t* vatomic2 = &atomic2;
-    fbl::atomic_init(vatomic2, 2u);
-    EXPECT_EQ(2u, atomic2.load());
-
-    END_TEST;
-}
-
-} // namespace
-
-BEGIN_TEST_CASE(atomic_tests)
-RUN_NAMED_TEST("Atomic explicit declarations test", atomic_explicit_declarations_test)
-RUN_NAMED_TEST("Atomic using declarations test", atomic_using_declarations_test)
-RUN_NAMED_TEST("Atomic won't compile test", atomic_wont_compile_test)
-RUN_NAMED_TEST("Atomic math test", atomic_math_test)
-RUN_NAMED_TEST("Atomic pointer math test", atomic_pointer_math_test)
-RUN_NAMED_TEST("Atomic load/store test", atomic_load_store_test)
-RUN_NAMED_TEST("Atomic exchange test", atomic_exchange_test)
-RUN_NAMED_TEST("Atomic compare-exchange test", atomic_compare_exchange_test)
-RUN_NAMED_TEST("Atomic fence test", atomic_fence_test)
-RUN_NAMED_TEST("Atomic init test", atomic_init_test)
-END_TEST_CASE(atomic_tests);
diff --git a/system/utest/fbl/include/fbl/tests/intrusive_containers/objects.h b/system/utest/fbl/include/fbl/tests/intrusive_containers/objects.h
index 2af11d5..0103d43 100644
--- a/system/utest/fbl/include/fbl/tests/intrusive_containers/objects.h
+++ b/system/utest/fbl/include/fbl/tests/intrusive_containers/objects.h
@@ -5,12 +5,12 @@
 #pragma once
 
 #include <fbl/alloc_checker.h>
-#include <fbl/atomic.h>
 #include <fbl/ref_counted.h>
 #include <fbl/ref_ptr.h>
 #include <fbl/unique_ptr.h>
 #include <unittest/unittest.h>
 
+#include <atomic>
 #include <memory>
 #include <utility>
 
@@ -77,7 +77,7 @@
     static size_t delete_count() { return delete_count_.load(); }
 
 private:
-    static fbl::atomic<size_t> delete_count_;
+    static std::atomic<size_t> delete_count_;
 };
 
 // Container test objects are objects which...
diff --git a/system/utest/fbl/include/fbl/tests/intrusive_containers/test_thunks.h b/system/utest/fbl/include/fbl/tests/intrusive_containers/test_thunks.h
index 2c62741..38fa739 100644
--- a/system/utest/fbl/include/fbl/tests/intrusive_containers/test_thunks.h
+++ b/system/utest/fbl/include/fbl/tests/intrusive_containers/test_thunks.h
@@ -89,7 +89,7 @@
 // tested container type.  If new static storage is needed for testing custom
 // pointer type or custom deleters, it should be declared here.
 #define DECLARE_TEST_STORAGE(_container_type) \
-    template <> fbl::atomic<size_t> TestCustomDeleter< \
+    template <> std::atomic<size_t> TestCustomDeleter< \
         StdUniquePtrCustomDeleter ## _container_type ## TestObj \
     >::delete_count_{0}
 
diff --git a/system/utest/fbl/rules.mk b/system/utest/fbl/rules.mk
index 2fac772..766377c 100644
--- a/system/utest/fbl/rules.mk
+++ b/system/utest/fbl/rules.mk
@@ -11,7 +11,6 @@
 fbl_common_tests := \
     $(LOCAL_DIR)/algorithm_tests.cpp \
     $(LOCAL_DIR)/array_tests.cpp \
-    $(LOCAL_DIR)/atomic_tests.cpp \
     $(LOCAL_DIR)/auto_call_tests.cpp \
     $(LOCAL_DIR)/forward_tests.cpp \
     $(LOCAL_DIR)/function_tests.cpp \