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