1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
10 * These tests verify the correct behavior of the IPC Barrier implementation.
11 * Note that the tests use alarm-timers to verify dead-locks and timeouts. These
12 * might not work on slow machines where 20ms are too short to perform specific
13 * operations (though, very unlikely). In case that turns out true, we have to
14 * increase it at the slightly cost of lengthen test-duration on other machines.
25 /* 20ms to test deadlocks; All timings use multiples of this constant as
26 * alarm/sleep timers. If this timeout is too small for slow machines to perform
27 * the requested operations, we have to increase it. On an i7 this works fine
28 * with 1ms base-time, so 20ms should be just fine for everyone. */
29 #define BASE_TIME (20 * USEC_PER_MSEC)
31 static void set_alarm(usec_t usecs
) {
32 struct itimerval v
= { };
34 timeval_store(&v
.it_value
, usecs
);
35 assert_se(setitimer(ITIMER_REAL
, &v
, NULL
) >= 0);
38 static void sleep_for(usec_t usecs
) {
39 /* stupid usleep() might fail if >1000000 */
40 assert_se(usecs
< USEC_PER_SEC
);
44 #define TEST_BARRIER(_FUNCTION, _CHILD_CODE, _WAIT_CHILD, _PARENT_CODE, _WAIT_PARENT) \
45 static void _FUNCTION(void) { \
46 Barrier b = BARRIER_NULL; \
49 assert_se(barrier_create(&b) >= 0); \
50 assert_se(b.me > 0); \
51 assert_se(b.them > 0); \
52 assert_se(b.pipe[0] > 0); \
53 assert_se(b.pipe[1] > 0); \
56 assert_se(pid1 >= 0); \
58 barrier_set_role(&b, BARRIER_CHILD); \
64 assert_se(pid2 >= 0); \
66 barrier_set_role(&b, BARRIER_PARENT); \
71 barrier_destroy(&b); \
78 #define TEST_BARRIER_WAIT_SUCCESS(_pid) \
81 pidr = waitpid(_pid, &status, 0); \
82 assert_se(pidr == _pid); \
83 assert_se(WIFEXITED(status)); \
84 assert_se(WEXITSTATUS(status) == 42); \
87 #define TEST_BARRIER_WAIT_ALARM(_pid) \
90 pidr = waitpid(_pid, &status, 0); \
91 assert_se(pidr == _pid); \
92 assert_se(WIFSIGNALED(status)); \
93 assert_se(WTERMSIG(status) == SIGALRM); \
97 * Test basic sync points
98 * This places a barrier in both processes and waits synchronously for them.
99 * The timeout makes sure the sync works as expected. The sleep_for() on one side
100 * makes sure the exit of the parent does not overwrite previous barriers. Due
101 * to the sleep_for(), we know that the parent already exited, thus there's a
102 * pending HUP on the pipe. However, the barrier_sync() prefers reads on the
103 * eventfd, thus we can safely wait on the barrier.
105 TEST_BARRIER(test_barrier_sync
,
107 set_alarm(BASE_TIME
* 10);
108 assert_se(barrier_place(&b
));
109 sleep_for(BASE_TIME
* 2);
110 assert_se(barrier_sync(&b
));
112 TEST_BARRIER_WAIT_SUCCESS(pid1
),
114 set_alarm(BASE_TIME
* 10);
115 assert_se(barrier_place(&b
));
116 assert_se(barrier_sync(&b
));
118 TEST_BARRIER_WAIT_SUCCESS(pid2
));
122 * This places a barrier in the parent and syncs on it. The child sleeps while
123 * the parent places the barrier and then waits for a barrier. The wait will
124 * succeed as the child hasn't read the parent's barrier, yet. The following
125 * barrier and sync synchronize the exit.
127 TEST_BARRIER(test_barrier_wait_next
,
129 sleep_for(BASE_TIME
);
130 set_alarm(BASE_TIME
* 10);
131 assert_se(barrier_wait_next(&b
));
132 assert_se(barrier_place(&b
));
133 assert_se(barrier_sync(&b
));
135 TEST_BARRIER_WAIT_SUCCESS(pid1
),
137 set_alarm(BASE_TIME
* 4);
138 assert_se(barrier_place(&b
));
139 assert_se(barrier_sync(&b
));
141 TEST_BARRIER_WAIT_SUCCESS(pid2
));
144 * Test wait_next() multiple times
145 * This places two barriers in the parent and waits for the child to exit. The
146 * child sleeps 20ms so both barriers _should_ be in place. It then waits for
147 * the parent to place the next barrier twice. The first call will fetch both
148 * barriers and return. However, the second call will stall as the parent does
149 * not place a 3rd barrier (the sleep caught two barriers). wait_next() is does
150 * not look at barrier-links so this stall is expected. Thus this test times
153 TEST_BARRIER(test_barrier_wait_next_twice
,
155 sleep_for(BASE_TIME
);
156 set_alarm(BASE_TIME
);
157 assert_se(barrier_wait_next(&b
));
158 assert_se(barrier_wait_next(&b
));
161 TEST_BARRIER_WAIT_ALARM(pid1
),
163 set_alarm(BASE_TIME
* 10);
164 assert_se(barrier_place(&b
));
165 assert_se(barrier_place(&b
));
166 sleep_for(BASE_TIME
* 4);
168 TEST_BARRIER_WAIT_SUCCESS(pid2
));
171 * Test wait_next() with local barriers
172 * This is the same as test_barrier_wait_next_twice, but places local barriers
173 * between both waits. This does not have any effect on the wait so it times out
174 * like the other test.
176 TEST_BARRIER(test_barrier_wait_next_twice_local
,
178 sleep_for(BASE_TIME
);
179 set_alarm(BASE_TIME
);
180 assert_se(barrier_wait_next(&b
));
181 assert_se(barrier_place(&b
));
182 assert_se(barrier_place(&b
));
183 assert_se(barrier_wait_next(&b
));
186 TEST_BARRIER_WAIT_ALARM(pid1
),
188 set_alarm(BASE_TIME
* 10);
189 assert_se(barrier_place(&b
));
190 assert_se(barrier_place(&b
));
191 sleep_for(BASE_TIME
* 4);
193 TEST_BARRIER_WAIT_SUCCESS(pid2
));
196 * Test wait_next() with sync_next()
197 * This is again the same as test_barrier_wait_next_twice but uses a
198 * synced wait as the second wait. This works just fine because the local state
199 * has no barriers placed, therefore, the remote is always in sync.
201 TEST_BARRIER(test_barrier_wait_next_twice_sync
,
203 sleep_for(BASE_TIME
);
204 set_alarm(BASE_TIME
);
205 assert_se(barrier_wait_next(&b
));
206 assert_se(barrier_sync_next(&b
));
208 TEST_BARRIER_WAIT_SUCCESS(pid1
),
210 set_alarm(BASE_TIME
* 10);
211 assert_se(barrier_place(&b
));
212 assert_se(barrier_place(&b
));
214 TEST_BARRIER_WAIT_SUCCESS(pid2
));
217 * Test wait_next() with sync_next() and local barriers
218 * This is again the same as test_barrier_wait_next_twice_local but uses a
219 * synced wait as the second wait. This works just fine because the local state
220 * is in sync with the remote.
222 TEST_BARRIER(test_barrier_wait_next_twice_local_sync
,
224 sleep_for(BASE_TIME
);
225 set_alarm(BASE_TIME
);
226 assert_se(barrier_wait_next(&b
));
227 assert_se(barrier_place(&b
));
228 assert_se(barrier_place(&b
));
229 assert_se(barrier_sync_next(&b
));
231 TEST_BARRIER_WAIT_SUCCESS(pid1
),
233 set_alarm(BASE_TIME
* 10);
234 assert_se(barrier_place(&b
));
235 assert_se(barrier_place(&b
));
237 TEST_BARRIER_WAIT_SUCCESS(pid2
));
240 * Test sync_next() and sync()
241 * This tests sync_*() synchronizations and makes sure they work fine if the
242 * local state is behind the remote state.
244 TEST_BARRIER(test_barrier_sync_next
,
246 set_alarm(BASE_TIME
* 10);
247 assert_se(barrier_sync_next(&b
));
248 assert_se(barrier_sync(&b
));
249 assert_se(barrier_place(&b
));
250 assert_se(barrier_place(&b
));
251 assert_se(barrier_sync_next(&b
));
252 assert_se(barrier_sync_next(&b
));
253 assert_se(barrier_sync(&b
));
255 TEST_BARRIER_WAIT_SUCCESS(pid1
),
257 set_alarm(BASE_TIME
* 10);
258 sleep_for(BASE_TIME
);
259 assert_se(barrier_place(&b
));
260 assert_se(barrier_place(&b
));
261 assert_se(barrier_sync(&b
));
263 TEST_BARRIER_WAIT_SUCCESS(pid2
));
266 * Test sync_next() and sync() with local barriers
267 * This tests timeouts if sync_*() is used if local barriers are placed but the
268 * remote didn't place any.
270 TEST_BARRIER(test_barrier_sync_next_local
,
272 set_alarm(BASE_TIME
);
273 assert_se(barrier_place(&b
));
274 assert_se(barrier_sync_next(&b
));
277 TEST_BARRIER_WAIT_ALARM(pid1
),
279 sleep_for(BASE_TIME
* 2);
281 TEST_BARRIER_WAIT_SUCCESS(pid2
));
284 * Test sync_next() and sync() with local barriers and abortion
285 * This is the same as test_barrier_sync_next_local but aborts the sync in the
286 * parent. Therefore, the sync_next() succeeds just fine due to the abortion.
288 TEST_BARRIER(test_barrier_sync_next_local_abort
,
290 set_alarm(BASE_TIME
* 10);
291 assert_se(barrier_place(&b
));
292 assert_se(!barrier_sync_next(&b
));
294 TEST_BARRIER_WAIT_SUCCESS(pid1
),
296 assert_se(barrier_abort(&b
));
298 TEST_BARRIER_WAIT_SUCCESS(pid2
));
301 * Test matched wait_abortion()
302 * This runs wait_abortion() with remote abortion.
304 TEST_BARRIER(test_barrier_wait_abortion
,
306 set_alarm(BASE_TIME
* 10);
307 assert_se(barrier_wait_abortion(&b
));
309 TEST_BARRIER_WAIT_SUCCESS(pid1
),
311 assert_se(barrier_abort(&b
));
313 TEST_BARRIER_WAIT_SUCCESS(pid2
));
316 * Test unmatched wait_abortion()
317 * This runs wait_abortion() without any remote abortion going on. It thus must
320 TEST_BARRIER(test_barrier_wait_abortion_unmatched
,
322 set_alarm(BASE_TIME
);
323 assert_se(barrier_wait_abortion(&b
));
326 TEST_BARRIER_WAIT_ALARM(pid1
),
328 sleep_for(BASE_TIME
* 2);
330 TEST_BARRIER_WAIT_SUCCESS(pid2
));
333 * Test matched wait_abortion() with local abortion
334 * This runs wait_abortion() with local and remote abortion.
336 TEST_BARRIER(test_barrier_wait_abortion_local
,
338 set_alarm(BASE_TIME
* 10);
339 assert_se(barrier_abort(&b
));
340 assert_se(!barrier_wait_abortion(&b
));
342 TEST_BARRIER_WAIT_SUCCESS(pid1
),
344 assert_se(barrier_abort(&b
));
346 TEST_BARRIER_WAIT_SUCCESS(pid2
));
349 * Test unmatched wait_abortion() with local abortion
350 * This runs wait_abortion() with only local abortion. This must time out.
352 TEST_BARRIER(test_barrier_wait_abortion_local_unmatched
,
354 set_alarm(BASE_TIME
);
355 assert_se(barrier_abort(&b
));
356 assert_se(!barrier_wait_abortion(&b
));
359 TEST_BARRIER_WAIT_ALARM(pid1
),
361 sleep_for(BASE_TIME
* 2);
363 TEST_BARRIER_WAIT_SUCCESS(pid2
));
367 * Place barrier and sync with the child. The child only exits()s, which should
368 * cause an implicit abortion and wake the parent.
370 TEST_BARRIER(test_barrier_exit
,
373 TEST_BARRIER_WAIT_SUCCESS(pid1
),
375 set_alarm(BASE_TIME
* 10);
376 assert_se(barrier_place(&b
));
377 assert_se(!barrier_sync(&b
));
379 TEST_BARRIER_WAIT_SUCCESS(pid2
));
382 * Test child exit with sleep
383 * Same as test_barrier_exit but verifies the test really works due to the
384 * child-exit. We add a usleep() which triggers the alarm in the parent and
385 * causes the test to time out.
387 TEST_BARRIER(test_barrier_no_exit
,
389 sleep_for(BASE_TIME
* 2);
391 TEST_BARRIER_WAIT_SUCCESS(pid1
),
393 set_alarm(BASE_TIME
);
394 assert_se(barrier_place(&b
));
395 assert_se(!barrier_sync(&b
));
397 TEST_BARRIER_WAIT_ALARM(pid2
));
400 * Test pending exit against sync
401 * The parent places a barrier *and* exits. The 20ms wait in the child
402 * guarantees both are pending. However, our logic prefers pending barriers over
403 * pending exit-abortions (unlike normal abortions), thus the wait_next() must
404 * succeed, same for the sync_next() as our local barrier-count is smaller than
405 * the remote. Once we place a barrier our count is equal, so the sync still
406 * succeeds. Only if we place one more barrier, we're ahead of the remote, thus
407 * we will fail due to HUP on the pipe.
409 TEST_BARRIER(test_barrier_pending_exit
,
411 set_alarm(BASE_TIME
* 4);
412 sleep_for(BASE_TIME
* 2);
413 assert_se(barrier_wait_next(&b
));
414 assert_se(barrier_sync_next(&b
));
415 assert_se(barrier_place(&b
));
416 assert_se(barrier_sync_next(&b
));
417 assert_se(barrier_place(&b
));
418 assert_se(!barrier_sync_next(&b
));
420 TEST_BARRIER_WAIT_SUCCESS(pid1
),
422 assert_se(barrier_place(&b
));
424 TEST_BARRIER_WAIT_SUCCESS(pid2
));
426 int main(int argc
, char *argv
[]) {
428 * This test uses real-time alarms and sleeps to test for CPU races
429 * explicitly. This is highly fragile if your system is under load. We
430 * already increased the BASE_TIME value to make the tests more robust,
431 * but that just makes the test take significantly longer. Hence,
432 * disable the test by default, so it will not break CI.
435 return EXIT_TEST_SKIP
;
437 log_parse_environment();
441 test_barrier_wait_next();
442 test_barrier_wait_next_twice();
443 test_barrier_wait_next_twice_sync();
444 test_barrier_wait_next_twice_local();
445 test_barrier_wait_next_twice_local_sync();
446 test_barrier_sync_next();
447 test_barrier_sync_next_local();
448 test_barrier_sync_next_local_abort();
449 test_barrier_wait_abortion();
450 test_barrier_wait_abortion_unmatched();
451 test_barrier_wait_abortion_local();
452 test_barrier_wait_abortion_local_unmatched();
454 test_barrier_no_exit();
455 test_barrier_pending_exit();