This source file includes following definitions.
- store_newest_sum
- block_sigint
- idle_thread
- sigint_handler
- send_signal
- signal_sending_thread
- mutator_thread
- main
- main
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 #include <config.h>
45
46
47 #if 4 < __GNUC__ + (3 <= __GNUC_MINOR__)
48 # pragma GCC diagnostic ignored "-Wreturn-type"
49 #endif
50
51 #include "gl_linked_list.h"
52
53 #if SIGNAL_SAFE_LIST
54
55 # if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS
56
57
58
59
60
61
62
63 # include <signal.h>
64 # include <stdint.h>
65 # include <stdlib.h>
66 # include <unistd.h>
67 # include <time.h>
68
69 # include "glthread/thread.h"
70 # include "glthread/yield.h"
71
72 # include "macros.h"
73
74
75
76
77
78
79
80 # define MY_SIGNAL SIGTERM
81
82 # define RANDOM(n) (rand () % (n))
83 # define RANDOM_OBJECT() ((void *) (uintptr_t) RANDOM (10000))
84
85
86
87
88 static int volatile test;
89
90
91
92 # define NUM_RECENT_SUMS (4*1024*1024)
93 static uintptr_t volatile recent_sums[NUM_RECENT_SUMS];
94
95
96
97
98 static size_t volatile recent_sums_newest_index;
99 static size_t volatile recent_sums_oldest_index;
100
101 static void
102 store_newest_sum (uintptr_t sum)
103 {
104 recent_sums_oldest_index +=
105 (recent_sums_newest_index - recent_sums_oldest_index) == NUM_RECENT_SUMS;
106 recent_sums[recent_sums_newest_index % NUM_RECENT_SUMS] = sum;
107 recent_sums_newest_index++;
108 }
109
110 static gl_list_t volatile list1;
111
112 static gl_thread_t volatile signal_target;
113
114
115 static unsigned int volatile num_mutations;
116 static unsigned int volatile num_signals_sent;
117 static unsigned int volatile num_signals_arrived;
118
119
120 static void
121 block_sigint (void)
122 {
123 sigset_t mask;
124
125 sigemptyset (&mask);
126 sigaddset (&mask, MY_SIGNAL);
127 sigprocmask (SIG_BLOCK, &mask, NULL);
128 }
129
130
131 static void *
132 idle_thread (void *arg)
133 {
134 for (;;)
135 gl_thread_yield ();
136
137
138 }
139
140
141
142 static _GL_ASYNC_SAFE void
143 sigint_handler (int signo)
144 {
145 num_signals_arrived++;
146
147 uintptr_t sum = 0;
148 {
149 gl_list_iterator_t iter = gl_list_iterator (list1);
150 const void *elt;
151
152 while (gl_list_iterator_next (&iter, &elt, NULL))
153 sum += (uintptr_t) elt;
154 gl_list_iterator_free (&iter);
155 }
156
157 bool found = false;
158 if (test != 1)
159 {
160
161
162
163
164 size_t i;
165 for (i = recent_sums_newest_index - 1;;)
166 {
167 if (sum == recent_sums[i % NUM_RECENT_SUMS]
168 && i >= recent_sums_oldest_index)
169 {
170 found = true;
171 break;
172 }
173 if (i <= recent_sums_oldest_index)
174 break;
175 i--;
176 }
177 }
178 else
179 {
180
181
182
183 size_t i = recent_sums_newest_index - 1;
184 found = (sum == recent_sums[i % NUM_RECENT_SUMS]
185 || (i > recent_sums_oldest_index
186 && sum == recent_sums[(i - 1) % NUM_RECENT_SUMS]));
187 }
188 if (!found)
189 {
190
191
192
193 size_t i = recent_sums_newest_index - 1;
194 fprintf (stderr, "sum = %lu, expected %lu or older (after %u mutations and %u signals)\n",
195 (unsigned long) sum,
196 (unsigned long) recent_sums[i % NUM_RECENT_SUMS],
197 num_mutations, num_signals_arrived);
198 fflush (stderr);
199 abort ();
200 }
201 }
202
203
204 static void
205 send_signal (void)
206 {
207 #if 0
208
209
210
211 raise (MY_SIGNAL);
212 #else
213
214
215
216
217
218
219
220 kill (getpid (), MY_SIGNAL);
221 #endif
222 }
223
224
225 static void *
226 signal_sending_thread (void *arg)
227 {
228 if (test != 3)
229 block_sigint ();
230
231 int repeat;
232
233 for (repeat = 1000; repeat > 0; repeat--)
234 {
235 num_signals_sent++; send_signal ();
236 num_signals_sent++; send_signal ();
237 num_signals_sent++; send_signal ();
238 num_signals_sent++; send_signal ();
239 num_signals_sent++; send_signal ();
240 {
241 struct timespec ts;
242 ts.tv_sec = 0; ts.tv_nsec = 1000000;
243 nanosleep (&ts, NULL);
244 }
245 gl_thread_yield ();
246 }
247
248 printf ("Sent %u signals. Received %u signals. Done after %u mutations.\n",
249 num_signals_sent, num_signals_arrived, num_mutations);
250
251 exit (0);
252
253
254 }
255
256
257 static void *
258 mutator_thread (void *arg)
259 {
260 if (test != 1)
261 block_sigint ();
262
263 gl_list_t list2 = (gl_list_t) arg;
264
265 for (num_mutations = 0; ; num_mutations++)
266 {
267 unsigned int operation = RANDOM (2);
268 switch (operation)
269 {
270 case 0:
271 {
272 const void *obj = RANDOM_OBJECT ();
273 ASSERT (gl_list_nx_add_first (list2, obj) != NULL);
274 uintptr_t sum_before_current_operation =
275 recent_sums[(recent_sums_newest_index - 1) % NUM_RECENT_SUMS];
276 uintptr_t sum_after_current_operation =
277 sum_before_current_operation + (uintptr_t) obj;
278 store_newest_sum (sum_after_current_operation);
279 ASSERT (gl_list_nx_add_first (list1, obj) != NULL);
280 }
281 break;
282 case 1:
283 if (gl_list_size (list2) > 0)
284 {
285 size_t index = RANDOM (gl_list_size (list2));
286 const void *obj = gl_list_get_at (list2, index);
287 ASSERT (gl_list_remove (list2, obj));
288 uintptr_t sum_before_current_operation =
289 recent_sums[(recent_sums_newest_index - 1) % NUM_RECENT_SUMS];
290 uintptr_t sum_after_current_operation =
291 sum_before_current_operation - (uintptr_t) obj;
292 store_newest_sum (sum_after_current_operation);
293 ASSERT (gl_list_remove (list1, obj));
294 }
295 break;
296 }
297 }
298
299
300 }
301
302 int
303 main (int argc, char *argv[])
304 {
305 test = atoi (argv[1]);
306
307
308 if (argc > 2)
309 srand (atoi (argv[2]));
310
311 gl_list_t list2;
312
313 {
314 size_t initial_size = RANDOM (50);
315 const void **contents =
316 (const void **) malloc (initial_size * sizeof (const void *));
317 size_t i;
318
319 for (i = 0; i < initial_size; i++)
320 contents[i] = RANDOM_OBJECT ();
321
322 list1 = gl_list_nx_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
323 ASSERT (list1 != NULL);
324 for (i = 0; i < initial_size; i++)
325 ASSERT (gl_list_nx_add_first (list1, contents[i]) != NULL);
326
327 list2 = gl_list_nx_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
328 ASSERT (list2 != NULL);
329 for (i = 0; i < initial_size; i++)
330 ASSERT (gl_list_nx_add_last (list2, contents[i]) != NULL);
331
332 uintptr_t initial_sum = 0;
333 for (i = 0; i < initial_size; i++)
334 initial_sum += (uintptr_t) contents[i];
335 recent_sums_oldest_index = 0;
336 recent_sums[0] = initial_sum;
337 recent_sums_newest_index = 1;
338 }
339
340
341
342
343 #if 0
344 signal (MY_SIGNAL, sigint_handler);
345 #else
346 {
347 struct sigaction action;
348 action.sa_handler = sigint_handler;
349 action.sa_flags = SA_RESTART | SA_NODEFER;
350 sigemptyset (&action.sa_mask);
351 ASSERT (sigaction (MY_SIGNAL, &action, NULL) == 0);
352 }
353 #endif
354
355
356 switch (test)
357 {
358 case 1:
359 {
360 signal_target = gl_thread_create (mutator_thread, list2);
361 signal_sending_thread (NULL);
362 abort ();
363 }
364
365 case 2:
366 {
367 signal_target = gl_thread_create (idle_thread, NULL);
368 gl_thread_create (mutator_thread, list2);
369 signal_sending_thread (NULL);
370 abort ();
371 }
372
373 case 3:
374 {
375 gl_thread_create (mutator_thread, list2);
376 signal_target = gl_thread_self (); signal_sending_thread (NULL);
377 abort ();
378 }
379
380 default:
381 ASSERT (false);
382 }
383 }
384
385 # else
386
387 # include <stdio.h>
388
389 int
390 main ()
391 {
392 fputs ("Skipping test: POSIX compatible multithreading not enabled\n", stderr);
393 return 77;
394 }
395
396 # endif
397
398 #else
399
400 # include <stdio.h>
401
402 int
403 main ()
404 {
405 fputs ("Skipping test: signal-safety of linked lists is not enabled\n", stderr);
406 return 77;
407 }
408
409 #endif