• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Red Hat, Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * See the included COPYING file for more information.
10  */
11 
12 #include <glib.h>
13 
14 /* We want the g_atomic_pointer_get() macros to work when compiling third party
15  * projects with -Wbad-function-cast.
16  * See https://gitlab.gnome.org/GNOME/glib/issues/1041. */
17 #pragma GCC diagnostic error "-Wbad-function-cast"
18 
19 static void
test_types(void)20 test_types (void)
21 {
22   const gint *csp;
23   const gint * const *cspp;
24   guint u, u2;
25   gint s, s2;
26   gpointer vp, vp2;
27   int *ip, *ip2;
28   gsize gs, gs2;
29   gboolean res;
30 
31   csp = &s;
32   cspp = &csp;
33 
34   g_atomic_int_set (&u, 5);
35   u2 = g_atomic_int_get (&u);
36   g_assert_cmpint (u2, ==, 5);
37   res = g_atomic_int_compare_and_exchange (&u, 6, 7);
38   g_assert (!res);
39   g_assert_cmpint (u, ==, 5);
40   g_atomic_int_add (&u, 1);
41   g_assert_cmpint (u, ==, 6);
42   g_atomic_int_inc (&u);
43   g_assert_cmpint (u, ==, 7);
44   res = g_atomic_int_dec_and_test (&u);
45   g_assert (!res);
46   g_assert_cmpint (u, ==, 6);
47   u2 = g_atomic_int_and (&u, 5);
48   g_assert_cmpint (u2, ==, 6);
49   g_assert_cmpint (u, ==, 4);
50   u2 = g_atomic_int_or (&u, 8);
51   g_assert_cmpint (u2, ==, 4);
52   g_assert_cmpint (u, ==, 12);
53   u2 = g_atomic_int_xor (&u, 4);
54   g_assert_cmpint (u2, ==, 12);
55   g_assert_cmpint (u, ==, 8);
56 
57   g_atomic_int_set (&s, 5);
58   s2 = g_atomic_int_get (&s);
59   g_assert_cmpint (s2, ==, 5);
60   res = g_atomic_int_compare_and_exchange (&s, 6, 7);
61   g_assert (!res);
62   g_assert_cmpint (s, ==, 5);
63   g_atomic_int_add (&s, 1);
64   g_assert_cmpint (s, ==, 6);
65   g_atomic_int_inc (&s);
66   g_assert_cmpint (s, ==, 7);
67   res = g_atomic_int_dec_and_test (&s);
68   g_assert (!res);
69   g_assert_cmpint (s, ==, 6);
70   s2 = g_atomic_int_and (&s, 5);
71   g_assert_cmpint (s2, ==, 6);
72   g_assert_cmpint (s, ==, 4);
73   s2 = g_atomic_int_or (&s, 8);
74   g_assert_cmpint (s2, ==, 4);
75   g_assert_cmpint (s, ==, 12);
76   s2 = g_atomic_int_xor (&s, 4);
77   g_assert_cmpint (s2, ==, 12);
78   g_assert_cmpint (s, ==, 8);
79 
80   g_atomic_pointer_set (&vp, 0);
81   vp2 = g_atomic_pointer_get (&vp);
82   g_assert (vp2 == 0);
83   res = g_atomic_pointer_compare_and_exchange (&vp, 0, 0);
84   g_assert (res);
85   g_assert (vp == 0);
86 
87   g_atomic_pointer_set (&ip, 0);
88   ip2 = g_atomic_pointer_get (&ip);
89   g_assert (ip2 == 0);
90   res = g_atomic_pointer_compare_and_exchange (&ip, 0, 0);
91   g_assert (res);
92   g_assert (ip == 0);
93 
94   g_atomic_pointer_set (&gs, 0);
95   vp2 = g_atomic_pointer_get (&gs);
96   gs2 = (gsize) vp2;
97   g_assert (gs2 == 0);
98   res = g_atomic_pointer_compare_and_exchange (&gs, 0, 0);
99   g_assert (res);
100   g_assert (gs == 0);
101   gs2 = g_atomic_pointer_add (&gs, 5);
102   g_assert (gs2 == 0);
103   g_assert (gs == 5);
104   gs2 = g_atomic_pointer_and (&gs, 6);
105   g_assert (gs2 == 5);
106   g_assert (gs == 4);
107   gs2 = g_atomic_pointer_or (&gs, 8);
108   g_assert (gs2 == 4);
109   g_assert (gs == 12);
110   gs2 = g_atomic_pointer_xor (&gs, 4);
111   g_assert (gs2 == 12);
112   g_assert (gs == 8);
113 
114   g_assert (g_atomic_int_get (csp) == s);
115   g_assert (g_atomic_pointer_get (cspp) == csp);
116 
117   /* repeat, without the macros */
118 #undef g_atomic_int_set
119 #undef g_atomic_int_get
120 #undef g_atomic_int_compare_and_exchange
121 #undef g_atomic_int_add
122 #undef g_atomic_int_inc
123 #undef g_atomic_int_and
124 #undef g_atomic_int_or
125 #undef g_atomic_int_xor
126 #undef g_atomic_int_dec_and_test
127 #undef g_atomic_pointer_set
128 #undef g_atomic_pointer_get
129 #undef g_atomic_pointer_compare_and_exchange
130 #undef g_atomic_pointer_add
131 #undef g_atomic_pointer_and
132 #undef g_atomic_pointer_or
133 #undef g_atomic_pointer_xor
134 
135   g_atomic_int_set ((gint*)&u, 5);
136   u2 = g_atomic_int_get ((gint*)&u);
137   g_assert_cmpint (u2, ==, 5);
138   res = g_atomic_int_compare_and_exchange ((gint*)&u, 6, 7);
139   g_assert (!res);
140   g_assert_cmpint (u, ==, 5);
141   g_atomic_int_add ((gint*)&u, 1);
142   g_assert_cmpint (u, ==, 6);
143   g_atomic_int_inc ((gint*)&u);
144   g_assert_cmpint (u, ==, 7);
145   res = g_atomic_int_dec_and_test ((gint*)&u);
146   g_assert (!res);
147   g_assert_cmpint (u, ==, 6);
148   u2 = g_atomic_int_and (&u, 5);
149   g_assert_cmpint (u2, ==, 6);
150   g_assert_cmpint (u, ==, 4);
151   u2 = g_atomic_int_or (&u, 8);
152   g_assert_cmpint (u2, ==, 4);
153   g_assert_cmpint (u, ==, 12);
154   u2 = g_atomic_int_xor (&u, 4);
155   g_assert_cmpint (u2, ==, 12);
156 
157   g_atomic_int_set (&s, 5);
158   s2 = g_atomic_int_get (&s);
159   g_assert_cmpint (s2, ==, 5);
160   res = g_atomic_int_compare_and_exchange (&s, 6, 7);
161   g_assert (!res);
162   g_assert_cmpint (s, ==, 5);
163   g_atomic_int_add (&s, 1);
164   g_assert_cmpint (s, ==, 6);
165   g_atomic_int_inc (&s);
166   g_assert_cmpint (s, ==, 7);
167   res = g_atomic_int_dec_and_test (&s);
168   g_assert (!res);
169   g_assert_cmpint (s, ==, 6);
170   s2 = g_atomic_int_and ((guint*)&s, 5);
171   g_assert_cmpint (s2, ==, 6);
172   g_assert_cmpint (s, ==, 4);
173   s2 = g_atomic_int_or ((guint*)&s, 8);
174   g_assert_cmpint (s2, ==, 4);
175   g_assert_cmpint (s, ==, 12);
176   s2 = g_atomic_int_xor ((guint*)&s, 4);
177   g_assert_cmpint (s2, ==, 12);
178   g_assert_cmpint (s, ==, 8);
179 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
180   s2 = g_atomic_int_exchange_and_add ((gint*)&s, 1);
181 G_GNUC_END_IGNORE_DEPRECATIONS
182   g_assert_cmpint (s2, ==, 8);
183   g_assert_cmpint (s, ==, 9);
184 
185   g_atomic_pointer_set (&vp, 0);
186   vp2 = g_atomic_pointer_get (&vp);
187   g_assert (vp2 == 0);
188   res = g_atomic_pointer_compare_and_exchange (&vp, 0, 0);
189   g_assert (res);
190   g_assert (vp == 0);
191 
192   g_atomic_pointer_set (&ip, 0);
193   ip2 = g_atomic_pointer_get (&ip);
194   g_assert (ip2 == 0);
195   res = g_atomic_pointer_compare_and_exchange (&ip, 0, 0);
196   g_assert (res);
197   g_assert (ip == 0);
198 
199   g_atomic_pointer_set (&gs, 0);
200   vp = g_atomic_pointer_get (&gs);
201   gs2 = (gsize) vp;
202   g_assert (gs2 == 0);
203   res = g_atomic_pointer_compare_and_exchange (&gs, 0, 0);
204   g_assert (res);
205   g_assert (gs == 0);
206   gs2 = g_atomic_pointer_add (&gs, 5);
207   g_assert (gs2 == 0);
208   g_assert (gs == 5);
209   gs2 = g_atomic_pointer_and (&gs, 6);
210   g_assert (gs2 == 5);
211   g_assert (gs == 4);
212   gs2 = g_atomic_pointer_or (&gs, 8);
213   g_assert (gs2 == 4);
214   g_assert (gs == 12);
215   gs2 = g_atomic_pointer_xor (&gs, 4);
216   g_assert (gs2 == 12);
217   g_assert (gs == 8);
218 
219   g_assert (g_atomic_int_get (csp) == s);
220   g_assert (g_atomic_pointer_get (cspp) == csp);
221 }
222 
223 #define THREADS 10
224 #define ROUNDS 10000
225 
226 volatile gint bucket[THREADS];
227 volatile gint atomic;
228 
229 static gpointer
thread_func(gpointer data)230 thread_func (gpointer data)
231 {
232   gint idx = GPOINTER_TO_INT (data);
233   gint i;
234   gint d;
235 
236   for (i = 0; i < ROUNDS; i++)
237     {
238       d = g_random_int_range (-10, 100);
239       bucket[idx] += d;
240       g_atomic_int_add (&atomic, d);
241       g_thread_yield ();
242     }
243 
244   return NULL;
245 }
246 
247 static void
test_threaded(void)248 test_threaded (void)
249 {
250   gint sum;
251   gint i;
252   GThread *threads[THREADS];
253 
254   atomic = 0;
255   for (i = 0; i < THREADS; i++)
256     bucket[i] = 0;
257 
258   for (i = 0; i < THREADS; i++)
259     threads[i] = g_thread_new ("atomic", thread_func, GINT_TO_POINTER (i));
260 
261   for (i = 0; i < THREADS; i++)
262     g_thread_join (threads[i]);
263 
264   sum = 0;
265   for (i = 0; i < THREADS; i++)
266     sum += bucket[i];
267 
268   g_assert_cmpint (sum, ==, atomic);
269 }
270 
271 int
main(int argc,char ** argv)272 main (int argc, char **argv)
273 {
274   g_test_init (&argc, &argv, NULL);
275 
276   g_test_add_func ("/atomic/types", test_types);
277   g_test_add_func ("/atomic/threaded", test_threaded);
278 
279   return g_test_run ();
280 }
281