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