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
25typedef int64_t bigtime_t;
26
27static bigtime_t
28system_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
41static void
42dump_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
52static const char* const kSemName1 = "/test_sem1";
53
54
55static void
56test_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
139static void
140test_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
176static void
177test_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
222static void
223test_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
253static void
254test_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
403static void
404test_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
538static void
539test_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
663static void
664test_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
798static void
799test_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
876static void
877test_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
1007int
1008main()
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