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