nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 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 | #define GLIB_DISABLE_DEPRECATION_WARNINGS |
||
25 | |||
26 | #include <glib.h> |
||
27 | |||
28 | static void |
||
29 | test_rwlock1 (void) |
||
30 | { |
||
31 | GRWLock lock; |
||
32 | |||
33 | g_rw_lock_init (&lock); |
||
34 | g_rw_lock_writer_lock (&lock); |
||
35 | g_rw_lock_writer_unlock (&lock); |
||
36 | g_rw_lock_writer_lock (&lock); |
||
37 | g_rw_lock_writer_unlock (&lock); |
||
38 | g_rw_lock_clear (&lock); |
||
39 | } |
||
40 | |||
41 | static void |
||
42 | test_rwlock2 (void) |
||
43 | { |
||
44 | static GRWLock lock; |
||
45 | |||
46 | g_rw_lock_writer_lock (&lock); |
||
47 | g_rw_lock_writer_unlock (&lock); |
||
48 | g_rw_lock_writer_lock (&lock); |
||
49 | g_rw_lock_writer_unlock (&lock); |
||
50 | } |
||
51 | |||
52 | static void |
||
53 | test_rwlock3 (void) |
||
54 | { |
||
55 | static GRWLock lock; |
||
56 | gboolean ret; |
||
57 | |||
58 | ret = g_rw_lock_writer_trylock (&lock); |
||
59 | g_assert (ret); |
||
60 | ret = g_rw_lock_writer_trylock (&lock); |
||
61 | g_assert (!ret); |
||
62 | |||
63 | g_rw_lock_writer_unlock (&lock); |
||
64 | } |
||
65 | |||
66 | static void |
||
67 | test_rwlock4 (void) |
||
68 | { |
||
69 | static GRWLock lock; |
||
70 | |||
71 | g_rw_lock_reader_lock (&lock); |
||
72 | g_rw_lock_reader_unlock (&lock); |
||
73 | g_rw_lock_reader_lock (&lock); |
||
74 | g_rw_lock_reader_unlock (&lock); |
||
75 | } |
||
76 | |||
77 | static void |
||
78 | test_rwlock5 (void) |
||
79 | { |
||
80 | static GRWLock lock; |
||
81 | gboolean ret; |
||
82 | |||
83 | ret = g_rw_lock_reader_trylock (&lock); |
||
84 | g_assert (ret); |
||
85 | ret = g_rw_lock_reader_trylock (&lock); |
||
86 | g_assert (ret); |
||
87 | |||
88 | g_rw_lock_reader_unlock (&lock); |
||
89 | g_rw_lock_reader_unlock (&lock); |
||
90 | } |
||
91 | |||
92 | static void |
||
93 | test_rwlock6 (void) |
||
94 | { |
||
95 | static GRWLock lock; |
||
96 | gboolean ret; |
||
97 | |||
98 | g_rw_lock_writer_lock (&lock); |
||
99 | ret = g_rw_lock_reader_trylock (&lock); |
||
100 | g_assert (!ret); |
||
101 | g_rw_lock_writer_unlock (&lock); |
||
102 | |||
103 | g_rw_lock_reader_lock (&lock); |
||
104 | ret = g_rw_lock_writer_trylock (&lock); |
||
105 | g_assert (!ret); |
||
106 | g_rw_lock_reader_unlock (&lock); |
||
107 | } |
||
108 | |||
109 | |||
110 | #define LOCKS 48 |
||
111 | #define ITERATIONS 10000 |
||
112 | #define THREADS 100 |
||
113 | |||
114 | |||
115 | GThread *owners[LOCKS]; |
||
116 | GRWLock locks[LOCKS]; |
||
117 | |||
118 | static void |
||
119 | acquire (gint nr) |
||
120 | { |
||
121 | GThread *self; |
||
122 | |||
123 | self = g_thread_self (); |
||
124 | |||
125 | if (!g_rw_lock_writer_trylock (&locks[nr])) |
||
126 | { |
||
127 | if (g_test_verbose ()) |
||
128 | g_printerr ("thread %p going to block on lock %d\n", self, nr); |
||
129 | |||
130 | g_rw_lock_writer_lock (&locks[nr]); |
||
131 | } |
||
132 | |||
133 | g_assert (owners[nr] == NULL); /* hopefully nobody else is here */ |
||
134 | owners[nr] = self; |
||
135 | |||
136 | /* let some other threads try to ruin our day */ |
||
137 | g_thread_yield (); |
||
138 | g_thread_yield (); |
||
139 | g_thread_yield (); |
||
140 | |||
141 | g_assert (owners[nr] == self); /* hopefully this is still us... */ |
||
142 | owners[nr] = NULL; /* make way for the next guy */ |
||
143 | |||
144 | g_rw_lock_writer_unlock (&locks[nr]); |
||
145 | } |
||
146 | |||
147 | static gpointer |
||
148 | thread_func (gpointer data) |
||
149 | { |
||
150 | gint i; |
||
151 | GRand *rand; |
||
152 | |||
153 | rand = g_rand_new (); |
||
154 | |||
155 | for (i = 0; i < ITERATIONS; i++) |
||
156 | acquire (g_rand_int_range (rand, 0, LOCKS)); |
||
157 | |||
158 | g_rand_free (rand); |
||
159 | |||
160 | return NULL; |
||
161 | } |
||
162 | |||
163 | static void |
||
164 | test_rwlock7 (void) |
||
165 | { |
||
166 | gint i; |
||
167 | GThread *threads[THREADS]; |
||
168 | |||
169 | for (i = 0; i < LOCKS; i++) |
||
170 | g_rw_lock_init (&locks[i]); |
||
171 | |||
172 | for (i = 0; i < THREADS; i++) |
||
173 | threads[i] = g_thread_new ("test", thread_func, NULL); |
||
174 | |||
175 | for (i = 0; i < THREADS; i++) |
||
176 | g_thread_join (threads[i]); |
||
177 | |||
178 | for (i = 0; i < LOCKS; i++) |
||
179 | g_rw_lock_clear (&locks[i]); |
||
180 | |||
181 | for (i = 0; i < LOCKS; i++) |
||
182 | g_assert (owners[i] == NULL); |
||
183 | } |
||
184 | |||
185 | static gint even; |
||
186 | static GRWLock even_lock; |
||
187 | GThread *writers[2]; |
||
188 | GThread *readers[10]; |
||
189 | |||
190 | static void |
||
191 | change_even (gpointer data) |
||
192 | { |
||
193 | g_rw_lock_writer_lock (&even_lock); |
||
194 | |||
195 | g_assert (even % 2 == 0); |
||
196 | |||
197 | even += 1; |
||
198 | |||
199 | if (GPOINTER_TO_INT (data) == 0) |
||
200 | even += 1; |
||
201 | else |
||
202 | even -= 1; |
||
203 | |||
204 | g_assert (even % 2 == 0); |
||
205 | |||
206 | g_rw_lock_writer_unlock (&even_lock); |
||
207 | } |
||
208 | |||
209 | static void |
||
210 | verify_even (gpointer data) |
||
211 | { |
||
212 | g_rw_lock_reader_lock (&even_lock); |
||
213 | |||
214 | g_assert (even % 2 == 0); |
||
215 | |||
216 | g_rw_lock_reader_unlock (&even_lock); |
||
217 | } |
||
218 | |||
219 | static gpointer |
||
220 | writer_func (gpointer data) |
||
221 | { |
||
222 | gint i; |
||
223 | |||
224 | for (i = 0; i < 100000; i++) |
||
225 | change_even (data); |
||
226 | |||
227 | return NULL; |
||
228 | } |
||
229 | |||
230 | static gpointer |
||
231 | reader_func (gpointer data) |
||
232 | { |
||
233 | gint i; |
||
234 | |||
235 | for (i = 0; i < 100000; i++) |
||
236 | verify_even (data); |
||
237 | |||
238 | return NULL; |
||
239 | } |
||
240 | |||
241 | /* This test has 2 writers and 10 readers. |
||
242 | * The writers modify an integer multiple times, |
||
243 | * but always leave it with an even value. |
||
244 | * The readers verify that they can only observe |
||
245 | * even values |
||
246 | */ |
||
247 | static void |
||
248 | test_rwlock8 (void) |
||
249 | { |
||
250 | gint i; |
||
251 | |||
252 | even = 0; |
||
253 | g_rw_lock_init (&even_lock); |
||
254 | |||
255 | for (i = 0; i < 2; i++) |
||
256 | writers[i] = g_thread_new ("a", writer_func, GINT_TO_POINTER (i)); |
||
257 | |||
258 | for (i = 0; i < 10; i++) |
||
259 | readers[i] = g_thread_new ("b", reader_func, NULL); |
||
260 | |||
261 | for (i = 0; i < 2; i++) |
||
262 | g_thread_join (writers[i]); |
||
263 | |||
264 | for (i = 0; i < 10; i++) |
||
265 | g_thread_join (readers[i]); |
||
266 | |||
267 | g_assert (even % 2 == 0); |
||
268 | |||
269 | g_rw_lock_clear (&even_lock); |
||
270 | } |
||
271 | |||
272 | int |
||
273 | main (int argc, char *argv[]) |
||
274 | { |
||
275 | g_test_init (&argc, &argv, NULL); |
||
276 | |||
277 | g_test_add_func ("/thread/rwlock1", test_rwlock1); |
||
278 | g_test_add_func ("/thread/rwlock2", test_rwlock2); |
||
279 | g_test_add_func ("/thread/rwlock3", test_rwlock3); |
||
280 | g_test_add_func ("/thread/rwlock4", test_rwlock4); |
||
281 | g_test_add_func ("/thread/rwlock5", test_rwlock5); |
||
282 | g_test_add_func ("/thread/rwlock6", test_rwlock6); |
||
283 | g_test_add_func ("/thread/rwlock7", test_rwlock7); |
||
284 | g_test_add_func ("/thread/rwlock8", test_rwlock8); |
||
285 | |||
286 | return g_test_run (); |
||
287 | } |