1e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes/*
2e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes * Copyright (C) 2014 The Android Open Source Project
3e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes *
4e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes * you may not use this file except in compliance with the License.
6e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes * You may obtain a copy of the License at
7e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes *
8e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes *
10e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes * Unless required by applicable law or agreed to in writing, software
11e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes * See the License for the specific language governing permissions and
14e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes * limitations under the License.
15e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes */
16e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
17e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes#include <stdatomic.h>
18c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm#include <gtest/gtest.h>
19c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm#include <pthread.h>
20c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm#include <stdint.h>
21e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
22e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott HughesTEST(stdatomic, LOCK_FREE) {
23e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(ATOMIC_BOOL_LOCK_FREE);
24e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(ATOMIC_CHAR16_T_LOCK_FREE);
25e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(ATOMIC_CHAR32_T_LOCK_FREE);
26e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(ATOMIC_CHAR_LOCK_FREE);
27e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(ATOMIC_INT_LOCK_FREE);
28e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(ATOMIC_LLONG_LOCK_FREE);
29e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(ATOMIC_LONG_LOCK_FREE);
30e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(ATOMIC_POINTER_LOCK_FREE);
31e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(ATOMIC_SHORT_LOCK_FREE);
32e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(ATOMIC_WCHAR_T_LOCK_FREE);
33e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes}
34e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
35e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott HughesTEST(stdatomic, init) {
36e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_int v = ATOMIC_VAR_INIT(123);
37e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(123, atomic_load(&v));
38e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
39e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_init(&v, 456);
40e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(456, atomic_load(&v));
41e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
42e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_flag f = ATOMIC_FLAG_INIT;
43e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_FALSE(atomic_flag_test_and_set(&f));
44e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes}
45e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
46e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott HughesTEST(stdatomic, atomic_thread_fence) {
47e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_thread_fence(memory_order_relaxed);
48e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_thread_fence(memory_order_consume);
49e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_thread_fence(memory_order_acquire);
50e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_thread_fence(memory_order_release);
51e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_thread_fence(memory_order_acq_rel);
52e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_thread_fence(memory_order_seq_cst);
53e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes}
54e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
55e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott HughesTEST(stdatomic, atomic_signal_fence) {
56e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_signal_fence(memory_order_relaxed);
57e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_signal_fence(memory_order_consume);
58e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_signal_fence(memory_order_acquire);
59e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_signal_fence(memory_order_release);
60e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_signal_fence(memory_order_acq_rel);
61e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_signal_fence(memory_order_seq_cst);
62e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes}
63e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
64e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott HughesTEST(stdatomic, atomic_is_lock_free) {
65e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_char small;
66e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(atomic_is_lock_free(&small));
679ac60bf82b1f0e316666b862e9924f90caa60342Hans Boehm#if defined(__clang__) || __GNUC_PREREQ(4, 7)
689ac60bf82b1f0e316666b862e9924f90caa60342Hans Boehm  // Otherwise stdatomic.h doesn't handle this.
699ac60bf82b1f0e316666b862e9924f90caa60342Hans Boehm  atomic_intmax_t big;
7034b258dd692951ab2236e134e5520367cda60125Raghu Gandham  // atomic_intmax_t(size = 64) is not lock free on mips32.
7134b258dd692951ab2236e134e5520367cda60125Raghu Gandham#if defined(__mips__) && !defined(__LP64__)
7234b258dd692951ab2236e134e5520367cda60125Raghu Gandham  ASSERT_FALSE(atomic_is_lock_free(&big));
7334b258dd692951ab2236e134e5520367cda60125Raghu Gandham#else
74e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(atomic_is_lock_free(&big));
7534b258dd692951ab2236e134e5520367cda60125Raghu Gandham#endif
769ac60bf82b1f0e316666b862e9924f90caa60342Hans Boehm#endif
77e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes}
78e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
79e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott HughesTEST(stdatomic, atomic_flag) {
80e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_flag f = ATOMIC_FLAG_INIT;
81e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_FALSE(atomic_flag_test_and_set(&f));
82e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(atomic_flag_test_and_set(&f));
83e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
84e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_flag_clear(&f);
85e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
86e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_FALSE(atomic_flag_test_and_set_explicit(&f, memory_order_relaxed));
87e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(atomic_flag_test_and_set_explicit(&f, memory_order_relaxed));
88e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
89e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_flag_clear_explicit(&f, memory_order_relaxed);
90e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_FALSE(atomic_flag_test_and_set_explicit(&f, memory_order_relaxed));
91e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes}
92e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
93e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott HughesTEST(stdatomic, atomic_store) {
94e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_int i;
95e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_store(&i, 123);
96e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(123, atomic_load(&i));
97e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_store_explicit(&i, 123, memory_order_relaxed);
98e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(123, atomic_load_explicit(&i, memory_order_relaxed));
99e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes}
100e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
101e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott HughesTEST(stdatomic, atomic_exchange) {
102e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_int i;
103e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_store(&i, 123);
104e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(123, atomic_exchange(&i, 456));
105e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(456, atomic_exchange_explicit(&i, 123, memory_order_relaxed));
106e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes}
107e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
108e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott HughesTEST(stdatomic, atomic_compare_exchange) {
109e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_int i;
1106b3beb23d666b722deeb81672166766ad28e7340Dan Albert  int expected;
111e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
112e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_store(&i, 123);
1136b3beb23d666b722deeb81672166766ad28e7340Dan Albert  expected = 123;
114e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(atomic_compare_exchange_strong(&i, &expected, 456));
115e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_FALSE(atomic_compare_exchange_strong(&i, &expected, 456));
1166b3beb23d666b722deeb81672166766ad28e7340Dan Albert  ASSERT_EQ(456, expected);
117e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
118e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_store(&i, 123);
1196b3beb23d666b722deeb81672166766ad28e7340Dan Albert  expected = 123;
120e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(atomic_compare_exchange_strong_explicit(&i, &expected, 456, memory_order_relaxed, memory_order_relaxed));
121e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_FALSE(atomic_compare_exchange_strong_explicit(&i, &expected, 456, memory_order_relaxed, memory_order_relaxed));
1226b3beb23d666b722deeb81672166766ad28e7340Dan Albert  ASSERT_EQ(456, expected);
123e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
124e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_store(&i, 123);
1256b3beb23d666b722deeb81672166766ad28e7340Dan Albert  expected = 123;
126e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(atomic_compare_exchange_weak(&i, &expected, 456));
127e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_FALSE(atomic_compare_exchange_weak(&i, &expected, 456));
1286b3beb23d666b722deeb81672166766ad28e7340Dan Albert  ASSERT_EQ(456, expected);
129e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
130e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_store(&i, 123);
1316b3beb23d666b722deeb81672166766ad28e7340Dan Albert  expected = 123;
132e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_TRUE(atomic_compare_exchange_weak_explicit(&i, &expected, 456, memory_order_relaxed, memory_order_relaxed));
133e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_FALSE(atomic_compare_exchange_weak_explicit(&i, &expected, 456, memory_order_relaxed, memory_order_relaxed));
1346b3beb23d666b722deeb81672166766ad28e7340Dan Albert  ASSERT_EQ(456, expected);
135e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes}
136e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
137e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott HughesTEST(stdatomic, atomic_fetch_add) {
138e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_int i = ATOMIC_VAR_INIT(123);
139e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(123, atomic_fetch_add(&i, 1));
140e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(124, atomic_fetch_add_explicit(&i, 1, memory_order_relaxed));
141e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(125, atomic_load(&i));
142e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes}
143e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
144e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott HughesTEST(stdatomic, atomic_fetch_sub) {
145e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_int i = ATOMIC_VAR_INIT(123);
146e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(123, atomic_fetch_sub(&i, 1));
147e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(122, atomic_fetch_sub_explicit(&i, 1, memory_order_relaxed));
148e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(121, atomic_load(&i));
149e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes}
150e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
151e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott HughesTEST(stdatomic, atomic_fetch_or) {
152e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_int i = ATOMIC_VAR_INIT(0x100);
153e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(0x100, atomic_fetch_or(&i, 0x020));
154e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(0x120, atomic_fetch_or_explicit(&i, 0x003, memory_order_relaxed));
155e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(0x123, atomic_load(&i));
156e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes}
157e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
158e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott HughesTEST(stdatomic, atomic_fetch_xor) {
159e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_int i = ATOMIC_VAR_INIT(0x100);
160e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(0x100, atomic_fetch_xor(&i, 0x120));
161e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(0x020, atomic_fetch_xor_explicit(&i, 0x103, memory_order_relaxed));
162e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(0x123, atomic_load(&i));
163e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes}
164e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
165e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott HughesTEST(stdatomic, atomic_fetch_and) {
166e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  atomic_int i = ATOMIC_VAR_INIT(0x123);
167e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(0x123, atomic_fetch_and(&i, 0x00f));
168e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(0x003, atomic_fetch_and_explicit(&i, 0x2, memory_order_relaxed));
169e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes  ASSERT_EQ(0x002, atomic_load(&i));
170e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes}
171e6c57fcb05b0dcbfa8129bb6f7d99093f4819370Elliott Hughes
172c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm// And a rudimentary test of acquire-release memory ordering:
173c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm
174c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehmconstexpr static uint_least32_t BIG = 10000000ul; // Assumed even below.
175c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm
176c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehmstruct three_atomics {
177c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  atomic_uint_least32_t x;
178c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  char a[123];  // Everything in different cache lines,
179c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm                // increase chance of compiler getting alignment wrong.
180c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  atomic_uint_least32_t y;
181c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  char b[4013];
182c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  atomic_uint_least32_t z;
183c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm};
184c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm
185c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm// Very simple acquire/release memory ordering sanity check.
186c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehmstatic void* writer(void* arg) {
187c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  three_atomics* a = reinterpret_cast<three_atomics*>(arg);
188c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  for (uint_least32_t i = 0; i <= BIG; i+=2) {
189c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    atomic_store_explicit(&a->x, i, memory_order_relaxed);
190c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    atomic_store_explicit(&a->z, i, memory_order_relaxed);
191c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    atomic_store_explicit(&a->y, i, memory_order_release);
192c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    atomic_store_explicit(&a->x, i+1, memory_order_relaxed);
193c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    atomic_store_explicit(&a->z, i+1, memory_order_relaxed);
194c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    atomic_store_explicit(&a->y, i+1, memory_order_release);
195c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  }
196c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  return 0;
197c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm}
198c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm
199c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehmstatic void* reader(void* arg) {
200c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  three_atomics* a = reinterpret_cast<three_atomics*>(arg);
201c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  uint_least32_t xval = 0, yval = 0, zval = 0;
202c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  size_t repeat = 0;
203c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  size_t repeat_limit = 1000;
204c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  while (yval != BIG + 1) {
205c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    yval = atomic_load_explicit(&a->y, memory_order_acquire);
206c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    zval = atomic_load_explicit(&a->z, memory_order_relaxed);
207c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    xval = atomic_load_explicit(&a->x, memory_order_relaxed);
208c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    // If we see a given value of y, the immediately preceding
209c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    // stores to z and x, or later ones, should also be visible.
210c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    if (zval < yval) {
211c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm      // Cant just ASSERT, since we are in a non-void function.
212c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm      ADD_FAILURE() << "acquire-release ordering violation: "
213c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm                    << zval << " < " << yval << ", " << xval << "\n";
214c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm      return 0; // Only report once.
215c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    }
216c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    if (xval < yval) {
217c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm      // Cant just ASSERT, since we are in a non-void function.
218c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm      ADD_FAILURE() << "acquire-release ordering violation: "
219c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm                    << xval << " < " << yval << ", " << zval <<  "\n";
220c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm      return 0; // Only report once.
221c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    }
222c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm    if (repeat < repeat_limit) ++repeat;
223c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  }
224c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  // The following assertion is not technically guaranteed to hold.
225c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  // But if it fails to hold, this test was useless, and we have a
226c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  // serious scheduling issue that we should probably know about.
227c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  EXPECT_EQ(repeat, repeat_limit);
228c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  return 0;
229c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm}
230c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm
231c8cf3513ecb265ba3aadc846aa2113290a504c44Hans BoehmTEST(stdatomic, ordering) {
232c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  // Run a memory ordering sanity test.
233c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  void* result;
234c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  three_atomics a;
235c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  atomic_init(&a.x, 0ul);
236c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  atomic_init(&a.y, 0ul);
237c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  atomic_init(&a.z, 0ul);
238c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  pthread_t t1,t2;
239c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  ASSERT_EQ(0, pthread_create(&t1, 0, reader, &a));
240c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  ASSERT_EQ(0, pthread_create(&t2, 0, writer, &a));
241c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  ASSERT_EQ(0, pthread_join(t1, &result));
242c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  EXPECT_EQ(0, result);
243c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  ASSERT_EQ(0, pthread_join(t2, &result));
244c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  EXPECT_EQ(0, result);
245c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  EXPECT_EQ(atomic_load_explicit(&a.x, memory_order_consume), BIG + 1);
246c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  EXPECT_EQ(atomic_load_explicit(&a.y, memory_order_seq_cst), BIG + 1);
247c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm  EXPECT_EQ(atomic_load(&a.z), BIG + 1);
248c8cf3513ecb265ba3aadc846aa2113290a504c44Hans Boehm}
249