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