Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/CMakeLists.txt1
-rw-r--r--intern/atomic/CMakeLists.txt38
-rw-r--r--intern/atomic/tests/atomic_test.cc883
3 files changed, 922 insertions, 0 deletions
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index c1792a312b2..dbd939e64b7 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -19,6 +19,7 @@
# ***** END GPL LICENSE BLOCK *****
# add_subdirectory(atomic) # header only
+add_subdirectory(atomic)
add_subdirectory(clog)
add_subdirectory(ghost)
add_subdirectory(guardedalloc)
diff --git a/intern/atomic/CMakeLists.txt b/intern/atomic/CMakeLists.txt
new file mode 100644
index 00000000000..afcafc4c8ab
--- /dev/null
+++ b/intern/atomic/CMakeLists.txt
@@ -0,0 +1,38 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2020, Blender Foundation
+# All rights reserved.
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+)
+
+set(INC_SYS
+)
+
+if(WITH_GTESTS)
+ set(TEST_SRC
+ tests/atomic_test.cc
+ )
+ set(TEST_INC
+ )
+ set(TEST_LIB
+ )
+ include(GTestTesting)
+ blender_add_test_executable(atomic "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB};${TEST_LIB}")
+endif()
diff --git a/intern/atomic/tests/atomic_test.cc b/intern/atomic/tests/atomic_test.cc
new file mode 100644
index 00000000000..f52422d0d30
--- /dev/null
+++ b/intern/atomic/tests/atomic_test.cc
@@ -0,0 +1,883 @@
+/* Apache License, Version 2.0 */
+
+#include <limits>
+
+#include "atomic_ops.h"
+#include "testing/testing.h"
+
+#ifdef __GNUC__
+# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */
+# pragma GCC diagnostic error "-Wsign-compare"
+# endif
+# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408
+# pragma GCC diagnostic error "-Wsign-conversion"
+# endif
+#endif
+
+/* NOTE: it is suboptimal to duplicate same check as in API, but this check is
+ * planned to be removed, making it so 64bit intrinsics are available on 32bit
+ * platforms. */
+#if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8)
+
+/* -------------------------------------------------------------------- */
+/** \name 64 bit unsigned int atomics
+ * \{ */
+
+TEST(atomic, atomic_add_and_fetch_uint64)
+{
+ {
+ uint64_t value = 1;
+ EXPECT_EQ(atomic_add_and_fetch_uint64(&value, 2), 3);
+ EXPECT_EQ(value, 3);
+ }
+
+ {
+ uint64_t value = 0x1020304050607080;
+ EXPECT_EQ(atomic_add_and_fetch_uint64(&value, 0x0807060504030201), 0x1827364554637281);
+ EXPECT_EQ(value, 0x1827364554637281);
+ }
+
+ {
+ uint64_t value = 0x9020304050607080;
+ EXPECT_EQ(atomic_add_and_fetch_uint64(&value, 0x0807060504030201), 0x9827364554637281);
+ EXPECT_EQ(value, 0x9827364554637281);
+ }
+}
+
+TEST(atomic, atomic_sub_and_fetch_uint64)
+{
+ {
+ uint64_t value = 3;
+ EXPECT_EQ(atomic_sub_and_fetch_uint64(&value, 2), 1);
+ EXPECT_EQ(value, 1);
+ }
+
+ {
+ uint64_t value = 0x1827364554637281;
+ EXPECT_EQ(atomic_sub_and_fetch_uint64(&value, 0x0807060504030201), 0x1020304050607080);
+ EXPECT_EQ(value, 0x1020304050607080);
+ }
+
+ {
+ uint64_t value = 0x9827364554637281;
+ EXPECT_EQ(atomic_sub_and_fetch_uint64(&value, 0x0807060504030201), 0x9020304050607080);
+ EXPECT_EQ(value, 0x9020304050607080);
+ }
+
+ {
+ uint64_t value = 1;
+ EXPECT_EQ(atomic_sub_and_fetch_uint64(&value, 2), 0xffffffffffffffff);
+ EXPECT_EQ(value, 0xffffffffffffffff);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_add_uint64)
+{
+ {
+ uint64_t value = 1;
+ EXPECT_EQ(atomic_fetch_and_add_uint64(&value, 2), 1);
+ EXPECT_EQ(value, 3);
+ }
+
+ {
+ uint64_t value = 0x1020304050607080;
+ EXPECT_EQ(atomic_fetch_and_add_uint64(&value, 0x0807060504030201), 0x1020304050607080);
+ EXPECT_EQ(value, 0x1827364554637281);
+ }
+
+ {
+ uint64_t value = 0x9020304050607080;
+ EXPECT_EQ(atomic_fetch_and_add_uint64(&value, 0x0807060504030201), 0x9020304050607080);
+ EXPECT_EQ(value, 0x9827364554637281);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_sub_uint64)
+{
+ {
+ uint64_t value = 3;
+ EXPECT_EQ(atomic_fetch_and_sub_uint64(&value, 2), 3);
+ EXPECT_EQ(value, 1);
+ }
+
+ {
+ uint64_t value = 0x1827364554637281;
+ EXPECT_EQ(atomic_fetch_and_sub_uint64(&value, 0x0807060504030201), 0x1827364554637281);
+ EXPECT_EQ(value, 0x1020304050607080);
+ }
+
+ {
+ uint64_t value = 0x9827364554637281;
+ EXPECT_EQ(atomic_fetch_and_sub_uint64(&value, 0x0807060504030201), 0x9827364554637281);
+ EXPECT_EQ(value, 0x9020304050607080);
+ }
+
+ {
+ uint64_t value = 1;
+ EXPECT_EQ(atomic_fetch_and_sub_uint64(&value, 2), 1);
+ EXPECT_EQ(value, 0xffffffffffffffff);
+ }
+}
+
+TEST(atomic, atomic_cas_uint64)
+{
+ {
+ uint64_t value = 1;
+ EXPECT_EQ(atomic_cas_uint64(&value, 1, 2), 1);
+ EXPECT_EQ(value, 2);
+ }
+
+ {
+ uint64_t value = 1;
+ EXPECT_EQ(atomic_cas_uint64(&value, 2, 3), 1);
+ EXPECT_EQ(value, 1);
+ }
+
+ {
+ uint64_t value = 0x1234567890abcdef;
+ EXPECT_EQ(atomic_cas_uint64(&value, 0x1234567890abcdef, 0xfedcba0987654321),
+ 0x1234567890abcdef);
+ EXPECT_EQ(value, 0xfedcba0987654321);
+ }
+
+ {
+ uint64_t value = 0x1234567890abcdef;
+ EXPECT_EQ(atomic_cas_uint64(&value, 0xdeadbeefefefefef, 0xfedcba0987654321),
+ 0x1234567890abcdef);
+ EXPECT_EQ(value, 0x1234567890abcdef);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name 64 bit signed int atomics
+ * \{ */
+
+TEST(atomic, atomic_add_and_fetch_int64)
+{
+ {
+ int64_t value = 1;
+ EXPECT_EQ(atomic_add_and_fetch_int64(&value, 2), 3);
+ EXPECT_EQ(value, 3);
+ }
+
+ {
+ int64_t value = 0x1020304050607080;
+ EXPECT_EQ(atomic_add_and_fetch_int64(&value, 0x0807060504030201), 0x1827364554637281);
+ EXPECT_EQ(value, 0x1827364554637281);
+ }
+
+ {
+ int64_t value = -0x1020304050607080;
+ EXPECT_EQ(atomic_add_and_fetch_int64(&value, -0x0807060504030201), -0x1827364554637281);
+ EXPECT_EQ(value, -0x1827364554637281);
+ }
+}
+
+TEST(atomic, atomic_sub_and_fetch_int64)
+{
+ {
+ int64_t value = 3;
+ EXPECT_EQ(atomic_sub_and_fetch_int64(&value, 2), 1);
+ EXPECT_EQ(value, 1);
+ }
+
+ {
+ int64_t value = 0x1827364554637281;
+ EXPECT_EQ(atomic_sub_and_fetch_int64(&value, 0x0807060504030201), 0x1020304050607080);
+ EXPECT_EQ(value, 0x1020304050607080);
+ }
+
+ {
+ int64_t value = -0x1827364554637281;
+ EXPECT_EQ(atomic_sub_and_fetch_int64(&value, -0x0807060504030201), -0x1020304050607080);
+ EXPECT_EQ(value, -0x1020304050607080);
+ }
+
+ {
+ int64_t value = 1;
+ EXPECT_EQ(atomic_sub_and_fetch_int64(&value, 2), -1);
+ EXPECT_EQ(value, -1);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_add_int64)
+{
+ {
+ int64_t value = 1;
+ EXPECT_EQ(atomic_fetch_and_add_int64(&value, 2), 1);
+ EXPECT_EQ(value, 3);
+ }
+
+ {
+ int64_t value = 0x1020304050607080;
+ EXPECT_EQ(atomic_fetch_and_add_int64(&value, 0x0807060504030201), 0x1020304050607080);
+ EXPECT_EQ(value, 0x1827364554637281);
+ }
+
+ {
+ int64_t value = -0x1020304050607080;
+ EXPECT_EQ(atomic_fetch_and_add_int64(&value, -0x0807060504030201), -0x1020304050607080);
+ EXPECT_EQ(value, -0x1827364554637281);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_sub_int64)
+{
+ {
+ int64_t value = 3;
+ EXPECT_EQ(atomic_fetch_and_sub_int64(&value, 2), 3);
+ EXPECT_EQ(value, 1);
+ }
+
+ {
+ int64_t value = 0x1827364554637281;
+ EXPECT_EQ(atomic_fetch_and_sub_int64(&value, 0x0807060504030201), 0x1827364554637281);
+ EXPECT_EQ(value, 0x1020304050607080);
+ }
+
+ {
+ int64_t value = -0x1827364554637281;
+ EXPECT_EQ(atomic_fetch_and_sub_int64(&value, -0x0807060504030201), -0x1827364554637281);
+ EXPECT_EQ(value, -0x1020304050607080);
+ }
+
+ {
+ int64_t value = 1;
+ EXPECT_EQ(atomic_fetch_and_sub_int64(&value, 2), 1);
+ EXPECT_EQ(value, -1);
+ }
+}
+
+TEST(atomic, atomic_cas_int64)
+{
+ {
+ int64_t value = 1;
+ EXPECT_EQ(atomic_cas_int64(&value, 1, 2), 1);
+ EXPECT_EQ(value, 2);
+ }
+
+ {
+ int64_t value = 1;
+ EXPECT_EQ(atomic_cas_int64(&value, 2, 3), 1);
+ EXPECT_EQ(value, 1);
+ }
+
+ // 0xfedcba0987654321 is -0x012345f6789abcdf
+ // 0xdeadbeefefefefef is -0x2152411010101011
+
+ {
+ int64_t value = 0x1234567890abcdef;
+ EXPECT_EQ(atomic_cas_int64(&value, 0x1234567890abcdef, -0x012345f6789abcdf),
+ 0x1234567890abcdef);
+ EXPECT_EQ(value, -0x012345f6789abcdf);
+ }
+
+ {
+ int64_t value = 0x1234567890abcdef;
+ EXPECT_EQ(atomic_cas_int64(&value, 0x2152411010101011, -0x012345f6789abcdf),
+ 0x1234567890abcdef);
+ EXPECT_EQ(value, 0x1234567890abcdef);
+ }
+}
+
+/** \} */
+
+#endif
+
+/* -------------------------------------------------------------------- */
+/** \name 32 bit unsigned int atomics
+ * \{ */
+
+TEST(atomic, atomic_add_and_fetch_uint32)
+{
+ {
+ uint32_t value = 1;
+ EXPECT_EQ(atomic_add_and_fetch_uint32(&value, 2), 3);
+ EXPECT_EQ(value, 3);
+ }
+
+ {
+ uint32_t value = 0x10203040;
+ EXPECT_EQ(atomic_add_and_fetch_uint32(&value, 0x04030201), 0x14233241);
+ EXPECT_EQ(value, 0x14233241);
+ }
+
+ {
+ uint32_t value = 0x90203040;
+ EXPECT_EQ(atomic_add_and_fetch_uint32(&value, 0x04030201), 0x94233241);
+ EXPECT_EQ(value, 0x94233241);
+ }
+}
+
+TEST(atomic, atomic_sub_and_fetch_uint32)
+{
+ {
+ uint32_t value = 3;
+ EXPECT_EQ(atomic_sub_and_fetch_uint32(&value, 2), 1);
+ EXPECT_EQ(value, 1);
+ }
+
+ {
+ uint32_t value = 0x14233241;
+ EXPECT_EQ(atomic_sub_and_fetch_uint32(&value, 0x04030201), 0x10203040);
+ EXPECT_EQ(value, 0x10203040);
+ }
+
+ {
+ uint32_t value = 0x94233241;
+ EXPECT_EQ(atomic_sub_and_fetch_uint32(&value, 0x04030201), 0x90203040);
+ EXPECT_EQ(value, 0x90203040);
+ }
+
+ {
+ uint32_t value = 1;
+ EXPECT_EQ(atomic_sub_and_fetch_uint32(&value, 2), 0xffffffff);
+ EXPECT_EQ(value, 0xffffffff);
+ }
+}
+
+TEST(atomic, atomic_cas_uint32)
+{
+ {
+ uint32_t value = 1;
+ EXPECT_EQ(atomic_cas_uint32(&value, 1, 2), 1);
+ EXPECT_EQ(value, 2);
+ }
+
+ {
+ uint32_t value = 1;
+ EXPECT_EQ(atomic_cas_uint32(&value, 2, 3), 1);
+ EXPECT_EQ(value, 1);
+ }
+
+ {
+ uint32_t value = 0x12345678;
+ EXPECT_EQ(atomic_cas_uint32(&value, 0x12345678, 0x87654321), 0x12345678);
+ EXPECT_EQ(value, 0x87654321);
+ }
+
+ {
+ uint32_t value = 0x12345678;
+ EXPECT_EQ(atomic_cas_uint32(&value, 0xdeadbeef, 0x87654321), 0x12345678);
+ EXPECT_EQ(value, 0x12345678);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_add_uint32)
+{
+ {
+ uint32_t value = 1;
+ EXPECT_EQ(atomic_fetch_and_add_uint32(&value, 2), 1);
+ EXPECT_EQ(value, 3);
+ }
+
+ {
+ uint32_t value = 0x10203040;
+ EXPECT_EQ(atomic_fetch_and_add_uint32(&value, 0x04030201), 0x10203040);
+ EXPECT_EQ(value, 0x14233241);
+ }
+
+ {
+ uint32_t value = 0x90203040;
+ EXPECT_EQ(atomic_fetch_and_add_uint32(&value, 0x04030201), 0x90203040);
+ EXPECT_EQ(value, 0x94233241);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_or_uint32)
+{
+ {
+ uint32_t value = 12;
+ EXPECT_EQ(atomic_fetch_and_or_uint32(&value, 5), 12);
+ EXPECT_EQ(value, 13);
+ }
+
+ {
+ uint32_t value = 0x12345678;
+ EXPECT_EQ(atomic_fetch_and_or_uint32(&value, 0x87654321), 0x12345678);
+ EXPECT_EQ(value, 0x97755779);
+ }
+
+ {
+ uint32_t value = 0x92345678;
+ EXPECT_EQ(atomic_fetch_and_or_uint32(&value, 0x87654321), 0x92345678);
+ EXPECT_EQ(value, 0x97755779);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_and_uint32)
+{
+ {
+ uint32_t value = 12;
+ EXPECT_EQ(atomic_fetch_and_and_uint32(&value, 5), 12);
+ EXPECT_EQ(value, 4);
+ }
+
+ {
+ uint32_t value = 0x12345678;
+ EXPECT_EQ(atomic_fetch_and_and_uint32(&value, 0x87654321), 0x12345678);
+ EXPECT_EQ(value, 0x02244220);
+ }
+
+ {
+ uint32_t value = 0x92345678;
+ EXPECT_EQ(atomic_fetch_and_and_uint32(&value, 0x87654321), 0x92345678);
+ EXPECT_EQ(value, 0x82244220);
+ }
+}
+
+/** \} */
+
+/** \name 32 bit signed int atomics
+ * \{ */
+
+TEST(atomic, atomic_add_and_fetch_int32)
+{
+ {
+ int32_t value = 1;
+ EXPECT_EQ(atomic_add_and_fetch_int32(&value, 2), 3);
+ EXPECT_EQ(value, 3);
+ }
+
+ {
+ int32_t value = 0x10203040;
+ EXPECT_EQ(atomic_add_and_fetch_int32(&value, 0x04030201), 0x14233241);
+ EXPECT_EQ(value, 0x14233241);
+ }
+
+ {
+ int32_t value = -0x10203040;
+ EXPECT_EQ(atomic_add_and_fetch_int32(&value, -0x04030201), -0x14233241);
+ EXPECT_EQ(value, -0x14233241);
+ }
+}
+
+TEST(atomic, atomic_sub_and_fetch_int32)
+{
+ {
+ int32_t value = 3;
+ EXPECT_EQ(atomic_sub_and_fetch_int32(&value, 2), 1);
+ EXPECT_EQ(value, 1);
+ }
+
+ {
+ int32_t value = 0x14233241;
+ EXPECT_EQ(atomic_sub_and_fetch_int32(&value, 0x04030201), 0x10203040);
+ EXPECT_EQ(value, 0x10203040);
+ }
+
+ {
+ int32_t value = -0x14233241;
+ EXPECT_EQ(atomic_sub_and_fetch_int32(&value, -0x04030201), -0x10203040);
+ EXPECT_EQ(value, -0x10203040);
+ }
+
+ {
+ int32_t value = 1;
+ EXPECT_EQ(atomic_sub_and_fetch_int32(&value, 2), 0xffffffff);
+ EXPECT_EQ(value, 0xffffffff);
+ }
+}
+
+TEST(atomic, atomic_cas_int32)
+{
+ {
+ int32_t value = 1;
+ EXPECT_EQ(atomic_cas_int32(&value, 1, 2), 1);
+ EXPECT_EQ(value, 2);
+ }
+
+ {
+ int32_t value = 1;
+ EXPECT_EQ(atomic_cas_int32(&value, 2, 3), 1);
+ EXPECT_EQ(value, 1);
+ }
+
+ // 0x87654321 is -0x789abcdf
+ // 0xdeadbeef is -0x21524111
+
+ {
+ int32_t value = 0x12345678;
+ EXPECT_EQ(atomic_cas_int32(&value, 0x12345678, -0x789abcdf), 0x12345678);
+ EXPECT_EQ(value, -0x789abcdf);
+ }
+
+ {
+ int32_t value = 0x12345678;
+ EXPECT_EQ(atomic_cas_int32(&value, -0x21524111, -0x789abcdf), 0x12345678);
+ EXPECT_EQ(value, 0x12345678);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_add_int32)
+{
+ {
+ int32_t value = 1;
+ EXPECT_EQ(atomic_fetch_and_add_int32(&value, 2), 1);
+ EXPECT_EQ(value, 3);
+ }
+
+ {
+ int32_t value = 0x10203040;
+ EXPECT_EQ(atomic_fetch_and_add_int32(&value, 0x04030201), 0x10203040);
+ EXPECT_EQ(value, 0x14233241);
+ }
+
+ {
+ int32_t value = -0x10203040;
+ EXPECT_EQ(atomic_fetch_and_add_int32(&value, -0x04030201), -0x10203040);
+ EXPECT_EQ(value, -0x14233241);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_or_int32)
+{
+ {
+ int32_t value = 12;
+ EXPECT_EQ(atomic_fetch_and_or_int32(&value, 5), 12);
+ EXPECT_EQ(value, 13);
+ }
+
+ // 0x87654321 is -0x789abcdf
+
+ {
+ int32_t value = 0x12345678;
+ EXPECT_EQ(atomic_fetch_and_or_int32(&value, -0x789abcdf), 0x12345678);
+ EXPECT_EQ(value, 0x97755779);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_and_int32)
+{
+ {
+ int32_t value = 12;
+ EXPECT_EQ(atomic_fetch_and_and_int32(&value, 5), 12);
+ EXPECT_EQ(value, 4);
+ }
+
+ {
+ int32_t value = 0x12345678;
+ EXPECT_EQ(atomic_fetch_and_and_int32(&value, -0x789abcdf), 0x12345678);
+ EXPECT_EQ(value, 0x02244220);
+ }
+}
+
+/** \} */
+
+/** \name 8 bit unsigned int atomics
+ * \{ */
+
+TEST(atomic, atomic_fetch_and_or_uint8)
+{
+ {
+ uint8_t value = 12;
+ EXPECT_EQ(atomic_fetch_and_or_uint8(&value, 5), 12);
+ EXPECT_EQ(value, 13);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_and_uint8)
+{
+ {
+ uint8_t value = 12;
+ EXPECT_EQ(atomic_fetch_and_and_uint8(&value, 5), 12);
+ EXPECT_EQ(value, 4);
+ }
+}
+
+/** \} */
+
+/** \name 8 bit signed int atomics
+ * \{ */
+
+TEST(atomic, atomic_fetch_and_or_int8)
+{
+ {
+ int8_t value = 12;
+ EXPECT_EQ(atomic_fetch_and_or_int8(&value, 5), 12);
+ EXPECT_EQ(value, 13);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_and_int8)
+{
+ {
+ int8_t value = 12;
+ EXPECT_EQ(atomic_fetch_and_and_int8(&value, 5), 12);
+ EXPECT_EQ(value, 4);
+ }
+}
+
+/** \} */
+
+/** \name char aliases
+ * \{ */
+
+TEST(atomic, atomic_fetch_and_or_char)
+{
+ {
+ char value = 12;
+ EXPECT_EQ(atomic_fetch_and_or_char(&value, 5), 12);
+ EXPECT_EQ(value, 13);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_and_char)
+{
+ {
+ char value = 12;
+ EXPECT_EQ(atomic_fetch_and_and_char(&value, 5), 12);
+ EXPECT_EQ(value, 4);
+ }
+}
+
+/** \} */
+
+/** \name size_t aliases
+ * \{ */
+
+TEST(atomic, atomic_add_and_fetch_z)
+{
+ /* Make sure alias is implemented. */
+ {
+ size_t value = 1;
+ EXPECT_EQ(atomic_add_and_fetch_z(&value, 2), 3);
+ EXPECT_EQ(value, 3);
+ }
+
+ /* Make sure alias is using proper bitness. */
+ {
+ const size_t size_t_max = std::numeric_limits<size_t>::max();
+ size_t value = size_t_max - 10;
+ EXPECT_EQ(atomic_add_and_fetch_z(&value, 2), size_t_max - 8);
+ EXPECT_EQ(value, size_t_max - 8);
+ }
+}
+
+TEST(atomic, atomic_sub_and_fetch_z)
+{
+ /* Make sure alias is implemented. */
+ {
+ size_t value = 3;
+ EXPECT_EQ(atomic_sub_and_fetch_z(&value, 2), 1);
+ EXPECT_EQ(value, 1);
+ }
+
+ /* Make sure alias is using proper bitness. */
+ {
+ const size_t size_t_max = std::numeric_limits<size_t>::max();
+ size_t value = size_t_max - 10;
+ EXPECT_EQ(atomic_sub_and_fetch_z(&value, 2), size_t_max - 12);
+ EXPECT_EQ(value, size_t_max - 12);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_add_z)
+{
+ /* Make sure alias is implemented. */
+ {
+ size_t value = 1;
+ EXPECT_EQ(atomic_fetch_and_add_z(&value, 2), 1);
+ EXPECT_EQ(value, 3);
+ }
+
+ /* Make sure alias is using proper bitness. */
+ {
+ const size_t size_t_max = std::numeric_limits<size_t>::max();
+ size_t value = size_t_max - 10;
+ EXPECT_EQ(atomic_fetch_and_add_z(&value, 2), size_t_max - 10);
+ EXPECT_EQ(value, size_t_max - 8);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_sub_z)
+{
+ /* Make sure alias is implemented. */
+ {
+ size_t value = 3;
+ EXPECT_EQ(atomic_fetch_and_sub_z(&value, 2), 3);
+ EXPECT_EQ(value, 1);
+ }
+
+ /* Make sure alias is using proper bitness. */
+ {
+ const size_t size_t_max = std::numeric_limits<size_t>::max();
+ size_t value = size_t_max - 10;
+ EXPECT_EQ(atomic_fetch_and_sub_z(&value, 2), size_t_max - 10);
+ EXPECT_EQ(value, size_t_max - 12);
+ }
+}
+
+TEST(atomic, atomic_cas_z)
+{
+ /* Make sure alias is implemented. */
+ {
+ size_t value = 1;
+ EXPECT_EQ(atomic_cas_z(&value, 1, 2), 1);
+ EXPECT_EQ(value, 2);
+ }
+
+ /* Make sure alias is using proper bitness. */
+ {
+ const size_t size_t_max = std::numeric_limits<size_t>::max();
+ size_t value = 1;
+ EXPECT_EQ(atomic_cas_z(&value, 1, size_t_max), 1);
+ EXPECT_EQ(value, size_t_max);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_update_max_z)
+{
+ const size_t size_t_max = std::numeric_limits<size_t>::max();
+
+ size_t value = 12;
+
+ EXPECT_EQ(atomic_fetch_and_update_max_z(&value, 8), 12);
+ EXPECT_EQ(value, 12);
+
+ EXPECT_EQ(atomic_fetch_and_update_max_z(&value, 24), 12);
+ EXPECT_EQ(value, 24);
+
+ EXPECT_EQ(atomic_fetch_and_update_max_z(&value, size_t_max), 24);
+ EXPECT_EQ(value, size_t_max);
+}
+
+/** \} */
+
+/** \name unsigned int aliases
+ * \{ */
+
+TEST(atomic, atomic_add_and_fetch_u)
+{
+ /* Make sure alias is implemented. */
+ {
+ unsigned int value = 1;
+ EXPECT_EQ(atomic_add_and_fetch_u(&value, 2), 3);
+ EXPECT_EQ(value, 3);
+ }
+
+ /* Make sure alias is using proper bitness. */
+ {
+ const unsigned int uint_max = std::numeric_limits<unsigned int>::max();
+ unsigned int value = uint_max - 10;
+ EXPECT_EQ(atomic_add_and_fetch_u(&value, 2), uint_max - 8);
+ EXPECT_EQ(value, uint_max - 8);
+ }
+}
+
+TEST(atomic, atomic_sub_and_fetch_u)
+{
+ /* Make sure alias is implemented. */
+ {
+ unsigned int value = 3;
+ EXPECT_EQ(atomic_sub_and_fetch_u(&value, 2), 1);
+ EXPECT_EQ(value, 1);
+ }
+
+ /* Make sure alias is using proper bitness. */
+ {
+ const unsigned int uint_max = std::numeric_limits<unsigned int>::max();
+ unsigned int value = uint_max - 10;
+ EXPECT_EQ(atomic_sub_and_fetch_u(&value, 2), uint_max - 12);
+ EXPECT_EQ(value, uint_max - 12);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_add_u)
+{
+ /* Make sure alias is implemented. */
+ {
+ unsigned int value = 1;
+ EXPECT_EQ(atomic_fetch_and_add_u(&value, 2), 1);
+ EXPECT_EQ(value, 3);
+ }
+
+ /* Make sure alias is using proper bitness. */
+ {
+ const unsigned int uint_max = std::numeric_limits<unsigned int>::max();
+ unsigned int value = uint_max - 10;
+ EXPECT_EQ(atomic_fetch_and_add_u(&value, 2), uint_max - 10);
+ EXPECT_EQ(value, uint_max - 8);
+ }
+}
+
+TEST(atomic, atomic_fetch_and_sub_u)
+{
+ /* Make sure alias is implemented. */
+ {
+ unsigned int value = 3;
+ EXPECT_EQ(atomic_fetch_and_sub_u(&value, 2), 3);
+ EXPECT_EQ(value, 1);
+ }
+
+ /* Make sure alias is using proper bitness. */
+ {
+ const unsigned int uint_max = std::numeric_limits<unsigned int>::max();
+ unsigned int value = uint_max - 10;
+ EXPECT_EQ(atomic_fetch_and_sub_u(&value, 2), uint_max - 10);
+ EXPECT_EQ(value, uint_max - 12);
+ }
+}
+
+TEST(atomic, atomic_cas_u)
+{
+ /* Make sure alias is implemented. */
+ {
+ unsigned int value = 1;
+ EXPECT_EQ(atomic_cas_u(&value, 1, 2), 1);
+ EXPECT_EQ(value, 2);
+ }
+
+ /* Make sure alias is using proper bitness. */
+ {
+ const unsigned int uint_max = std::numeric_limits<unsigned int>::max();
+ unsigned int value = 1;
+ EXPECT_EQ(atomic_cas_u(&value, 1, uint_max), 1);
+ EXPECT_EQ(value, uint_max);
+ }
+}
+
+/** \} */
+
+/** \name pointer aliases
+ * \{ */
+
+#define INT_AS_PTR(a) reinterpret_cast<void *>((a))
+
+TEST(atomic, atomic_cas_ptr)
+{
+ {
+ void *value = INT_AS_PTR(0x7f);
+ EXPECT_EQ(atomic_cas_ptr(&value, INT_AS_PTR(0x7f), INT_AS_PTR(0xef)), INT_AS_PTR(0x7f));
+ EXPECT_EQ(value, INT_AS_PTR(0xef));
+ }
+}
+
+#undef INT_AS_PTR
+
+/** \} */
+
+/** \name floating point atomics
+ * \{ */
+
+TEST(atomic, atomic_cas_float)
+{
+ {
+ float value = 1.234f;
+ EXPECT_EQ(atomic_cas_float(&value, 1.234f, 2.71f), 1.234f);
+ EXPECT_EQ(value, 2.71f);
+ }
+}
+
+TEST(atomic, atomic_add_and_fetch_fl)
+{
+ {
+ float value = 1.23f;
+ EXPECT_NEAR(atomic_add_and_fetch_fl(&value, 2.71f), 3.94f, 1e-8f);
+ EXPECT_NEAR(value, 3.94f, 1e-8f);
+ }
+}
+
+/** \} */