xref: /haiku/src/tests/system/libroot/posix/realtime_sem_test1.cpp (revision cefb069022202b5aca22614b93cb4e3b810a8e7a)
1 /*
2  * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <semaphore.h>
14 #include <sys/mman.h>
15 #include <sys/stat.h>
16 #include <sys/time.h>
17 #include <sys/wait.h>
18 #include <time.h>
19 
20 
21 #ifdef __HAIKU__
22 #	include <OS.h>
23 #else
24 
25 typedef int64_t bigtime_t;
26 
27 static bigtime_t
system_time()28 system_time()
29 {
30 	timeval tv;
31 	gettimeofday(&tv, NULL);
32 	return (bigtime_t)tv.tv_sec * 1000000 + tv.tv_usec;
33 }
34 
35 
36 #endif	// !__HAIKU__
37 
38 #include "TestUnitUtils.h"
39 
40 #if 0
41 static void
42 dump_sem(const char* name, sem_t* sem)
43 {
44 	printf("%s, %p: ", name, sem);
45 	for (size_t i = 0; i < sizeof(sem_t); i++)
46 		printf("%02x", ((char*)sem)[i]);
47 	printf("\n");
48 }
49 #endif
50 
51 
52 static const char* const kSemName1 = "/test_sem1";
53 
54 
55 static void
test_open_close_unlink()56 test_open_close_unlink()
57 {
58 	TEST_SET("sem_{open,close,unlink}()");
59 
60 	const char* currentTest = NULL;
61 
62 	// open non-existing with O_CREAT
63 	TEST("sem_open(O_CREAT) non-existing");
64 	sem_t* sem = sem_open(kSemName1, O_CREAT, S_IRUSR | S_IWUSR, 1);
65 	assert_posix_bool_success(sem != SEM_FAILED);
66 
67 	// close
68 	TEST("sem_close()");
69 	assert_posix_success(sem_close(sem));
70 
71 	// open existing with O_CREAT
72 	TEST("sem_open(O_CREAT) existing");
73 	sem = sem_open(kSemName1, O_CREAT, S_IRUSR | S_IWUSR, 1);
74 	assert_posix_bool_success(sem != SEM_FAILED);
75 
76 	// close
77 	TEST("sem_close()");
78 	assert_posix_success(sem_close(sem));
79 
80 	// open existing without O_CREAT
81 	TEST("sem_open() existing");
82 	sem = sem_open(kSemName1, 0);
83 	assert_posix_bool_success(sem != SEM_FAILED);
84 
85 	// re-open existing without O_CREAT
86 	TEST("sem_open() existing");
87 	sem_t* sem2 = sem_open(kSemName1, 0);
88 	assert_posix_bool_success(sem2 != SEM_FAILED);
89 	assert_equals(sem, sem2);
90 
91 	// close
92 	TEST("sem_close()");
93 	assert_posix_success(sem_close(sem));
94 
95 	// close
96 	TEST("sem_close()");
97 	assert_posix_success(sem_close(sem));
98 
99 	// open existing with O_CREAT | O_EXCL
100 	TEST("sem_open(O_CREAT | O_EXCL) existing");
101 	sem = sem_open(kSemName1, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1);
102 	assert_posix_bool_error(EEXIST, sem != SEM_FAILED);
103 
104 	// open existing without O_CREAT
105 	TEST("sem_open() existing");
106 	sem = sem_open(kSemName1, 0);
107 	assert_posix_bool_success(sem != SEM_FAILED);
108 
109 	// unlink
110 	TEST("unlink() existing");
111 	assert_posix_success(sem_unlink(kSemName1));
112 
113 	// open non-existing with O_CREAT | O_EXCL
114 	TEST("sem_open(O_CREAT | O_EXCL) non-existing");
115 	sem2 = sem_open(kSemName1, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 2);
116 	assert_posix_bool_success(sem2 != SEM_FAILED);
117 	assert_equals_not(sem, sem2);
118 
119 	// unlink
120 	TEST("unlink() existing");
121 	assert_posix_success(sem_unlink(kSemName1));
122 
123 	// unlink
124 	TEST("unlink() non-existing");
125 	assert_posix_error(ENOENT, sem_unlink(kSemName1));
126 
127 	// close
128 	TEST("sem_close()");
129 	assert_posix_success(sem_close(sem));
130 
131 	// close
132 	TEST("sem_close()");
133 	assert_posix_success(sem_close(sem2));
134 
135 	TEST("done");
136 }
137 
138 
139 static void
test_init_destroy()140 test_init_destroy()
141 {
142 	TEST_SET("sem_{init,destroy}()");
143 
144 	const char* currentTest = NULL;
145 
146 	// init
147 	TEST("sem_init()");
148 	sem_t sem;
149 	assert_posix_success(sem_init(&sem, 0, 1));
150 
151 	// destroy
152 	TEST("sem_destroy()");
153 	assert_posix_success(sem_destroy(&sem));
154 
155 	// init
156 	TEST("sem_init()");
157 	assert_posix_success(sem_init(&sem, 0, 1));
158 
159 	// init
160 	TEST("sem_init()");
161 	sem_t sem2;
162 	assert_posix_success(sem_init(&sem2, 0, 2));
163 
164 	// destroy
165 	TEST("sem_destroy()");
166 	assert_posix_success(sem_destroy(&sem));
167 
168 	// destroy
169 	TEST("sem_destroy()");
170 	assert_posix_success(sem_destroy(&sem2));
171 
172 	TEST("done");
173 }
174 
175 
176 static void
test_open_close_fork()177 test_open_close_fork()
178 {
179 	TEST_SET("sem_{open,close}() with fork()");
180 
181 	const char* currentTest = NULL;
182 
183 	// open non-existing with O_CREAT
184 	TEST("sem_open(O_CREAT) non-existing");
185 	sem_t* sem = sem_open(kSemName1, O_CREAT, S_IRUSR | S_IWUSR, 1);
186 	assert_posix_bool_success(sem != SEM_FAILED);
187 
188 	TEST("close_sem() forked");
189 	pid_t child = fork();
190 	assert_posix_bool_success(child >= 0);
191 
192 	if (child == 0) {
193 		// child
194 		assert_posix_success(sem_close(sem));
195 		exit(0);
196 	} else {
197 		// parent
198 		assert_posix_success(sem_close(sem));
199 		wait_for_child(child);
200 	}
201 
202 	TEST("sem_open() existing forked");
203 	child = fork();
204 	assert_posix_bool_success(child >= 0);
205 
206 	if (child == 0) {
207 		// child
208 		sem = sem_open(kSemName1, O_CREAT);
209 		assert_posix_bool_success(sem != SEM_FAILED);
210 		exit(0);
211 	} else {
212 		// parent
213 		sem = sem_open(kSemName1, O_CREAT);
214 		wait_for_child(child);
215 		assert_posix_success(sem_close(sem));
216 	}
217 
218 	TEST("done");
219 }
220 
221 
222 static void
test_init_destroy_fork()223 test_init_destroy_fork()
224 {
225 	TEST_SET("sem_{init,destroy}() with fork()");
226 
227 	const char* currentTest = NULL;
228 
229 	// init
230 	TEST("sem_init()");
231 	sem_t sem;
232 	assert_posix_success(sem_init(&sem, 0, 1));
233 
234 	// destroy
235 	TEST("sem_destroy() forked");
236 	pid_t child = fork();
237 	assert_posix_bool_success(child >= 0);
238 
239 	if (child == 0) {
240 		// child
241 		assert_posix_success(sem_destroy(&sem));
242 		exit(0);
243 	} else {
244 		// parent
245 		assert_posix_success(sem_destroy(&sem));
246 		wait_for_child(child);
247 	}
248 
249 	TEST("done");
250 }
251 
252 
253 static void
test_post_wait_named()254 test_post_wait_named()
255 {
256 	TEST_SET("sem_{post,wait,trywait,timedwait}() named semaphore");
257 
258 	const char* currentTest = NULL;
259 
260 	// make sure the sem doesn't exist yet
261 	sem_unlink(kSemName1);
262 
263 	// open non-existing with O_CREAT
264 	TEST("sem_open(O_CREAT) non-existing");
265 	sem_t* sem = sem_open(kSemName1, O_CREAT, S_IRUSR | S_IWUSR, 1);
266 	assert_posix_bool_success(sem != SEM_FAILED);
267 
268 	TEST("sem_getvalue()");
269 	int value;
270 	assert_posix_success(sem_getvalue(sem, &value));
271 	assert_equals(1, value);
272 
273 	// post
274 	TEST("sem_post() no waiting");
275 	assert_posix_success(sem_post(sem));
276 
277 	TEST("sem_getvalue()");
278 	assert_posix_success(sem_getvalue(sem, &value));
279 	assert_equals(2, value);
280 
281 	// wait
282 	TEST("sem_wait() non-blocking");
283 	assert_posix_success(sem_wait(sem));
284 
285 	TEST("sem_getvalue()");
286 	assert_posix_success(sem_getvalue(sem, &value));
287 	assert_equals(1, value);
288 
289 	// wait
290 	TEST("sem_wait() non-blocking");
291 	assert_posix_success(sem_wait(sem));
292 
293 	TEST("sem_getvalue()");
294 	assert_posix_success(sem_getvalue(sem, &value));
295 	assert_equals(0, value);
296 
297 	// close
298 	TEST("sem_close()");
299 	assert_posix_success(sem_close(sem));
300 
301 	// re-open existing
302 	TEST("sem_open() existing");
303 	sem = sem_open(kSemName1, 0);
304 	assert_posix_bool_success(sem != SEM_FAILED);
305 
306 	TEST("sem_getvalue()");
307 	assert_posix_success(sem_getvalue(sem, &value));
308 	assert_equals(0, value);
309 
310 	// post
311 	TEST("sem_post() no waiting");
312 	assert_posix_success(sem_post(sem));
313 
314 	TEST("sem_getvalue()");
315 	assert_posix_success(sem_getvalue(sem, &value));
316 	assert_equals(1, value);
317 
318 	// post
319 	TEST("sem_post() no waiting");
320 	assert_posix_success(sem_post(sem));
321 
322 	TEST("sem_getvalue()");
323 	assert_posix_success(sem_getvalue(sem, &value));
324 	assert_equals(2, value);
325 
326 	// trywait
327 	TEST("sem_trywait() success");
328 	assert_posix_success(sem_trywait(sem));
329 
330 	TEST("sem_getvalue()");
331 	assert_posix_success(sem_getvalue(sem, &value));
332 	assert_equals(1, value);
333 
334 	// trywait
335 	TEST("sem_trywait() success");
336 	assert_posix_success(sem_trywait(sem));
337 
338 	TEST("sem_getvalue()");
339 	assert_posix_success(sem_getvalue(sem, &value));
340 	assert_equals(0, value);
341 
342 	// trywait failure
343 	TEST("sem_trywait() failure");
344 	assert_posix_error(EAGAIN, sem_trywait(sem));
345 
346 	TEST("sem_getvalue()");
347 	assert_posix_success(sem_getvalue(sem, &value));
348 	assert_equals(0, value);
349 
350 	// post
351 	TEST("sem_post() no waiting");
352 	assert_posix_success(sem_post(sem));
353 
354 	TEST("sem_getvalue()");
355 	assert_posix_success(sem_getvalue(sem, &value));
356 	assert_equals(1, value);
357 
358 	// post
359 	TEST("sem_post() no waiting");
360 	assert_posix_success(sem_post(sem));
361 
362 	TEST("sem_getvalue()");
363 	assert_posix_success(sem_getvalue(sem, &value));
364 	assert_equals(2, value);
365 
366 	// timedwait
367 	TEST("sem_timedwait() success");
368 	timespec timeout;
369 	assert_posix_success(sem_timedwait(sem,
370 		absolute_timeout(timeout, 1000000)));
371 
372 	TEST("sem_getvalue()");
373 	assert_posix_success(sem_getvalue(sem, &value));
374 	assert_equals(1, value);
375 
376 	TEST("sem_timedwait() success");
377 	assert_posix_success(sem_timedwait(sem,
378 		absolute_timeout(timeout, 1000000)));
379 
380 	TEST("sem_getvalue()");
381 	assert_posix_success(sem_getvalue(sem, &value));
382 	assert_equals(0, value);
383 
384 	TEST("sem_timedwait() timeout");
385 	bigtime_t startTime = system_time();
386 	assert_posix_error(ETIMEDOUT, sem_timedwait(sem,
387 		absolute_timeout(timeout, 1000000)));
388 	bigtime_t diffTime = system_time() - startTime;
389 	assert_time_equals(1000000, diffTime);
390 
391 	TEST("sem_getvalue()");
392 	assert_posix_success(sem_getvalue(sem, &value));
393 	assert_equals(0, value);
394 
395 	// close
396 	TEST("sem_close()");
397 	assert_posix_success(sem_close(sem));
398 
399 	TEST("done");
400 }
401 
402 
403 static void
test_post_wait_unnamed()404 test_post_wait_unnamed()
405 {
406 	TEST_SET("sem_{post,wait,trywait,timedwait}() unnamed semaphore");
407 
408 	const char* currentTest = NULL;
409 
410 	// init
411 	TEST("sem_init()");
412 	sem_t _sem;
413 	assert_posix_success(sem_init(&_sem, 0, 1));
414 	sem_t* sem = &_sem;
415 
416 	TEST("sem_getvalue()");
417 	int value;
418 	assert_posix_success(sem_getvalue(sem, &value));
419 	assert_equals(1, value);
420 
421 	// post
422 	TEST("sem_post() no waiting");
423 	assert_posix_success(sem_post(sem));
424 
425 	TEST("sem_getvalue()");
426 	assert_posix_success(sem_getvalue(sem, &value));
427 	assert_equals(2, value);
428 
429 	// wait
430 	TEST("sem_wait() non-blocking");
431 	assert_posix_success(sem_wait(sem));
432 
433 	TEST("sem_getvalue()");
434 	assert_posix_success(sem_getvalue(sem, &value));
435 	assert_equals(1, value);
436 
437 	// wait
438 	TEST("sem_wait() non-blocking");
439 	assert_posix_success(sem_wait(sem));
440 
441 	TEST("sem_getvalue()");
442 	assert_posix_success(sem_getvalue(sem, &value));
443 	assert_equals(0, value);
444 
445 	// post
446 	TEST("sem_post() no waiting");
447 	assert_posix_success(sem_post(sem));
448 
449 	TEST("sem_getvalue()");
450 	assert_posix_success(sem_getvalue(sem, &value));
451 	assert_equals(1, value);
452 
453 	// post
454 	TEST("sem_post() no waiting");
455 	assert_posix_success(sem_post(sem));
456 
457 	TEST("sem_getvalue()");
458 	assert_posix_success(sem_getvalue(sem, &value));
459 	assert_equals(2, value);
460 
461 	// trywait
462 	TEST("sem_trywait() success");
463 	assert_posix_success(sem_trywait(sem));
464 
465 	TEST("sem_getvalue()");
466 	assert_posix_success(sem_getvalue(sem, &value));
467 	assert_equals(1, value);
468 
469 	// trywait
470 	TEST("sem_trywait() success");
471 	assert_posix_success(sem_trywait(sem));
472 
473 	TEST("sem_getvalue()");
474 	assert_posix_success(sem_getvalue(sem, &value));
475 	assert_equals(0, value);
476 
477 	// trywait failure
478 	TEST("sem_trywait() failure");
479 	assert_posix_error(EAGAIN, sem_trywait(sem));
480 
481 	TEST("sem_getvalue()");
482 	assert_posix_success(sem_getvalue(sem, &value));
483 	assert_equals(0, value);
484 
485 	// post
486 	TEST("sem_post() no waiting");
487 	assert_posix_success(sem_post(sem));
488 
489 	TEST("sem_getvalue()");
490 	assert_posix_success(sem_getvalue(sem, &value));
491 	assert_equals(1, value);
492 
493 	// post
494 	TEST("sem_post() no waiting");
495 	assert_posix_success(sem_post(sem));
496 
497 	TEST("sem_getvalue()");
498 	assert_posix_success(sem_getvalue(sem, &value));
499 	assert_equals(2, value);
500 
501 	// timedwait
502 	TEST("sem_timedwait() success");
503 	timespec timeout;
504 	assert_posix_success(sem_timedwait(sem,
505 		absolute_timeout(timeout, 1000000)));
506 
507 	TEST("sem_getvalue()");
508 	assert_posix_success(sem_getvalue(sem, &value));
509 	assert_equals(1, value);
510 
511 	TEST("sem_timedwait() success");
512 	assert_posix_success(sem_timedwait(sem,
513 		absolute_timeout(timeout, 1000000)));
514 
515 	TEST("sem_getvalue()");
516 	assert_posix_success(sem_getvalue(sem, &value));
517 	assert_equals(0, value);
518 
519 	TEST("sem_timedwait() timeout");
520 	bigtime_t startTime = system_time();
521 	assert_posix_error(ETIMEDOUT, sem_timedwait(sem,
522 		absolute_timeout(timeout, 1000000)));
523 	bigtime_t diffTime = system_time() - startTime;
524 	assert_time_equals(1000000, diffTime);
525 
526 	TEST("sem_getvalue()");
527 	assert_posix_success(sem_getvalue(sem, &value));
528 	assert_equals(0, value);
529 
530 	// destroy
531 	TEST("sem_destroy()");
532 	assert_posix_success(sem_destroy(sem));
533 
534 	TEST("done");
535 }
536 
537 
538 static void
test_post_wait_named_fork()539 test_post_wait_named_fork()
540 {
541 	TEST_SET("sem_{post,wait,trywait,timedwait}() named semaphore with fork()");
542 
543 	const char* currentTest = NULL;
544 
545 	// make sure the sem doesn't exist yet
546 	sem_unlink(kSemName1);
547 
548 	// open non-existing with O_CREAT
549 	TEST("sem_open(O_CREAT) non-existing");
550 	sem_t* sem = sem_open(kSemName1, O_CREAT, S_IRUSR | S_IWUSR, 0);
551 	assert_posix_bool_success(sem != SEM_FAILED);
552 
553 	TEST("sem_getvalue()");
554 	int value;
555 	assert_posix_success(sem_getvalue(sem, &value));
556 	assert_equals(0, value);
557 
558 	TEST("unblock child after wait");
559 	pid_t child = fork();
560 	assert_posix_bool_success(child >= 0);
561 
562 	if (child == 0) {
563 		// child
564 		bigtime_t startTime = system_time();
565 		assert_posix_success(sem_wait(sem));
566 		bigtime_t diffTime = system_time() - startTime;
567 		assert_time_equals(1000000, diffTime);
568 
569 		exit(0);
570 	} else {
571 		// parent
572 		sleep(1);
573 		assert_posix_success(sem_post(sem));
574 		wait_for_child(child);
575 	}
576 
577 	TEST("sem_getvalue()");
578 	assert_posix_success(sem_getvalue(sem, &value));
579 	assert_equals(0, value);
580 
581 	TEST("unblock parent after wait");
582 	child = fork();
583 	assert_posix_bool_success(child >= 0);
584 
585 	if (child == 0) {
586 		// child
587 		sleep(1);
588 		assert_posix_success(sem_post(sem));
589 
590 		exit(0);
591 	} else {
592 		// parent
593 		bigtime_t startTime = system_time();
594 		assert_posix_success(sem_wait(sem));
595 		bigtime_t diffTime = system_time() - startTime;
596 		assert_time_equals(1000000, diffTime);
597 
598 		wait_for_child(child);
599 	}
600 
601 	TEST("sem_getvalue()");
602 	assert_posix_success(sem_getvalue(sem, &value));
603 	assert_equals(0, value);
604 
605 	TEST("unblock child after wait before timeout");
606 	child = fork();
607 	assert_posix_bool_success(child >= 0);
608 
609 	if (child == 0) {
610 		// child
611 		timespec timeout;
612 		bigtime_t startTime = system_time();
613 		assert_posix_success(sem_timedwait(sem,
614 			absolute_timeout(timeout, 2000000)));
615 		bigtime_t diffTime = system_time() - startTime;
616 		assert_time_equals(1000000, diffTime);
617 
618 		exit(0);
619 	} else {
620 		// parent
621 		sleep(1);
622 		assert_posix_success(sem_post(sem));
623 		wait_for_child(child);
624 	}
625 
626 	TEST("sem_getvalue()");
627 	assert_posix_success(sem_getvalue(sem, &value));
628 	assert_equals(0, value);
629 
630 	TEST("unblock child after wait after timeout");
631 	child = fork();
632 	assert_posix_bool_success(child >= 0);
633 
634 	if (child == 0) {
635 		// child
636 		timespec timeout;
637 		bigtime_t startTime = system_time();
638 		assert_posix_error(ETIMEDOUT, sem_timedwait(sem,
639 			absolute_timeout(timeout, 1000000)));
640 		bigtime_t diffTime = system_time() - startTime;
641 		assert_time_equals(1000000, diffTime);
642 
643 		exit(0);
644 	} else {
645 		// parent
646 		sleep(2);
647 		assert_posix_success(sem_post(sem));
648 		wait_for_child(child);
649 	}
650 
651 	TEST("sem_getvalue()");
652 	assert_posix_success(sem_getvalue(sem, &value));
653 	assert_equals(1, value);
654 
655 	// close
656 	TEST("sem_close()");
657 	assert_posix_success(sem_close(sem));
658 
659 	TEST("done");
660 }
661 
662 
663 static void
test_post_wait_named_fork2()664 test_post_wait_named_fork2()
665 {
666 	TEST_SET("sem_{post,wait,trywait,timedwait}() named semaphore open after "
667 		"fork");
668 
669 	const char* currentTest = NULL;
670 
671 	// make sure the sem doesn't exist yet
672 	sem_unlink(kSemName1);
673 
674 	// open non-existing with O_CREAT
675 	TEST("sem_open(O_CREAT) non-existing");
676 	sem_t* sem = sem_open(kSemName1, O_CREAT, S_IRUSR | S_IWUSR, 0);
677 	assert_posix_bool_success(sem != SEM_FAILED);
678 
679 	TEST("sem_getvalue()");
680 	int value;
681 	assert_posix_success(sem_getvalue(sem, &value));
682 	assert_equals(0, value);
683 
684 	// close
685 	TEST("sem_close()");
686 	assert_posix_success(sem_close(sem));
687 	sem = NULL;
688 
689 	TEST("unblock child after wait");
690 	pid_t child = fork();
691 	assert_posix_bool_success(child >= 0);
692 
693 	if (child == 0) {
694 		// child
695 		sem = sem_open(kSemName1, 0);
696 		assert_posix_bool_success(sem != SEM_FAILED);
697 
698 		bigtime_t startTime = system_time();
699 		assert_posix_success(sem_wait(sem));
700 		bigtime_t diffTime = system_time() - startTime;
701 		assert_time_equals(1000000, diffTime);
702 
703 		exit(0);
704 	} else {
705 		// parent
706 		sem = sem_open(kSemName1, 0);
707 		assert_posix_bool_success(sem != SEM_FAILED);
708 
709 		sleep(1);
710 		assert_posix_success(sem_post(sem));
711 		wait_for_child(child);
712 	}
713 
714 	TEST("sem_getvalue()");
715 	assert_posix_success(sem_getvalue(sem, &value));
716 	assert_equals(0, value);
717 
718 	// close
719 	TEST("sem_close()");
720 	assert_posix_success(sem_close(sem));
721 	sem = NULL;
722 
723 	TEST("unblock child after wait before timeout");
724 	child = fork();
725 	assert_posix_bool_success(child >= 0);
726 
727 	if (child == 0) {
728 		// child
729 		sem = sem_open(kSemName1, 0);
730 		assert_posix_bool_success(sem != SEM_FAILED);
731 
732 		timespec timeout;
733 		bigtime_t startTime = system_time();
734 		assert_posix_success(sem_timedwait(sem,
735 			absolute_timeout(timeout, 2000000)));
736 		bigtime_t diffTime = system_time() - startTime;
737 		assert_time_equals(1000000, diffTime);
738 
739 		exit(0);
740 	} else {
741 		// parent
742 		sem = sem_open(kSemName1, 0);
743 		assert_posix_bool_success(sem != SEM_FAILED);
744 
745 		sleep(1);
746 		assert_posix_success(sem_post(sem));
747 		wait_for_child(child);
748 	}
749 
750 	TEST("sem_getvalue()");
751 	assert_posix_success(sem_getvalue(sem, &value));
752 	assert_equals(0, value);
753 
754 	// close
755 	TEST("sem_close()");
756 	assert_posix_success(sem_close(sem));
757 	sem = NULL;
758 
759 	TEST("unblock child after wait after timeout");
760 	child = fork();
761 	assert_posix_bool_success(child >= 0);
762 
763 	if (child == 0) {
764 		// child
765 		sem = sem_open(kSemName1, 0);
766 		assert_posix_bool_success(sem != SEM_FAILED);
767 
768 		timespec timeout;
769 		bigtime_t startTime = system_time();
770 		assert_posix_error(ETIMEDOUT, sem_timedwait(sem,
771 			absolute_timeout(timeout, 1000000)));
772 		bigtime_t diffTime = system_time() - startTime;
773 		assert_time_equals(1000000, diffTime);
774 
775 		exit(0);
776 	} else {
777 		// parent
778 		sem = sem_open(kSemName1, 0);
779 		assert_posix_bool_success(sem != SEM_FAILED);
780 
781 		sleep(2);
782 		assert_posix_success(sem_post(sem));
783 		wait_for_child(child);
784 	}
785 
786 	TEST("sem_getvalue()");
787 	assert_posix_success(sem_getvalue(sem, &value));
788 	assert_equals(1, value);
789 
790 	// close
791 	TEST("sem_close()");
792 	assert_posix_success(sem_close(sem));
793 
794 	TEST("done");
795 }
796 
797 
798 static void
test_post_wait_unnamed_fork()799 test_post_wait_unnamed_fork()
800 {
801 	TEST_SET("sem_{post,wait,trywait,timedwait}() unnamed semaphore with "
802 		"fork()");
803 
804 	const char* currentTest = NULL;
805 
806 	// init
807 	TEST("sem_init()");
808 	sem_t _sem;
809 	assert_posix_success(sem_init(&_sem, 0, 1));
810 	sem_t* sem = &_sem;
811 
812 	TEST("sem_getvalue()");
813 	int value;
814 	assert_posix_success(sem_getvalue(sem, &value));
815 	assert_equals(1, value);
816 
817 	TEST("sem_wait() on fork()ed unnamed sem in parent and child");
818 	pid_t child = fork();
819 	assert_posix_bool_success(child >= 0);
820 
821 	if (child == 0) {
822 		// child
823 		sleep(1);
824 		assert_posix_success(sem_wait(sem));
825 
826 		assert_posix_success(sem_getvalue(sem, &value));
827 		assert_equals(0, value);
828 
829 		exit(0);
830 	} else {
831 		// parent
832 		assert_posix_success(sem_wait(sem));
833 		assert_posix_success(sem_getvalue(sem, &value));
834 		assert_equals(0, value);
835 
836 		wait_for_child(child);
837 	}
838 
839 	TEST("sem_getvalue()");
840 	assert_posix_success(sem_getvalue(sem, &value));
841 	assert_equals(0, value);
842 
843 	TEST("sem_post() on fork()ed unnamed sem in parent and child");
844 	child = fork();
845 	assert_posix_bool_success(child >= 0);
846 
847 	if (child == 0) {
848 		// child
849 		assert_posix_success(sem_post(sem));
850 
851 		assert_posix_success(sem_getvalue(sem, &value));
852 		assert_equals(1, value);
853 
854 		exit(0);
855 	} else {
856 		// parent
857 		assert_posix_success(sem_post(sem));
858 		assert_posix_success(sem_getvalue(sem, &value));
859 		assert_equals(1, value);
860 
861 		wait_for_child(child);
862 	}
863 
864 	TEST("sem_getvalue()");
865 	assert_posix_success(sem_getvalue(sem, &value));
866 	assert_equals(1, value);
867 
868 	// destroy
869 	TEST("sem_destroy()");
870 	assert_posix_success(sem_destroy(sem));
871 
872 	TEST("done");
873 }
874 
875 
876 static void
test_post_wait_unnamed_fork_shared()877 test_post_wait_unnamed_fork_shared()
878 {
879 	TEST_SET("sem_{post,wait,trywait,timedwait}() unnamed semaphore with "
880 		"fork() in shared memory");
881 
882 	const char* currentTest = NULL;
883 
884 	// create shared memory area
885 	void* address = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
886 		MAP_SHARED | MAP_ANON, -1, 0);
887 	assert_posix_bool_success(address != MAP_FAILED);
888 
889 	// init
890 	TEST("sem_init()");
891 	sem_t* sem = (sem_t*)address;
892 	assert_posix_success(sem_init(sem, 1, 0));
893 
894 	TEST("sem_getvalue()");
895 	int value;
896 	assert_posix_success(sem_getvalue(sem, &value));
897 	assert_equals(0, value);
898 
899 	TEST("unblock child after wait");
900 	pid_t child = fork();
901 	assert_posix_bool_success(child >= 0);
902 
903 	if (child == 0) {
904 		// child
905 		bigtime_t startTime = system_time();
906 		assert_posix_success(sem_wait(sem));
907 		bigtime_t diffTime = system_time() - startTime;
908 		assert_time_equals(1000000, diffTime);
909 
910 		exit(0);
911 	} else {
912 		// parent
913 		sleep(1);
914 		assert_posix_success(sem_post(sem));
915 		wait_for_child(child);
916 	}
917 
918 	TEST("sem_getvalue()");
919 	assert_posix_success(sem_getvalue(sem, &value));
920 	assert_equals(0, value);
921 
922 	TEST("unblock parent after wait");
923 	child = fork();
924 	assert_posix_bool_success(child >= 0);
925 
926 	if (child == 0) {
927 		// child
928 		sleep(1);
929 		assert_posix_success(sem_post(sem));
930 
931 		exit(0);
932 	} else {
933 		// parent
934 		bigtime_t startTime = system_time();
935 		assert_posix_success(sem_wait(sem));
936 		bigtime_t diffTime = system_time() - startTime;
937 		assert_time_equals(1000000, diffTime);
938 
939 		wait_for_child(child);
940 	}
941 
942 	TEST("sem_getvalue()");
943 	assert_posix_success(sem_getvalue(sem, &value));
944 	assert_equals(0, value);
945 
946 	TEST("unblock child after wait before timeout");
947 	child = fork();
948 	assert_posix_bool_success(child >= 0);
949 
950 	if (child == 0) {
951 		// child
952 		timespec timeout;
953 		bigtime_t startTime = system_time();
954 		assert_posix_success(sem_timedwait(sem,
955 			absolute_timeout(timeout, 2000000)));
956 		bigtime_t diffTime = system_time() - startTime;
957 		assert_time_equals(1000000, diffTime);
958 
959 		exit(0);
960 	} else {
961 		// parent
962 		sleep(1);
963 		assert_posix_success(sem_post(sem));
964 		wait_for_child(child);
965 	}
966 
967 	TEST("sem_getvalue()");
968 	assert_posix_success(sem_getvalue(sem, &value));
969 	assert_equals(0, value);
970 
971 	TEST("unblock child after wait after timeout");
972 	child = fork();
973 	assert_posix_bool_success(child >= 0);
974 
975 	if (child == 0) {
976 		// child
977 		timespec timeout;
978 		bigtime_t startTime = system_time();
979 		assert_posix_error(ETIMEDOUT, sem_timedwait(sem,
980 			absolute_timeout(timeout, 1000000)));
981 		bigtime_t diffTime = system_time() - startTime;
982 		assert_time_equals(1000000, diffTime);
983 
984 		exit(0);
985 	} else {
986 		// parent
987 		sleep(2);
988 		assert_posix_success(sem_post(sem));
989 		wait_for_child(child);
990 	}
991 
992 	TEST("sem_getvalue()");
993 	assert_posix_success(sem_getvalue(sem, &value));
994 	assert_equals(1, value);
995 
996 	// destroy
997 	TEST("sem_destroy()");
998 	assert_posix_success(sem_destroy(sem));
999 
1000 	// unmap memory
1001 	assert_posix_success(munmap(address, 4096));
1002 
1003 	TEST("done");
1004 }
1005 
1006 
1007 int
main()1008 main()
1009 {
1010 	test_open_close_unlink();
1011 	test_init_destroy();
1012 	test_open_close_fork();
1013 	test_init_destroy_fork();
1014 	test_post_wait_named();
1015 	test_post_wait_unnamed();
1016 	test_post_wait_named_fork();
1017 	test_post_wait_named_fork2();
1018 	test_post_wait_unnamed_fork();
1019 	test_post_wait_unnamed_fork_shared();
1020 
1021 	printf("\nall tests OK\n");
1022 }
1023