1 | #include <errno.h> |
2 | #include <pthread.h> |
3 | #include <stdio.h> |
4 | #include <stdlib.h> |
5 | #include <unistd.h> |
6 | #include <sys/wait.h> |
7 | |
8 | #define NKEYS 100 |
9 | static pthread_key_t keys[NKEYS]; |
10 | static pthread_barrier_t b; |
11 | |
12 | |
13 | static void * |
14 | tf (void *arg) |
15 | { |
16 | void *res = NULL; |
17 | for (int i = 0; i < NKEYS; ++i) |
18 | { |
19 | void *p = pthread_getspecific (key: keys[i]); |
20 | /* Use an arbitrary but valid pointer as the value. */ |
21 | pthread_setspecific (key: keys[i], pointer: (void *) keys); |
22 | if (p != NULL) |
23 | res = p; |
24 | } |
25 | if (arg != NULL) |
26 | { |
27 | pthread_barrier_wait (barrier: arg); |
28 | pthread_barrier_wait (barrier: arg); |
29 | } |
30 | return res; |
31 | } |
32 | |
33 | |
34 | static int |
35 | do_test (void) |
36 | { |
37 | pthread_barrier_init (barrier: &b, NULL, count: 2); |
38 | |
39 | for (int i = 0; i < NKEYS; ++i) |
40 | if (pthread_key_create (key: &keys[i], NULL) != 0) |
41 | { |
42 | puts (s: "cannot create keys" ); |
43 | return 1; |
44 | } |
45 | |
46 | pthread_t th; |
47 | if (pthread_create (newthread: &th, NULL, start_routine: tf, arg: &b) != 0) |
48 | { |
49 | puts (s: "cannot create thread in parent" ); |
50 | return 1; |
51 | } |
52 | |
53 | pthread_barrier_wait (barrier: &b); |
54 | |
55 | pid_t pid = fork (); |
56 | if (pid == 0) |
57 | { |
58 | if (pthread_create (newthread: &th, NULL, start_routine: tf, NULL) != 0) |
59 | { |
60 | puts (s: "cannot create thread in child" ); |
61 | exit (1); |
62 | } |
63 | |
64 | void *res; |
65 | pthread_join (th: th, thread_return: &res); |
66 | |
67 | exit (res != NULL); |
68 | } |
69 | else if (pid == -1) |
70 | { |
71 | puts (s: "cannot create child process" ); |
72 | return 1; |
73 | } |
74 | |
75 | int s; |
76 | if (TEMP_FAILURE_RETRY (waitpid (pid, &s, 0)) != pid) |
77 | { |
78 | puts (s: "failing to wait for child process" ); |
79 | return 1; |
80 | } |
81 | |
82 | pthread_barrier_wait (barrier: &b); |
83 | pthread_join (th: th, NULL); |
84 | |
85 | return !WIFEXITED (s) ? 2 : WEXITSTATUS (s); |
86 | } |
87 | |
88 | |
89 | #define TEST_FUNCTION do_test () |
90 | #include "../test-skeleton.c" |
91 | |