1 /* SPDX-License-Identifier: LGPL-2.1+ */
5 * These tests verify the correct behavior of the IPC Barrier implementation.
6 * Note that the tests use alarm-timers to verify dead-locks and timeouts. These
7 * might not work on slow machines where 20ms are too short to perform specific
8 * operations (though, very unlikely). In case that turns out true, we have to
9 * increase it at the slightly cost of lengthen test-duration on other machines.
21 #include "time-util.h"
23 /* 20ms to test deadlocks; All timings use multiples of this constant as
24 * alarm/sleep timers. If this timeout is too small for slow machines to perform
25 * the requested operations, we have to increase it. On an i7 this works fine
26 * with 1ms base-time, so 20ms should be just fine for everyone. */
27 #define BASE_TIME (20 * USEC_PER_MSEC)
29 static void set_alarm(usec_t usecs
) {
30 struct itimerval v
= { };
32 timeval_store(&v
.it_value
, usecs
);
33 assert_se(setitimer(ITIMER_REAL
, &v
, NULL
) >= 0);
36 static void sleep_for(usec_t usecs
) {
37 /* stupid usleep() might fail if >1000000 */
38 assert_se(usecs
< USEC_PER_SEC
);
42 #define TEST_BARRIER(_FUNCTION, _CHILD_CODE, _WAIT_CHILD, _PARENT_CODE, _WAIT_PARENT) \
43 static void _FUNCTION(void) { \
44 Barrier b = BARRIER_NULL; \
47 assert_se(barrier_create(&b) >= 0); \
48 assert_se(b.me > 0); \
49 assert_se(b.them > 0); \
50 assert_se(b.pipe[0] > 0); \
51 assert_se(b.pipe[1] > 0); \
54 assert_se(pid1 >= 0); \
56 barrier_set_role(&b, BARRIER_CHILD); \
62 assert_se(pid2 >= 0); \
64 barrier_set_role(&b, BARRIER_PARENT); \
69 barrier_destroy(&b); \
76 #define TEST_BARRIER_WAIT_SUCCESS(_pid) \
79 pidr = waitpid(_pid, &status, 0); \
80 assert_se(pidr == _pid); \
81 assert_se(WIFEXITED(status)); \
82 assert_se(WEXITSTATUS(status) == 42); \
85 #define TEST_BARRIER_WAIT_ALARM(_pid) \
88 pidr = waitpid(_pid, &status, 0); \
89 assert_se(pidr == _pid); \
90 assert_se(WIFSIGNALED(status)); \
91 assert_se(WTERMSIG(status) == SIGALRM); \
95 * Test basic sync points
96 * This places a barrier in both processes and waits synchronously for them.
97 * The timeout makes sure the sync works as expected. The sleep_for() on one side
98 * makes sure the exit of the parent does not overwrite previous barriers. Due
99 * to the sleep_for(), we know that the parent already exited, thus there's a
100 * pending HUP on the pipe. However, the barrier_sync() prefers reads on the
101 * eventfd, thus we can safely wait on the barrier.
103 TEST_BARRIER(test_barrier_sync
,
105 set_alarm(BASE_TIME
* 10);
106 assert_se(barrier_place(&b
));
107 sleep_for(BASE_TIME
* 2);
108 assert_se(barrier_sync(&b
));
110 TEST_BARRIER_WAIT_SUCCESS(pid1
),
112 set_alarm(BASE_TIME
* 10);
113 assert_se(barrier_place(&b
));
114 assert_se(barrier_sync(&b
));
116 TEST_BARRIER_WAIT_SUCCESS(pid2
));
120 * This places a barrier in the parent and syncs on it. The child sleeps while
121 * the parent places the barrier and then waits for a barrier. The wait will
122 * succeed as the child hasn't read the parent's barrier, yet. The following
123 * barrier and sync synchronize the exit.
125 TEST_BARRIER(test_barrier_wait_next
,
127 sleep_for(BASE_TIME
);
128 set_alarm(BASE_TIME
* 10);
129 assert_se(barrier_wait_next(&b
));
130 assert_se(barrier_place(&b
));
131 assert_se(barrier_sync(&b
));
133 TEST_BARRIER_WAIT_SUCCESS(pid1
),
135 set_alarm(BASE_TIME
* 4);
136 assert_se(barrier_place(&b
));
137 assert_se(barrier_sync(&b
));
139 TEST_BARRIER_WAIT_SUCCESS(pid2
));
142 * Test wait_next() multiple times
143 * This places two barriers in the parent and waits for the child to exit. The
144 * child sleeps 20ms so both barriers _should_ be in place. It then waits for
145 * the parent to place the next barrier twice. The first call will fetch both
146 * barriers and return. However, the second call will stall as the parent does
147 * not place a 3rd barrier (the sleep caught two barriers). wait_next() is does
148 * not look at barrier-links so this stall is expected. Thus this test times
151 TEST_BARRIER(test_barrier_wait_next_twice
,
153 sleep_for(BASE_TIME
);
154 set_alarm(BASE_TIME
);
155 assert_se(barrier_wait_next(&b
));
156 assert_se(barrier_wait_next(&b
));
159 TEST_BARRIER_WAIT_ALARM(pid1
),
161 set_alarm(BASE_TIME
* 10);
162 assert_se(barrier_place(&b
));
163 assert_se(barrier_place(&b
));
164 sleep_for(BASE_TIME
* 4);
166 TEST_BARRIER_WAIT_SUCCESS(pid2
));
169 * Test wait_next() with local barriers
170 * This is the same as test_barrier_wait_next_twice, but places local barriers
171 * between both waits. This does not have any effect on the wait so it times out
172 * like the other test.
174 TEST_BARRIER(test_barrier_wait_next_twice_local
,
176 sleep_for(BASE_TIME
);
177 set_alarm(BASE_TIME
);
178 assert_se(barrier_wait_next(&b
));
179 assert_se(barrier_place(&b
));
180 assert_se(barrier_place(&b
));
181 assert_se(barrier_wait_next(&b
));
184 TEST_BARRIER_WAIT_ALARM(pid1
),
186 set_alarm(BASE_TIME
* 10);
187 assert_se(barrier_place(&b
));
188 assert_se(barrier_place(&b
));
189 sleep_for(BASE_TIME
* 4);
191 TEST_BARRIER_WAIT_SUCCESS(pid2
));
194 * Test wait_next() with sync_next()
195 * This is again the same as test_barrier_wait_next_twice but uses a
196 * synced wait as the second wait. This works just fine because the local state
197 * has no barriers placed, therefore, the remote is always in sync.
199 TEST_BARRIER(test_barrier_wait_next_twice_sync
,
201 sleep_for(BASE_TIME
);
202 set_alarm(BASE_TIME
);
203 assert_se(barrier_wait_next(&b
));
204 assert_se(barrier_sync_next(&b
));
206 TEST_BARRIER_WAIT_SUCCESS(pid1
),
208 set_alarm(BASE_TIME
* 10);
209 assert_se(barrier_place(&b
));
210 assert_se(barrier_place(&b
));
212 TEST_BARRIER_WAIT_SUCCESS(pid2
));
215 * Test wait_next() with sync_next() and local barriers
216 * This is again the same as test_barrier_wait_next_twice_local but uses a
217 * synced wait as the second wait. This works just fine because the local state
218 * is in sync with the remote.
220 TEST_BARRIER(test_barrier_wait_next_twice_local_sync
,
222 sleep_for(BASE_TIME
);
223 set_alarm(BASE_TIME
);
224 assert_se(barrier_wait_next(&b
));
225 assert_se(barrier_place(&b
));
226 assert_se(barrier_place(&b
));
227 assert_se(barrier_sync_next(&b
));
229 TEST_BARRIER_WAIT_SUCCESS(pid1
),
231 set_alarm(BASE_TIME
* 10);
232 assert_se(barrier_place(&b
));
233 assert_se(barrier_place(&b
));
235 TEST_BARRIER_WAIT_SUCCESS(pid2
));
238 * Test sync_next() and sync()
239 * This tests sync_*() synchronizations and makes sure they work fine if the
240 * local state is behind the remote state.
242 TEST_BARRIER(test_barrier_sync_next
,
244 set_alarm(BASE_TIME
* 10);
245 assert_se(barrier_sync_next(&b
));
246 assert_se(barrier_sync(&b
));
247 assert_se(barrier_place(&b
));
248 assert_se(barrier_place(&b
));
249 assert_se(barrier_sync_next(&b
));
250 assert_se(barrier_sync_next(&b
));
251 assert_se(barrier_sync(&b
));
253 TEST_BARRIER_WAIT_SUCCESS(pid1
),
255 set_alarm(BASE_TIME
* 10);
256 sleep_for(BASE_TIME
);
257 assert_se(barrier_place(&b
));
258 assert_se(barrier_place(&b
));
259 assert_se(barrier_sync(&b
));
261 TEST_BARRIER_WAIT_SUCCESS(pid2
));
264 * Test sync_next() and sync() with local barriers
265 * This tests timeouts if sync_*() is used if local barriers are placed but the
266 * remote didn't place any.
268 TEST_BARRIER(test_barrier_sync_next_local
,
270 set_alarm(BASE_TIME
);
271 assert_se(barrier_place(&b
));
272 assert_se(barrier_sync_next(&b
));
275 TEST_BARRIER_WAIT_ALARM(pid1
),
277 sleep_for(BASE_TIME
* 2);
279 TEST_BARRIER_WAIT_SUCCESS(pid2
));
282 * Test sync_next() and sync() with local barriers and abortion
283 * This is the same as test_barrier_sync_next_local but aborts the sync in the
284 * parent. Therefore, the sync_next() succeeds just fine due to the abortion.
286 TEST_BARRIER(test_barrier_sync_next_local_abort
,
288 set_alarm(BASE_TIME
* 10);
289 assert_se(barrier_place(&b
));
290 assert_se(!barrier_sync_next(&b
));
292 TEST_BARRIER_WAIT_SUCCESS(pid1
),
294 assert_se(barrier_abort(&b
));
296 TEST_BARRIER_WAIT_SUCCESS(pid2
));
299 * Test matched wait_abortion()
300 * This runs wait_abortion() with remote abortion.
302 TEST_BARRIER(test_barrier_wait_abortion
,
304 set_alarm(BASE_TIME
* 10);
305 assert_se(barrier_wait_abortion(&b
));
307 TEST_BARRIER_WAIT_SUCCESS(pid1
),
309 assert_se(barrier_abort(&b
));
311 TEST_BARRIER_WAIT_SUCCESS(pid2
));
314 * Test unmatched wait_abortion()
315 * This runs wait_abortion() without any remote abortion going on. It thus must
318 TEST_BARRIER(test_barrier_wait_abortion_unmatched
,
320 set_alarm(BASE_TIME
);
321 assert_se(barrier_wait_abortion(&b
));
324 TEST_BARRIER_WAIT_ALARM(pid1
),
326 sleep_for(BASE_TIME
* 2);
328 TEST_BARRIER_WAIT_SUCCESS(pid2
));
331 * Test matched wait_abortion() with local abortion
332 * This runs wait_abortion() with local and remote abortion.
334 TEST_BARRIER(test_barrier_wait_abortion_local
,
336 set_alarm(BASE_TIME
* 10);
337 assert_se(barrier_abort(&b
));
338 assert_se(!barrier_wait_abortion(&b
));
340 TEST_BARRIER_WAIT_SUCCESS(pid1
),
342 assert_se(barrier_abort(&b
));
344 TEST_BARRIER_WAIT_SUCCESS(pid2
));
347 * Test unmatched wait_abortion() with local abortion
348 * This runs wait_abortion() with only local abortion. This must time out.
350 TEST_BARRIER(test_barrier_wait_abortion_local_unmatched
,
352 set_alarm(BASE_TIME
);
353 assert_se(barrier_abort(&b
));
354 assert_se(!barrier_wait_abortion(&b
));
357 TEST_BARRIER_WAIT_ALARM(pid1
),
359 sleep_for(BASE_TIME
* 2);
361 TEST_BARRIER_WAIT_SUCCESS(pid2
));
365 * Place barrier and sync with the child. The child only exits()s, which should
366 * cause an implicit abortion and wake the parent.
368 TEST_BARRIER(test_barrier_exit
,
371 TEST_BARRIER_WAIT_SUCCESS(pid1
),
373 set_alarm(BASE_TIME
* 10);
374 assert_se(barrier_place(&b
));
375 assert_se(!barrier_sync(&b
));
377 TEST_BARRIER_WAIT_SUCCESS(pid2
));
380 * Test child exit with sleep
381 * Same as test_barrier_exit but verifies the test really works due to the
382 * child-exit. We add a usleep() which triggers the alarm in the parent and
383 * causes the test to time out.
385 TEST_BARRIER(test_barrier_no_exit
,
387 sleep_for(BASE_TIME
* 2);
389 TEST_BARRIER_WAIT_SUCCESS(pid1
),
391 set_alarm(BASE_TIME
);
392 assert_se(barrier_place(&b
));
393 assert_se(!barrier_sync(&b
));
395 TEST_BARRIER_WAIT_ALARM(pid2
));
398 * Test pending exit against sync
399 * The parent places a barrier *and* exits. The 20ms wait in the child
400 * guarantees both are pending. However, our logic prefers pending barriers over
401 * pending exit-abortions (unlike normal abortions), thus the wait_next() must
402 * succeed, same for the sync_next() as our local barrier-count is smaller than
403 * the remote. Once we place a barrier our count is equal, so the sync still
404 * succeeds. Only if we place one more barrier, we're ahead of the remote, thus
405 * we will fail due to HUP on the pipe.
407 TEST_BARRIER(test_barrier_pending_exit
,
409 set_alarm(BASE_TIME
* 4);
410 sleep_for(BASE_TIME
* 2);
411 assert_se(barrier_wait_next(&b
));
412 assert_se(barrier_sync_next(&b
));
413 assert_se(barrier_place(&b
));
414 assert_se(barrier_sync_next(&b
));
415 assert_se(barrier_place(&b
));
416 assert_se(!barrier_sync_next(&b
));
418 TEST_BARRIER_WAIT_SUCCESS(pid1
),
420 assert_se(barrier_place(&b
));
422 TEST_BARRIER_WAIT_SUCCESS(pid2
));
424 int main(int argc
, char *argv
[]) {
426 test_setup_logging(LOG_INFO
);
428 if (!slow_tests_enabled())
429 return log_tests_skipped("slow tests are disabled");
432 * This test uses real-time alarms and sleeps to test for CPU races
433 * explicitly. This is highly fragile if your system is under load. We
434 * already increased the BASE_TIME value to make the tests more robust,
435 * but that just makes the test take significantly longer. Given the recent
436 * issues when running the test in a virtualized environments, limit it
437 * to bare metal machines only, to minimize false-positives in CIs.
439 v
= detect_virtualization();
440 if (IN_SET(v
, -EPERM
, -EACCES
))
441 return log_tests_skipped("Cannot detect virtualization");
443 if (v
!= VIRTUALIZATION_NONE
)
444 return log_tests_skipped("This test requires a baremetal machine");
447 test_barrier_wait_next();
448 test_barrier_wait_next_twice();
449 test_barrier_wait_next_twice_sync();
450 test_barrier_wait_next_twice_local();
451 test_barrier_wait_next_twice_local_sync();
452 test_barrier_sync_next();
453 test_barrier_sync_next_local();
454 test_barrier_sync_next_local_abort();
455 test_barrier_wait_abortion();
456 test_barrier_wait_abortion_unmatched();
457 test_barrier_wait_abortion_local();
458 test_barrier_wait_abortion_local_unmatched();
460 test_barrier_no_exit();
461 test_barrier_pending_exit();