Warning: That file was not part of the compilation database. It may have many parsing errors.

1#include <pthread.h>
2#include <signal.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <unistd.h>
8#include <sys/mman.h>
9#include <sys/wait.h>
10
11
12
13
14static void prepare (void);
15#define PREPARE(argc, argv) prepare ()
16static int do_test (void);
17#define TEST_FUNCTION do_test ()
18#include "../test-skeleton.c"
19
20
21static int fd;
22#define N 100
23
24static void
25prepare (void)
26{
27 fd = create_temp_file ("tst-robust8", NULL);
28 if (fd == -1)
29 exit (1);
30}
31
32
33#define THESIGNAL SIGKILL
34#define ROUNDS 5
35#define THREADS 9
36
37
38static const struct timespec before = { 0, 0 };
39
40
41static pthread_mutex_t *map;
42
43
44static void *
45tf (void *arg)
46{
47 long int nr = (long int) arg;
48 int fct = nr % 3;
49
50 uint8_t state[N];
51 memset (state, '\0', sizeof (state));
52
53 while (1)
54 {
55 int r = random () % N;
56 if (state[r] == 0)
57 {
58 int e;
59
60 switch (fct)
61 {
62 case 0:
63 e = pthread_mutex_lock (&map[r]);
64 if (e != 0)
65 {
66 printf ("mutex_lock of %d in thread %ld failed with %d\n",
67 r, nr, e);
68 exit (1);
69 }
70 state[r] = 1;
71 break;
72 case 1:
73 e = pthread_mutex_timedlock (&map[r], &before);
74 if (e != 0 && e != ETIMEDOUT)
75 {
76 printf ("\
77mutex_timedlock of %d in thread %ld failed with %d\n",
78 r, nr, e);
79 exit (1);
80 }
81 break;
82 default:
83 e = pthread_mutex_trylock (&map[r]);
84 if (e != 0 && e != EBUSY)
85 {
86 printf ("mutex_trylock of %d in thread %ld failed with %d\n",
87 r, nr, e);
88 exit (1);
89 }
90 break;
91 }
92
93 if (e == EOWNERDEAD)
94 pthread_mutex_consistent_np (&map[r]);
95
96 if (e == 0 || e == EOWNERDEAD)
97 state[r] = 1;
98 }
99 else
100 {
101 int e = pthread_mutex_unlock (&map[r]);
102 if (e != 0)
103 {
104 printf ("mutex_unlock of %d in thread %ld failed with %d\n",
105 r, nr, e);
106 exit (1);
107 }
108
109 state[r] = 0;
110 }
111 }
112}
113
114
115static void
116child (int round)
117{
118 for (int thread = 1; thread <= THREADS; ++thread)
119 {
120 pthread_t th;
121 if (pthread_create (&th, NULL, tf, (void *) (long int) thread) != 0)
122 {
123 printf ("cannot create thread %d in round %d\n", thread, round);
124 exit (1);
125 }
126 }
127
128 struct timespec ts;
129 ts.tv_sec = 0;
130 ts.tv_nsec = 1000000000 / ROUNDS;
131 while (nanosleep (&ts, &ts) != 0)
132 /* nothing */;
133
134 /* Time to die. */
135 kill (getpid (), THESIGNAL);
136
137 /* We better never get here. */
138 abort ();
139}
140
141
142static int
143do_test (void)
144{
145 if (ftruncate (fd, N * sizeof (pthread_mutex_t)) != 0)
146 {
147 puts ("cannot size new file");
148 return 1;
149 }
150
151 map = mmap (NULL, N * sizeof (pthread_mutex_t), PROT_READ | PROT_WRITE,
152 MAP_SHARED, fd, 0);
153 if (map == MAP_FAILED)
154 {
155 puts ("mapping failed");
156 return 1;
157 }
158
159 pthread_mutexattr_t ma;
160 if (pthread_mutexattr_init (&ma) != 0)
161 {
162 puts ("mutexattr_init failed");
163 return 0;
164 }
165 if (pthread_mutexattr_setrobust_np (&ma, PTHREAD_MUTEX_ROBUST_NP) != 0)
166 {
167 puts ("mutexattr_setrobust failed");
168 return 1;
169 }
170 if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
171 {
172 puts ("mutexattr_setpshared failed");
173 return 1;
174 }
175#ifdef ENABLE_PI
176 if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0)
177 {
178 puts ("pthread_mutexattr_setprotocol failed");
179 return 1;
180 }
181#endif
182
183 for (int round = 1; round <= ROUNDS; ++round)
184 {
185 for (int n = 0; n < N; ++n)
186 {
187 int e = pthread_mutex_init (&map[n], &ma);
188 if (e == ENOTSUP)
189 {
190#ifdef ENABLE_PI
191 puts ("cannot support pshared robust PI mutexes");
192#else
193 puts ("cannot support pshared robust mutexes");
194#endif
195 return 0;
196 }
197 if (e != 0)
198 {
199 printf ("mutex_init %d in round %d failed\n", n + 1, round);
200 return 1;
201 }
202 }
203
204 pid_t p = fork ();
205 if (p == -1)
206 {
207 printf ("fork in round %d failed\n", round);
208 return 1;
209 }
210 if (p == 0)
211 child (round);
212
213 int status;
214 if (TEMP_FAILURE_RETRY (waitpid (p, &status, 0)) != p)
215 {
216 printf ("waitpid in round %d failed\n", round);
217 return 1;
218 }
219 if (!WIFSIGNALED (status))
220 {
221 printf ("child did not die of a signal in round %d\n", round);
222 return 1;
223 }
224 if (WTERMSIG (status) != THESIGNAL)
225 {
226 printf ("child did not die of signal %d in round %d\n",
227 THESIGNAL, round);
228 return 1;
229 }
230
231 for (int n = 0; n < N; ++n)
232 {
233 int e = pthread_mutex_lock (&map[n]);
234 if (e != 0 && e != EOWNERDEAD)
235 {
236 printf ("mutex_lock %d failed in round %d\n", n + 1, round);
237 return 1;
238 }
239 }
240
241 for (int n = 0; n < N; ++n)
242 if (pthread_mutex_unlock (&map[n]) != 0)
243 {
244 printf ("mutex_unlock %d failed in round %d\n", n + 1, round);
245 return 1;
246 }
247
248 for (int n = 0; n < N; ++n)
249 {
250 int e = pthread_mutex_destroy (&map[n]);
251 if (e != 0)
252 {
253 printf ("mutex_destroy %d in round %d failed with %d\n",
254 n + 1, round, e);
255 printf("nusers = %d\n", (int) map[n].__data.__nusers);
256 return 1;
257 }
258 }
259 }
260
261 if (pthread_mutexattr_destroy (&ma) != 0)
262 {
263 puts ("mutexattr_destroy failed");
264 return 1;
265 }
266
267 if (munmap (map, N * sizeof (pthread_mutex_t)) != 0)
268 {
269 puts ("munmap failed");
270 return 1;
271 }
272
273 return 0;
274}
275

Warning: That file was not part of the compilation database. It may have many parsing errors.