1*52dd0f17Sfgsch /* $OpenBSD: pthread_atfork.c,v 1.3 2005/11/05 04:28:46 fgsch Exp $ */
2c8063e44Sfgsch
3c8063e44Sfgsch /*
4c8063e44Sfgsch * Federico Schwindt <fgsch@openbsd.org>, 2005. Public Domain.
5c8063e44Sfgsch */
6c8063e44Sfgsch
7c8063e44Sfgsch #include <sys/types.h>
8c8063e44Sfgsch #include <pthread.h>
9c8063e44Sfgsch #include <unistd.h>
10c8063e44Sfgsch
11c8063e44Sfgsch #include "test.h"
12c8063e44Sfgsch
13c8063e44Sfgsch int cnt;
14c8063e44Sfgsch
15c8063e44Sfgsch void
prepare1(void)16c8063e44Sfgsch prepare1(void)
17c8063e44Sfgsch {
18c8063e44Sfgsch ASSERT(cnt == 1);
19c8063e44Sfgsch cnt--;
20c8063e44Sfgsch }
21c8063e44Sfgsch
22c8063e44Sfgsch void
prepare2(void)23c8063e44Sfgsch prepare2(void)
24c8063e44Sfgsch {
25c8063e44Sfgsch ASSERT(cnt == 2);
26c8063e44Sfgsch cnt--;
27c8063e44Sfgsch }
28c8063e44Sfgsch
29c8063e44Sfgsch void
parent1(void)30c8063e44Sfgsch parent1(void)
31c8063e44Sfgsch {
32c8063e44Sfgsch ASSERT(cnt == 0);
33c8063e44Sfgsch cnt += 2;
34c8063e44Sfgsch }
35c8063e44Sfgsch
36c8063e44Sfgsch void
parent2(void)37c8063e44Sfgsch parent2(void)
38c8063e44Sfgsch {
39c8063e44Sfgsch ASSERT(cnt == 2);
40c8063e44Sfgsch cnt -= 2;
41c8063e44Sfgsch }
42c8063e44Sfgsch
43c8063e44Sfgsch void
child1(void)44c8063e44Sfgsch child1(void)
45c8063e44Sfgsch {
46c8063e44Sfgsch ASSERT(cnt == 0);
47c8063e44Sfgsch cnt += 3;
48c8063e44Sfgsch }
49c8063e44Sfgsch
50c8063e44Sfgsch void
child2(void)51c8063e44Sfgsch child2(void)
52c8063e44Sfgsch {
53c8063e44Sfgsch ASSERT(cnt == 3);
54c8063e44Sfgsch cnt++;
55c8063e44Sfgsch }
56c8063e44Sfgsch
57c8063e44Sfgsch void *
forker1(void * arg)58c8063e44Sfgsch forker1(void *arg)
59c8063e44Sfgsch {
60c8063e44Sfgsch CHECKr(pthread_atfork(prepare1, parent1, child1));
61c8063e44Sfgsch
62c8063e44Sfgsch cnt = 1;
63c8063e44Sfgsch switch (fork()) {
64c8063e44Sfgsch case -1:
652c790616Sfgsch PANIC("fork");
66c8063e44Sfgsch break;
67c8063e44Sfgsch
68c8063e44Sfgsch case 0:
69c8063e44Sfgsch ASSERT(cnt == 3);
70c8063e44Sfgsch _exit(0);
71c8063e44Sfgsch
72c8063e44Sfgsch default:
73c8063e44Sfgsch ASSERT(cnt == 2);
74c8063e44Sfgsch break;
75c8063e44Sfgsch }
76c8063e44Sfgsch
77c8063e44Sfgsch cnt = 1;
78c8063e44Sfgsch
79c8063e44Sfgsch return (NULL);
80c8063e44Sfgsch }
81c8063e44Sfgsch
82c8063e44Sfgsch void *
forker2(void * arg)83c8063e44Sfgsch forker2(void *arg)
84c8063e44Sfgsch {
85c8063e44Sfgsch CHECKr(pthread_atfork(prepare2, parent2, child2));
86c8063e44Sfgsch
87c8063e44Sfgsch cnt = 2;
88c8063e44Sfgsch switch (fork()) {
89c8063e44Sfgsch case -1:
902c790616Sfgsch PANIC("fork");
91c8063e44Sfgsch break;
92c8063e44Sfgsch
93c8063e44Sfgsch case 0:
94c8063e44Sfgsch ASSERT(cnt == 4);
95c8063e44Sfgsch _exit(0);
96c8063e44Sfgsch
97c8063e44Sfgsch default:
98c8063e44Sfgsch ASSERT(cnt == 0);
99c8063e44Sfgsch break;
100c8063e44Sfgsch }
101c8063e44Sfgsch
102c8063e44Sfgsch cnt = 0;
103c8063e44Sfgsch
104c8063e44Sfgsch return (NULL);
105c8063e44Sfgsch }
106c8063e44Sfgsch
107c8063e44Sfgsch int
main(int argc,char ** argv)108c8063e44Sfgsch main(int argc, char **argv)
109c8063e44Sfgsch {
110c8063e44Sfgsch pthread_t tid;
111c8063e44Sfgsch
112c8063e44Sfgsch CHECKr(pthread_create(&tid, NULL, forker1, NULL));
113c8063e44Sfgsch CHECKr(pthread_join(tid, NULL));
114c8063e44Sfgsch ASSERT(cnt == 1);
115c8063e44Sfgsch CHECKr(pthread_create(&tid, NULL, forker2, NULL));
116c8063e44Sfgsch CHECKr(pthread_join(tid, NULL));
117c8063e44Sfgsch ASSERT(cnt == 0);
118c8063e44Sfgsch SUCCEED;
119c8063e44Sfgsch }
120