• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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