1 #include <gtest/gtest.h>
2
3 extern "C" {
4 #include "atomic.h"
5 }
6
7 const static size_t ATOMIC_DATA_MAX = 2;
8 const static int ATOMIC_MAX_THREADS = 20;
9
10 struct atomic_test_s32_s {
11 pthread_t pthread_id;
12 int thread_num;
13 int max_val;
14 atomic_s32_t *data;
15 };
16
atomic_thread(void * context)17 void *atomic_thread(void *context) {
18 struct atomic_test_s32_s *at = (struct atomic_test_s32_s *)context;
19 for (int i = 0; i < at->max_val; i++) {
20 TEMP_FAILURE_RETRY(usleep(1));
21 atomic_inc_prefix_s32(&at->data[i]);
22 }
23 return NULL;
24 }
25
atomic_thread_inc_dec(void * context)26 void *atomic_thread_inc_dec(void *context) {
27 struct atomic_test_s32_s *at = (struct atomic_test_s32_s *)context;
28 for (int i = 0; i < at->max_val; i++) {
29 TEMP_FAILURE_RETRY(usleep(1));
30 atomic_inc_prefix_s32(&at->data[i]);
31 TEMP_FAILURE_RETRY(usleep(1));
32 atomic_dec_prefix_s32(&at->data[i]);
33 }
34 return NULL;
35 }
36
TEST(AtomicTest,test_store_load_s32)37 TEST(AtomicTest, test_store_load_s32) {
38 atomic_s32_t data;
39
40 atomic_store_s32(&data, -1);
41 EXPECT_EQ(-1, atomic_load_s32(&data));
42
43 atomic_store_s32(&data, 0);
44 EXPECT_EQ(0, atomic_load_s32(&data));
45
46 atomic_store_s32(&data, 1);
47 EXPECT_EQ(1, atomic_load_s32(&data));
48
49 atomic_store_s32(&data, 2);
50 EXPECT_EQ(2, atomic_load_s32(&data));
51 }
52
TEST(AtomicTest,test_store_load_u32)53 TEST(AtomicTest, test_store_load_u32) {
54 atomic_u32_t data;
55
56 atomic_store_u32(&data, -1);
57 EXPECT_EQ((uint32_t)-1, atomic_load_u32(&data));
58
59 atomic_store_u32(&data, 0);
60 EXPECT_EQ((uint32_t)0, atomic_load_u32(&data));
61
62 atomic_store_u32(&data, 1);
63 EXPECT_EQ((uint32_t)1, atomic_load_u32(&data));
64
65 atomic_store_u32(&data, 2);
66 EXPECT_EQ((uint32_t)2, atomic_load_u32(&data));
67 }
68
TEST(AtomicTest,test_inc_dec_s32)69 TEST(AtomicTest, test_inc_dec_s32) {
70 atomic_s32_t data;
71
72 atomic_store_s32(&data, 0);
73 EXPECT_EQ(0, atomic_load_s32(&data));
74
75 int32_t val = atomic_inc_prefix_s32(&data);
76 EXPECT_EQ(1, atomic_load_s32(&data));
77 EXPECT_EQ(1, val);
78
79 val = atomic_inc_prefix_s32(&data);
80 EXPECT_EQ(2, atomic_load_s32(&data));
81 EXPECT_EQ(2, val);
82
83 val = atomic_inc_prefix_s32(&data);
84 EXPECT_EQ(3, atomic_load_s32(&data));
85 EXPECT_EQ(3, val);
86
87 val = atomic_dec_prefix_s32(&data);
88 EXPECT_EQ(2, val);
89
90 val = atomic_dec_prefix_s32(&data);
91 EXPECT_EQ(1, val);
92 val = atomic_dec_prefix_s32(&data);
93 EXPECT_EQ(0, val);
94 val = atomic_dec_prefix_s32(&data);
95 EXPECT_EQ(-1, val);
96 }
97
TEST(AtomicTest,test_inc_dec_u32)98 TEST(AtomicTest, test_inc_dec_u32) {
99 atomic_u32_t data;
100
101 atomic_store_u32(&data, 0);
102 EXPECT_EQ((unsigned)0, atomic_load_u32(&data));
103
104 uint32_t val = atomic_inc_prefix_u32(&data);
105 EXPECT_EQ((unsigned)1, atomic_load_u32(&data));
106 EXPECT_EQ((unsigned)1, val);
107
108 val = atomic_inc_prefix_u32(&data);
109 EXPECT_EQ((unsigned)2, atomic_load_u32(&data));
110 EXPECT_EQ((unsigned)2, val);
111
112 val = atomic_inc_prefix_u32(&data);
113 EXPECT_EQ((unsigned)3, atomic_load_u32(&data));
114 EXPECT_EQ((unsigned)3, val);
115
116 val = atomic_dec_prefix_u32(&data);
117 EXPECT_EQ((unsigned)2, val);
118
119 val = atomic_dec_prefix_u32(&data);
120 EXPECT_EQ((unsigned)1, val);
121 val = atomic_dec_prefix_u32(&data);
122 EXPECT_EQ((unsigned)0, val);
123 val = atomic_dec_prefix_u32(&data);
124 EXPECT_EQ((unsigned)-1, val);
125 }
126
TEST(AtomicTest,test_atomic_inc_thread)127 TEST(AtomicTest, test_atomic_inc_thread) {
128 struct atomic_test_s32_s atomic_test[ATOMIC_MAX_THREADS];
129 atomic_s32_t data[ATOMIC_DATA_MAX];
130
131 memset(&atomic_test, 0, sizeof(atomic_test));
132 memset(data, 0, sizeof(data));
133
134 for (unsigned int i = 0; i < ATOMIC_DATA_MAX; i++) {
135 EXPECT_EQ(0, data[i]._val);
136 }
137
138 for (int i = 0; i < ATOMIC_MAX_THREADS; i++) {
139 atomic_test[i].thread_num = i;
140 atomic_test[i].max_val = ATOMIC_DATA_MAX;
141 atomic_test[i].data = data;
142 pthread_create(&atomic_test[i].pthread_id, NULL, atomic_thread, &atomic_test[i]);
143 }
144
145 for (int i = 0; i < ATOMIC_MAX_THREADS; i++) {
146 int rc = pthread_join(atomic_test[i].pthread_id, NULL);
147 EXPECT_EQ(0, rc);
148 }
149
150 for (unsigned int i = 0; i < ATOMIC_DATA_MAX; i++) {
151 EXPECT_EQ(1 * ATOMIC_MAX_THREADS, data[i]._val);
152 }
153 }
154
TEST(AtomicTest,test_atomic_inc_thread_single)155 TEST(AtomicTest, test_atomic_inc_thread_single) {
156 struct atomic_test_s32_s atomic_test[ATOMIC_MAX_THREADS];
157 atomic_s32_t data;
158
159 memset(&atomic_test, 0, sizeof(atomic_test));
160 memset(&data, 0, sizeof(data));
161
162 EXPECT_EQ(0, data._val);
163
164 for (int i = 0; i < ATOMIC_MAX_THREADS; i++) {
165 atomic_test[i].thread_num = i;
166 atomic_test[i].max_val = 1;
167 atomic_test[i].data = &data;
168 pthread_create(&atomic_test[i].pthread_id, NULL, atomic_thread_inc_dec, &atomic_test[i]);
169 }
170
171 for (int i = 0; i < ATOMIC_MAX_THREADS; i++) {
172 int rc = pthread_join(atomic_test[i].pthread_id, NULL);
173 EXPECT_EQ(0, rc);
174 }
175 EXPECT_EQ(0, data._val);
176 }
177
TEST(AtomicTest,test_store_load_s64)178 TEST(AtomicTest, test_store_load_s64) {
179 atomic_s64_t data;
180
181 atomic_store_s64(&data, -1);
182 EXPECT_EQ(-1, atomic_load_s64(&data));
183
184 atomic_store_s64(&data, 0);
185 EXPECT_EQ(0, atomic_load_s64(&data));
186
187 atomic_store_s64(&data, 1);
188 EXPECT_EQ(1, atomic_load_s64(&data));
189
190 atomic_store_s64(&data, 2);
191 EXPECT_EQ(2, atomic_load_s64(&data));
192 }
193
TEST(AtomicTest,test_inc_dec_s64)194 TEST(AtomicTest, test_inc_dec_s64) {
195 atomic_s64_t data;
196
197 atomic_store_s64(&data, 0);
198 EXPECT_EQ(0, atomic_load_s64(&data));
199
200 int64_t val = atomic_inc_prefix_s64(&data);
201 EXPECT_EQ(1, atomic_load_s64(&data));
202 EXPECT_EQ(1, val);
203
204 val = atomic_inc_prefix_s64(&data);
205 EXPECT_EQ(2, atomic_load_s64(&data));
206 EXPECT_EQ(2, val);
207
208 val = atomic_inc_prefix_s64(&data);
209 EXPECT_EQ(3, atomic_load_s64(&data));
210 EXPECT_EQ(3, val);
211
212 val = atomic_dec_prefix_s64(&data);
213 EXPECT_EQ(2, val);
214
215 val = atomic_dec_prefix_s64(&data);
216 EXPECT_EQ(1, val);
217 val = atomic_dec_prefix_s64(&data);
218 EXPECT_EQ(0, val);
219 val = atomic_dec_prefix_s64(&data);
220 EXPECT_EQ(-1, val);
221
222 // Mutating using postfix.
223 val = atomic_inc_postfix_s64(&data);
224 EXPECT_EQ(0, atomic_load_s64(&data));
225 EXPECT_EQ(-1, val);
226
227 val = atomic_inc_postfix_s64(&data);
228 EXPECT_EQ(1, atomic_load_s64(&data));
229 EXPECT_EQ(0, val);
230
231 val = atomic_inc_postfix_s64(&data);
232 EXPECT_EQ(2, atomic_load_s64(&data));
233 EXPECT_EQ(1, val);
234
235 val = atomic_dec_postfix_s64(&data);
236 EXPECT_EQ(2, val);
237
238 val = atomic_dec_postfix_s64(&data);
239 EXPECT_EQ(1, val);
240 val = atomic_dec_postfix_s64(&data);
241 EXPECT_EQ(0, val);
242 val = atomic_dec_postfix_s64(&data);
243 EXPECT_EQ(-1, val);
244 EXPECT_EQ(-2, atomic_load_s64(&data));
245 }
246
TEST(AtomicTest,test_add_sub_u64)247 TEST(AtomicTest, test_add_sub_u64) {
248 atomic_u64_t data;
249
250 atomic_store_u64(&data, 0);
251 EXPECT_EQ((unsigned)0, atomic_load_u64(&data));
252
253 uint64_t val = atomic_add_u64(&data, 0xffff);
254 EXPECT_EQ((unsigned)0xffff, atomic_load_u64(&data));
255 EXPECT_EQ((unsigned)0xffff, val);
256
257 val = atomic_add_u64(&data, 0xffff);
258 EXPECT_EQ((unsigned)(2 * 0xffff), atomic_load_u64(&data));
259 EXPECT_EQ((unsigned)(2 * 0xffff), val);
260
261 val = atomic_add_u64(&data, 0xffff);
262 EXPECT_EQ((unsigned)(3 * 0xffff), atomic_load_u64(&data));
263 EXPECT_EQ((unsigned)(3 * 0xffff), val);
264 EXPECT_NE((unsigned)(3 * 0xfff0), val);
265
266 val = atomic_sub_u64(&data, 0xffff);
267 EXPECT_EQ((unsigned)(2 * 0xffff), val);
268
269 val = atomic_sub_u64(&data, 0);
270 EXPECT_EQ((unsigned)(2 * 0xffff), val);
271 val = atomic_sub_u64(&data, 0xffff);
272 EXPECT_EQ((unsigned)(1 * 0xffff), val);
273
274 val = atomic_sub_u64(&data, 0xffff);
275 EXPECT_EQ((unsigned)0, val);
276 }
277
278
279