1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 * These tests verify the correct behavior of the IPC Barrier implementation.
25 * Note that the tests use alarm-timers to verify dead-locks and timeouts. These
26 * might not work on slow machines where 20ms are too short to perform specific
27 * operations (though, very unlikely). In case that turns out true, we have to
28 * increase it at the slightly cost of lengthen test-duration on other machines.
42 /* 20ms to test deadlocks; All timings use multiples of this constant as
43 * alarm/sleep timers. If this timeout is too small for slow machines to perform
44 * the requested operations, we have to increase it. On an i7 this works fine
45 * with 1ms base-time, so 20ms should be just fine for everyone. */
46 #define BASE_TIME (20 * USEC_PER_MSEC)
48 static void set_alarm(usec_t usecs) {
49 struct itimerval v = { };
51 timeval_store(&v.it_value, usecs);
52 assert_se(setitimer(ITIMER_REAL, &v, NULL) >= 0);
55 static void sleep_for(usec_t usecs) {
56 /* stupid usleep() might fail if >1000000 */
57 assert_se(usecs < USEC_PER_SEC);
61 #define TEST_BARRIER(_FUNCTION, _CHILD_CODE, _WAIT_CHILD, _PARENT_CODE, _WAIT_PARENT) \
62 static void _FUNCTION(void) { \
63 Barrier b = BARRIER_NULL; \
66 assert_se(barrier_create(&b) >= 0); \
67 assert_se(b.me > 0); \
68 assert_se(b.them > 0); \
69 assert_se(b.pipe[0] > 0); \
70 assert_se(b.pipe[1] > 0); \
73 assert_se(pid1 >= 0); \
75 barrier_set_role(&b, BARRIER_CHILD); \
81 assert_se(pid2 >= 0); \
83 barrier_set_role(&b, BARRIER_PARENT); \
88 barrier_destroy(&b); \
95 #define TEST_BARRIER_WAIT_SUCCESS(_pid) \
98 pidr = waitpid(_pid, &status, 0); \
99 assert_se(pidr == _pid); \
100 assert_se(WIFEXITED(status)); \
101 assert_se(WEXITSTATUS(status) == 42); \
104 #define TEST_BARRIER_WAIT_ALARM(_pid) \
107 pidr = waitpid(_pid, &status, 0); \
108 assert_se(pidr == _pid); \
109 assert_se(WIFSIGNALED(status)); \
110 assert_se(WTERMSIG(status) == SIGALRM); \
114 * Test basic sync points
115 * This places a barrier in both processes and waits synchronously for them.
116 * The timeout makes sure the sync works as expected. The sleep_for() on one side
117 * makes sure the exit of the parent does not overwrite previous barriers. Due
118 * to the sleep_for(), we know that the parent already exited, thus there's a
119 * pending HUP on the pipe. However, the barrier_sync() prefers reads on the
120 * eventfd, thus we can safely wait on the barrier.
122 TEST_BARRIER(test_barrier_sync,
124 set_alarm(BASE_TIME * 10);
125 assert_se(barrier_place(&b));
126 sleep_for(BASE_TIME * 2);
127 assert_se(barrier_sync(&b));
129 TEST_BARRIER_WAIT_SUCCESS(pid1),
131 set_alarm(BASE_TIME * 10);
132 assert_se(barrier_place(&b));
133 assert_se(barrier_sync(&b));
135 TEST_BARRIER_WAIT_SUCCESS(pid2));
139 * This places a barrier in the parent and syncs on it. The child sleeps while
140 * the parent places the barrier and then waits for a barrier. The wait will
141 * succeed as the child hasn't read the parent's barrier, yet. The following
142 * barrier and sync synchronize the exit.
144 TEST_BARRIER(test_barrier_wait_next,
146 sleep_for(BASE_TIME);
147 set_alarm(BASE_TIME * 10);
148 assert_se(barrier_wait_next(&b));
149 assert_se(barrier_place(&b));
150 assert_se(barrier_sync(&b));
152 TEST_BARRIER_WAIT_SUCCESS(pid1),
154 set_alarm(BASE_TIME * 4);
155 assert_se(barrier_place(&b));
156 assert_se(barrier_sync(&b));
158 TEST_BARRIER_WAIT_SUCCESS(pid2));
161 * Test wait_next() multiple times
162 * This places two barriers in the parent and waits for the child to exit. The
163 * child sleeps 20ms so both barriers _should_ be in place. It then waits for
164 * the parent to place the next barrier twice. The first call will fetch both
165 * barriers and return. However, the second call will stall as the parent does
166 * not place a 3rd barrier (the sleep caught two barriers). wait_next() is does
167 * not look at barrier-links so this stall is expected. Thus this test times
170 TEST_BARRIER(test_barrier_wait_next_twice,
172 sleep_for(BASE_TIME);
173 set_alarm(BASE_TIME);
174 assert_se(barrier_wait_next(&b));
175 assert_se(barrier_wait_next(&b));
178 TEST_BARRIER_WAIT_ALARM(pid1),
180 set_alarm(BASE_TIME * 10);
181 assert_se(barrier_place(&b));
182 assert_se(barrier_place(&b));
183 sleep_for(BASE_TIME * 4);
185 TEST_BARRIER_WAIT_SUCCESS(pid2));
188 * Test wait_next() with local barriers
189 * This is the same as test_barrier_wait_next_twice, but places local barriers
190 * between both waits. This does not have any effect on the wait so it times out
191 * like the other test.
193 TEST_BARRIER(test_barrier_wait_next_twice_local,
195 sleep_for(BASE_TIME);
196 set_alarm(BASE_TIME);
197 assert_se(barrier_wait_next(&b));
198 assert_se(barrier_place(&b));
199 assert_se(barrier_place(&b));
200 assert_se(barrier_wait_next(&b));
203 TEST_BARRIER_WAIT_ALARM(pid1),
205 set_alarm(BASE_TIME * 10);
206 assert_se(barrier_place(&b));
207 assert_se(barrier_place(&b));
208 sleep_for(BASE_TIME * 4);
210 TEST_BARRIER_WAIT_SUCCESS(pid2));
213 * Test wait_next() with sync_next()
214 * This is again the same as test_barrier_wait_next_twice but uses a
215 * synced wait as the second wait. This works just fine because the local state
216 * has no barriers placed, therefore, the remote is always in sync.
218 TEST_BARRIER(test_barrier_wait_next_twice_sync,
220 sleep_for(BASE_TIME);
221 set_alarm(BASE_TIME);
222 assert_se(barrier_wait_next(&b));
223 assert_se(barrier_sync_next(&b));
225 TEST_BARRIER_WAIT_SUCCESS(pid1),
227 set_alarm(BASE_TIME * 10);
228 assert_se(barrier_place(&b));
229 assert_se(barrier_place(&b));
231 TEST_BARRIER_WAIT_SUCCESS(pid2));
234 * Test wait_next() with sync_next() and local barriers
235 * This is again the same as test_barrier_wait_next_twice_local but uses a
236 * synced wait as the second wait. This works just fine because the local state
237 * is in sync with the remote.
239 TEST_BARRIER(test_barrier_wait_next_twice_local_sync,
241 sleep_for(BASE_TIME);
242 set_alarm(BASE_TIME);
243 assert_se(barrier_wait_next(&b));
244 assert_se(barrier_place(&b));
245 assert_se(barrier_place(&b));
246 assert_se(barrier_sync_next(&b));
248 TEST_BARRIER_WAIT_SUCCESS(pid1),
250 set_alarm(BASE_TIME * 10);
251 assert_se(barrier_place(&b));
252 assert_se(barrier_place(&b));
254 TEST_BARRIER_WAIT_SUCCESS(pid2));
257 * Test sync_next() and sync()
258 * This tests sync_*() synchronizations and makes sure they work fine if the
259 * local state is behind the remote state.
261 TEST_BARRIER(test_barrier_sync_next,
263 set_alarm(BASE_TIME * 10);
264 assert_se(barrier_sync_next(&b));
265 assert_se(barrier_sync(&b));
266 assert_se(barrier_place(&b));
267 assert_se(barrier_place(&b));
268 assert_se(barrier_sync_next(&b));
269 assert_se(barrier_sync_next(&b));
270 assert_se(barrier_sync(&b));
272 TEST_BARRIER_WAIT_SUCCESS(pid1),
274 set_alarm(BASE_TIME * 10);
275 sleep_for(BASE_TIME);
276 assert_se(barrier_place(&b));
277 assert_se(barrier_place(&b));
278 assert_se(barrier_sync(&b));
280 TEST_BARRIER_WAIT_SUCCESS(pid2));
283 * Test sync_next() and sync() with local barriers
284 * This tests timeouts if sync_*() is used if local barriers are placed but the
285 * remote didn't place any.
287 TEST_BARRIER(test_barrier_sync_next_local,
289 set_alarm(BASE_TIME);
290 assert_se(barrier_place(&b));
291 assert_se(barrier_sync_next(&b));
294 TEST_BARRIER_WAIT_ALARM(pid1),
296 sleep_for(BASE_TIME * 2);
298 TEST_BARRIER_WAIT_SUCCESS(pid2));
301 * Test sync_next() and sync() with local barriers and abortion
302 * This is the same as test_barrier_sync_next_local but aborts the sync in the
303 * parent. Therefore, the sync_next() succeeds just fine due to the abortion.
305 TEST_BARRIER(test_barrier_sync_next_local_abort,
307 set_alarm(BASE_TIME * 10);
308 assert_se(barrier_place(&b));
309 assert_se(!barrier_sync_next(&b));
311 TEST_BARRIER_WAIT_SUCCESS(pid1),
313 assert_se(barrier_abort(&b));
315 TEST_BARRIER_WAIT_SUCCESS(pid2));
318 * Test matched wait_abortion()
319 * This runs wait_abortion() with remote abortion.
321 TEST_BARRIER(test_barrier_wait_abortion,
323 set_alarm(BASE_TIME * 10);
324 assert_se(barrier_wait_abortion(&b));
326 TEST_BARRIER_WAIT_SUCCESS(pid1),
328 assert_se(barrier_abort(&b));
330 TEST_BARRIER_WAIT_SUCCESS(pid2));
333 * Test unmatched wait_abortion()
334 * This runs wait_abortion() without any remote abortion going on. It thus must
337 TEST_BARRIER(test_barrier_wait_abortion_unmatched,
339 set_alarm(BASE_TIME);
340 assert_se(barrier_wait_abortion(&b));
343 TEST_BARRIER_WAIT_ALARM(pid1),
345 sleep_for(BASE_TIME * 2);
347 TEST_BARRIER_WAIT_SUCCESS(pid2));
350 * Test matched wait_abortion() with local abortion
351 * This runs wait_abortion() with local and remote abortion.
353 TEST_BARRIER(test_barrier_wait_abortion_local,
355 set_alarm(BASE_TIME * 10);
356 assert_se(barrier_abort(&b));
357 assert_se(!barrier_wait_abortion(&b));
359 TEST_BARRIER_WAIT_SUCCESS(pid1),
361 assert_se(barrier_abort(&b));
363 TEST_BARRIER_WAIT_SUCCESS(pid2));
366 * Test unmatched wait_abortion() with local abortion
367 * This runs wait_abortion() with only local abortion. This must time out.
369 TEST_BARRIER(test_barrier_wait_abortion_local_unmatched,
371 set_alarm(BASE_TIME);
372 assert_se(barrier_abort(&b));
373 assert_se(!barrier_wait_abortion(&b));
376 TEST_BARRIER_WAIT_ALARM(pid1),
378 sleep_for(BASE_TIME * 2);
380 TEST_BARRIER_WAIT_SUCCESS(pid2));
384 * Place barrier and sync with the child. The child only exits()s, which should
385 * cause an implicit abortion and wake the parent.
387 TEST_BARRIER(test_barrier_exit,
390 TEST_BARRIER_WAIT_SUCCESS(pid1),
392 set_alarm(BASE_TIME * 10);
393 assert_se(barrier_place(&b));
394 assert_se(!barrier_sync(&b));
396 TEST_BARRIER_WAIT_SUCCESS(pid2));
399 * Test child exit with sleep
400 * Same as test_barrier_exit but verifies the test really works due to the
401 * child-exit. We add a usleep() which triggers the alarm in the parent and
402 * causes the test to time out.
404 TEST_BARRIER(test_barrier_no_exit,
406 sleep_for(BASE_TIME * 2);
408 TEST_BARRIER_WAIT_SUCCESS(pid1),
410 set_alarm(BASE_TIME);
411 assert_se(barrier_place(&b));
412 assert_se(!barrier_sync(&b));
414 TEST_BARRIER_WAIT_ALARM(pid2));
417 * Test pending exit against sync
418 * The parent places a barrier *and* exits. The 20ms wait in the child
419 * guarantees both are pending. However, our logic prefers pending barriers over
420 * pending exit-abortions (unlike normal abortions), thus the wait_next() must
421 * succeed, same for the sync_next() as our local barrier-count is smaller than
422 * the remote. Once we place a barrier our count is equal, so the sync still
423 * succeeds. Only if we place one more barrier, we're ahead of the remote, thus
424 * we will fail due to HUP on the pipe.
426 TEST_BARRIER(test_barrier_pending_exit,
428 set_alarm(BASE_TIME * 4);
429 sleep_for(BASE_TIME * 2);
430 assert_se(barrier_wait_next(&b));
431 assert_se(barrier_sync_next(&b));
432 assert_se(barrier_place(&b));
433 assert_se(barrier_sync_next(&b));
434 assert_se(barrier_place(&b));
435 assert_se(!barrier_sync_next(&b));
437 TEST_BARRIER_WAIT_SUCCESS(pid1),
439 assert_se(barrier_place(&b));
441 TEST_BARRIER_WAIT_SUCCESS(pid2));
443 int main(int argc, char *argv[]) {
444 log_parse_environment();
448 test_barrier_wait_next();
449 test_barrier_wait_next_twice();
450 test_barrier_wait_next_twice_sync();
451 test_barrier_wait_next_twice_local();
452 test_barrier_wait_next_twice_local_sync();
453 test_barrier_sync_next();
454 test_barrier_sync_next_local();
455 test_barrier_sync_next_local_abort();
456 test_barrier_wait_abortion();
457 test_barrier_wait_abortion_unmatched();
458 test_barrier_wait_abortion_local();
459 test_barrier_wait_abortion_local_unmatched();
461 test_barrier_no_exit();
462 test_barrier_pending_exit();