Branch data Line data Source code
1 : : /* Unit tests for GRWLock
2 : : * Copyright (C) 2011 Red Hat, Inc
3 : : * Author: Matthias Clasen
4 : : *
5 : : * SPDX-License-Identifier: LicenseRef-old-glib-tests
6 : : *
7 : : * This work is provided "as is"; redistribution and modification
8 : : * in whole or in part, in any medium, physical or electronic is
9 : : * permitted without restriction.
10 : : *
11 : : * This work is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 : : *
15 : : * In no event shall the authors or contributors be liable for any
16 : : * direct, indirect, incidental, special, exemplary, or consequential
17 : : * damages (including, but not limited to, procurement of substitute
18 : : * goods or services; loss of use, data, or profits; or business
19 : : * interruption) however caused and on any theory of liability, whether
20 : : * in contract, strict liability, or tort (including negligence or
21 : : * otherwise) arising in any way out of the use of this software, even
22 : : * if advised of the possibility of such damage.
23 : : */
24 : :
25 : : /* We are testing some deprecated APIs here */
26 : : #ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
27 : : #define GLIB_DISABLE_DEPRECATION_WARNINGS
28 : : #endif
29 : :
30 : : #include <glib.h>
31 : :
32 : : static void
33 : 1 : test_rwlock1 (void)
34 : : {
35 : : GRWLock lock;
36 : :
37 : 1 : g_rw_lock_init (&lock);
38 : 1 : g_rw_lock_writer_lock (&lock);
39 : 1 : g_rw_lock_writer_unlock (&lock);
40 : 1 : g_rw_lock_writer_lock (&lock);
41 : 1 : g_rw_lock_writer_unlock (&lock);
42 : 1 : g_rw_lock_clear (&lock);
43 : 1 : }
44 : :
45 : : static void
46 : 1 : test_rwlock2 (void)
47 : : {
48 : : static GRWLock lock;
49 : :
50 : 1 : g_rw_lock_writer_lock (&lock);
51 : 1 : g_rw_lock_writer_unlock (&lock);
52 : 1 : g_rw_lock_writer_lock (&lock);
53 : 1 : g_rw_lock_writer_unlock (&lock);
54 : 1 : }
55 : :
56 : : static void
57 : 1 : test_rwlock3 (void)
58 : : {
59 : : static GRWLock lock;
60 : : gboolean ret;
61 : :
62 : 1 : ret = g_rw_lock_writer_trylock (&lock);
63 : 1 : g_assert (ret);
64 : 1 : ret = g_rw_lock_writer_trylock (&lock);
65 : 1 : g_assert (!ret);
66 : :
67 : 1 : g_rw_lock_writer_unlock (&lock);
68 : 1 : }
69 : :
70 : : static void
71 : 1 : test_rwlock4 (void)
72 : : {
73 : : static GRWLock lock;
74 : :
75 : 1 : g_rw_lock_reader_lock (&lock);
76 : 1 : g_rw_lock_reader_unlock (&lock);
77 : 1 : g_rw_lock_reader_lock (&lock);
78 : 1 : g_rw_lock_reader_unlock (&lock);
79 : 1 : }
80 : :
81 : : static void
82 : 1 : test_rwlock5 (void)
83 : : {
84 : : static GRWLock lock;
85 : : gboolean ret;
86 : :
87 : 1 : ret = g_rw_lock_reader_trylock (&lock);
88 : 1 : g_assert (ret);
89 : 1 : ret = g_rw_lock_reader_trylock (&lock);
90 : 1 : g_assert (ret);
91 : :
92 : 1 : g_rw_lock_reader_unlock (&lock);
93 : 1 : g_rw_lock_reader_unlock (&lock);
94 : 1 : }
95 : :
96 : : static void
97 : 1 : test_rwlock6 (void)
98 : : {
99 : : static GRWLock lock;
100 : : gboolean ret;
101 : :
102 : 1 : g_rw_lock_writer_lock (&lock);
103 : 1 : ret = g_rw_lock_reader_trylock (&lock);
104 : 1 : g_assert (!ret);
105 : 1 : g_rw_lock_writer_unlock (&lock);
106 : :
107 : 1 : g_rw_lock_reader_lock (&lock);
108 : 1 : ret = g_rw_lock_writer_trylock (&lock);
109 : 1 : g_assert (!ret);
110 : 1 : g_rw_lock_reader_unlock (&lock);
111 : 1 : }
112 : :
113 : :
114 : : #define LOCKS 48
115 : : #define ITERATIONS 10000
116 : : #define THREADS 100
117 : :
118 : :
119 : : GThread *owners[LOCKS];
120 : : GRWLock locks[LOCKS];
121 : :
122 : : static void
123 : 1000000 : acquire (gint nr)
124 : : {
125 : : GThread *self;
126 : :
127 : 1000000 : self = g_thread_self ();
128 : :
129 [ + + ]: 1000000 : if (!g_rw_lock_writer_trylock (&locks[nr]))
130 : : {
131 [ - + ]: 522989 : if (g_test_verbose ())
132 : 0 : g_printerr ("thread %p going to block on lock %d\n", self, nr);
133 : :
134 : 522989 : g_rw_lock_writer_lock (&locks[nr]);
135 : : }
136 : :
137 : 1000000 : g_assert (owners[nr] == NULL); /* hopefully nobody else is here */
138 : 1000000 : owners[nr] = self;
139 : :
140 : : /* let some other threads try to ruin our day */
141 : 1000000 : g_thread_yield ();
142 : 1000000 : g_thread_yield ();
143 : 1000000 : g_thread_yield ();
144 : :
145 : 1000000 : g_assert (owners[nr] == self); /* hopefully this is still us... */
146 : 1000000 : owners[nr] = NULL; /* make way for the next guy */
147 : :
148 : 1000000 : g_rw_lock_writer_unlock (&locks[nr]);
149 : 1000000 : }
150 : :
151 : : static gpointer
152 : 100 : thread_func (gpointer data)
153 : : {
154 : : gint i;
155 : : GRand *rand;
156 : :
157 : 100 : rand = g_rand_new ();
158 : :
159 [ + + ]: 1000100 : for (i = 0; i < ITERATIONS; i++)
160 : 1000000 : acquire (g_rand_int_range (rand, 0, LOCKS));
161 : :
162 : 100 : g_rand_free (rand);
163 : :
164 : 100 : return NULL;
165 : : }
166 : :
167 : : static void
168 : 1 : test_rwlock7 (void)
169 : : {
170 : : gint i;
171 : : GThread *threads[THREADS];
172 : :
173 [ + + ]: 49 : for (i = 0; i < LOCKS; i++)
174 : 48 : g_rw_lock_init (&locks[i]);
175 : :
176 [ + + ]: 101 : for (i = 0; i < THREADS; i++)
177 : 100 : threads[i] = g_thread_new ("test", thread_func, NULL);
178 : :
179 [ + + ]: 101 : for (i = 0; i < THREADS; i++)
180 : 100 : g_thread_join (threads[i]);
181 : :
182 [ + + ]: 49 : for (i = 0; i < LOCKS; i++)
183 : 48 : g_rw_lock_clear (&locks[i]);
184 : :
185 [ + + ]: 49 : for (i = 0; i < LOCKS; i++)
186 : 48 : g_assert (owners[i] == NULL);
187 : 1 : }
188 : :
189 : : static gint even;
190 : : static GRWLock even_lock;
191 : : GThread *writers[2];
192 : : GThread *readers[10];
193 : :
194 : : static void
195 : 200000 : change_even (gpointer data)
196 : : {
197 : 200000 : g_rw_lock_writer_lock (&even_lock);
198 : :
199 : 200000 : g_assert (even % 2 == 0);
200 : :
201 : 200000 : even += 1;
202 : :
203 [ + + ]: 200000 : if (GPOINTER_TO_INT (data) == 0)
204 : 100000 : even += 1;
205 : : else
206 : 100000 : even -= 1;
207 : :
208 : 200000 : g_assert (even % 2 == 0);
209 : :
210 : 200000 : g_rw_lock_writer_unlock (&even_lock);
211 : 200000 : }
212 : :
213 : : static void
214 : 1000000 : verify_even (gpointer data)
215 : : {
216 : 1000000 : g_rw_lock_reader_lock (&even_lock);
217 : :
218 : 1000000 : g_assert (even % 2 == 0);
219 : :
220 : 1000000 : g_rw_lock_reader_unlock (&even_lock);
221 : 1000000 : }
222 : :
223 : : static gpointer
224 : 2 : writer_func (gpointer data)
225 : : {
226 : : gint i;
227 : :
228 [ + + ]: 200002 : for (i = 0; i < 100000; i++)
229 : 200000 : change_even (data);
230 : :
231 : 2 : return NULL;
232 : : }
233 : :
234 : : static gpointer
235 : 10 : reader_func (gpointer data)
236 : : {
237 : : gint i;
238 : :
239 [ + + ]: 1000010 : for (i = 0; i < 100000; i++)
240 : 1000000 : verify_even (data);
241 : :
242 : 10 : return NULL;
243 : : }
244 : :
245 : : /* This test has 2 writers and 10 readers.
246 : : * The writers modify an integer multiple times,
247 : : * but always leave it with an even value.
248 : : * The readers verify that they can only observe
249 : : * even values
250 : : */
251 : : static void
252 : 1 : test_rwlock8 (void)
253 : : {
254 : : gint i;
255 : :
256 : 1 : even = 0;
257 : 1 : g_rw_lock_init (&even_lock);
258 : :
259 [ + + ]: 3 : for (i = 0; i < 2; i++)
260 : 2 : writers[i] = g_thread_new ("a", writer_func, GINT_TO_POINTER (i));
261 : :
262 [ + + ]: 11 : for (i = 0; i < 10; i++)
263 : 10 : readers[i] = g_thread_new ("b", reader_func, NULL);
264 : :
265 [ + + ]: 3 : for (i = 0; i < 2; i++)
266 : 2 : g_thread_join (writers[i]);
267 : :
268 [ + + ]: 11 : for (i = 0; i < 10; i++)
269 : 10 : g_thread_join (readers[i]);
270 : :
271 : 1 : g_assert (even % 2 == 0);
272 : :
273 : 1 : g_rw_lock_clear (&even_lock);
274 : 1 : }
275 : :
276 : : int
277 : 1 : main (int argc, char *argv[])
278 : : {
279 : 1 : g_test_init (&argc, &argv, NULL);
280 : :
281 : 1 : g_test_add_func ("/thread/rwlock1", test_rwlock1);
282 : 1 : g_test_add_func ("/thread/rwlock2", test_rwlock2);
283 : 1 : g_test_add_func ("/thread/rwlock3", test_rwlock3);
284 : 1 : g_test_add_func ("/thread/rwlock4", test_rwlock4);
285 : 1 : g_test_add_func ("/thread/rwlock5", test_rwlock5);
286 : 1 : g_test_add_func ("/thread/rwlock6", test_rwlock6);
287 : 1 : g_test_add_func ("/thread/rwlock7", test_rwlock7);
288 : 1 : g_test_add_func ("/thread/rwlock8", test_rwlock8);
289 : :
290 : 1 : return g_test_run ();
291 : : }
|