Print this page
10703 smatch unreachable code checking needs reworking
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/test/libc-tests/tests/c11_threads.c
+++ new/usr/src/test/libc-tests/tests/c11_threads.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 - * Copyright 2017 Joyent, Inc.
13 + * Copyright 2019 Joyent, Inc.
14 14 */
15 15
16 16 /*
17 17 * Validate various C11 threads routines. Specifically we want to cover:
18 18 *
19 19 * o threads
20 20 * o mutexes
21 21 * o condition variables
22 22 */
23 23
24 24 #include <threads.h>
25 25 #include <sys/debug.h>
26 26 #include <stdlib.h>
27 27 #include <unistd.h>
28 28
29 29 #define STRESS_NTHREADS 128
30 30 #define STRESS_COUNT 1000
31 31
32 32 static mtx_t stress_mtx;
33 33 static int stress_count;
34 34
35 35 #define BROADCAST_NTHREADS 128
36 36
37 37 static mtx_t broadcast_mtx;
38 38 static cnd_t broadcast_cnd;
39 39 static boolean_t broadcast_done;
40 40
41 41 #define SIGNAL_NTHREADS 128
42 42
43 43 static mtx_t signal_mtx;
44 44 static cnd_t signal_cnd;
45 45 static boolean_t signal_done;
46 46
47 47 /*
48 48 * This thread should only ever be used for detach.
49 49 */
50 50 static int
51 51 cthr_test_sleep_thr(void *arg)
52 52 {
53 53 for (;;) {
54 54 sleep(1000);
55 55 }
56 56
57 57 abort();
58 58 }
59 59
60 60 static void
61 61 cthr_test_mtx_init(void)
62 62 {
63 63 mtx_t mtx;
64 64
65 65 VERIFY3S(mtx_init(&mtx, mtx_plain), ==, thrd_success);
66 66 mtx_destroy(&mtx);
67 67 VERIFY3S(mtx_init(&mtx, mtx_timed), ==, thrd_success);
68 68 mtx_destroy(&mtx);
69 69 VERIFY3S(mtx_init(&mtx, mtx_plain | mtx_recursive), ==, thrd_success);
70 70 mtx_destroy(&mtx);
71 71 VERIFY3S(mtx_init(&mtx, mtx_timed | mtx_recursive), ==, thrd_success);
72 72 mtx_destroy(&mtx);
73 73
74 74 VERIFY3S(mtx_init(&mtx, UINT32_MAX), ==, thrd_error);
75 75 VERIFY3S(mtx_init(&mtx, 42), ==, thrd_error);
76 76 }
77 77
78 78 static void
79 79 cthr_test_mtx_lockrec(void)
80 80 {
81 81 mtx_t mtx;
82 82
83 83 VERIFY3S(mtx_init(&mtx, mtx_plain | mtx_recursive), ==, thrd_success);
84 84 VERIFY3S(mtx_lock(&mtx), ==, thrd_success);
85 85 VERIFY3S(mtx_lock(&mtx), ==, thrd_success);
86 86 VERIFY3S(mtx_trylock(&mtx), ==, thrd_success);
87 87 VERIFY3S(mtx_unlock(&mtx), ==, thrd_success);
88 88 VERIFY3S(mtx_unlock(&mtx), ==, thrd_success);
89 89 VERIFY3S(mtx_unlock(&mtx), ==, thrd_success);
90 90 mtx_destroy(&mtx);
91 91 }
92 92
93 93 static void
94 94 cthr_test_mtx_trylock(void)
95 95 {
96 96 mtx_t mtx;
97 97
98 98 VERIFY3S(mtx_init(&mtx, mtx_plain), ==, thrd_success);
99 99 VERIFY3S(mtx_trylock(&mtx), ==, thrd_success);
100 100 VERIFY3S(mtx_trylock(&mtx), ==, thrd_busy);
101 101 VERIFY3S(mtx_unlock(&mtx), ==, thrd_success);
102 102 mtx_destroy(&mtx);
103 103 }
104 104
105 105 static int
106 106 cthr_test_stress_thr(void *arg)
107 107 {
108 108 int i;
109 109 int *ip = arg;
110 110
111 111 for (i = 0; i < STRESS_COUNT; i++) {
112 112 VERIFY3S(mtx_lock(&stress_mtx), ==, thrd_success);
113 113 *ip = *ip + 1;
114 114 VERIFY3S(mtx_unlock(&stress_mtx), ==, thrd_success);
115 115 }
116 116
117 117 return (0);
118 118 }
119 119
120 120 static void
121 121 cthr_test_stress(void)
122 122 {
123 123 int i;
124 124 thrd_t threads[STRESS_NTHREADS];
125 125
126 126 VERIFY3S(mtx_init(&stress_mtx, mtx_plain), ==, thrd_success);
127 127 for (i = 0; i < STRESS_NTHREADS; i++) {
128 128 VERIFY3S(thrd_create(&threads[i], cthr_test_stress_thr,
129 129 &stress_count), ==, thrd_success);
130 130 }
131 131
132 132 for (i = 0; i < STRESS_NTHREADS; i++) {
133 133 VERIFY3S(thrd_join(threads[i], NULL), ==, thrd_success);
134 134 }
135 135 mtx_destroy(&stress_mtx);
136 136
137 137 VERIFY3S(stress_count, ==, STRESS_NTHREADS * STRESS_COUNT);
138 138 }
139 139
140 140 static void
141 141 cthr_test_equal(void)
142 142 {
143 143 thrd_t self, other;
144 144
145 145 self = thrd_current();
146 146
147 147 VERIFY3S(thrd_equal(self, self), !=, 0);
148 148 VERIFY3S(thrd_create(&other, cthr_test_sleep_thr, NULL), ==,
149 149 thrd_success);
150 150 VERIFY3S(thrd_equal(self, other), ==, 0);
151 151 VERIFY3S(thrd_equal(other, other), !=, 0);
152 152 VERIFY3S(thrd_detach(other), ==, thrd_success);
153 153 }
154 154
155 155 static void
156 156 cthr_test_detach_err(void)
157 157 {
158 158 thrd_t self, other;
159 159
160 160 self = thrd_current();
161 161
162 162 VERIFY3S(thrd_equal(self, self), !=, 0);
163 163 VERIFY3S(thrd_create(&other, cthr_test_sleep_thr, NULL), ==,
164 164 thrd_success);
↓ open down ↓ |
141 lines elided |
↑ open up ↑ |
165 165 VERIFY3S(thrd_detach(other), ==, thrd_success);
166 166
167 167 VERIFY3S(thrd_join(self, NULL), ==, thrd_error);
168 168 VERIFY3S(thrd_join(other, NULL), ==, thrd_error);
169 169 }
170 170
171 171 static int
172 172 cthr_test_detach_thr0(void *arg)
173 173 {
174 174 thrd_exit(23);
175 - abort();
176 175 }
177 176
178 177 static int
179 178 cthr_test_detach_thr1(void *arg)
180 179 {
181 180 return (42);
182 181 }
183 182
184 183 static void
185 184 cthr_test_detach(void)
186 185 {
187 186 int status;
188 187 thrd_t thrd;
189 188
190 189 VERIFY3S(thrd_create(&thrd, cthr_test_detach_thr0, NULL), ==,
191 190 thrd_success);
192 191 VERIFY3S(thrd_join(thrd, &status), ==, thrd_success);
193 192 VERIFY3S(status, ==, 23);
194 193
195 194 VERIFY3S(thrd_create(&thrd, cthr_test_detach_thr1, NULL), ==,
196 195 thrd_success);
197 196 VERIFY3S(thrd_join(thrd, &status), ==, thrd_success);
198 197 VERIFY3S(status, ==, 42);
199 198 }
200 199
201 200 static void
202 201 cthr_test_sleep(void)
203 202 {
204 203 struct timespec ts;
205 204 hrtime_t start, end;
206 205 long stime = 10 * NANOSEC / MILLISEC;
207 206
208 207 ts.tv_sec = 1;
209 208 ts.tv_nsec = -1;
210 209
211 210 VERIFY3S(thrd_sleep(&ts, NULL), <, -1);
212 211
213 212 ts.tv_sec = 0;
214 213 ts.tv_nsec = stime;
215 214 start = gethrtime();
216 215 VERIFY3S(thrd_sleep(&ts, NULL), ==, 0);
217 216 end = gethrtime();
218 217
219 218 VERIFY3S(end - start, >, stime);
220 219 }
221 220
222 221 static int
223 222 cthr_test_broadcast_thr(void *arg)
224 223 {
225 224 VERIFY3S(mtx_lock(&broadcast_mtx), ==, thrd_success);
226 225 while (broadcast_done == B_FALSE)
227 226 VERIFY3S(cnd_wait(&broadcast_cnd, &broadcast_mtx), ==,
228 227 thrd_success);
229 228 VERIFY3S(mtx_unlock(&broadcast_mtx), ==, thrd_success);
230 229
231 230 return (0);
232 231 }
233 232
234 233 static void
235 234 cthr_test_broadcast(void)
236 235 {
237 236 int i;
238 237 thrd_t threads[BROADCAST_NTHREADS];
239 238
240 239 VERIFY3S(mtx_init(&broadcast_mtx, mtx_plain), ==, thrd_success);
241 240 VERIFY3S(cnd_init(&broadcast_cnd), ==, thrd_success);
242 241 for (i = 0; i < BROADCAST_NTHREADS; i++) {
243 242 VERIFY3S(thrd_create(&threads[i], cthr_test_broadcast_thr,
244 243 NULL), ==, thrd_success);
245 244 }
246 245
247 246 VERIFY3S(mtx_lock(&broadcast_mtx), ==, thrd_success);
248 247 broadcast_done = B_TRUE;
249 248 VERIFY3S(mtx_unlock(&broadcast_mtx), ==, thrd_success);
250 249 VERIFY3S(cnd_broadcast(&broadcast_cnd), ==, thrd_success);
251 250
252 251 for (i = 0; i < STRESS_NTHREADS; i++) {
253 252 VERIFY3S(thrd_join(threads[i], NULL), ==, thrd_success);
254 253 }
255 254
256 255 mtx_destroy(&broadcast_mtx);
257 256 cnd_destroy(&broadcast_cnd);
258 257 }
259 258
260 259
261 260 static int
262 261 cthr_test_signal_thr(void *arg)
263 262 {
264 263 VERIFY3S(mtx_lock(&signal_mtx), ==, thrd_success);
265 264 while (signal_done == B_FALSE)
266 265 VERIFY3S(cnd_wait(&signal_cnd, &signal_mtx), ==,
267 266 thrd_success);
268 267 VERIFY3S(mtx_unlock(&signal_mtx), ==, thrd_success);
269 268 VERIFY3S(cnd_signal(&signal_cnd), ==, thrd_success);
270 269
271 270 return (0);
272 271 }
273 272
274 273 static void
275 274 cthr_test_signal(void)
276 275 {
277 276 int i;
278 277 thrd_t threads[SIGNAL_NTHREADS];
279 278
280 279 VERIFY3S(mtx_init(&signal_mtx, mtx_plain), ==, thrd_success);
281 280 VERIFY3S(cnd_init(&signal_cnd), ==, thrd_success);
282 281 for (i = 0; i < SIGNAL_NTHREADS; i++) {
283 282 VERIFY3S(thrd_create(&threads[i], cthr_test_signal_thr, NULL),
284 283 ==, thrd_success);
285 284 }
286 285
287 286 VERIFY3S(mtx_lock(&signal_mtx), ==, thrd_success);
288 287 signal_done = B_TRUE;
289 288 VERIFY3S(mtx_unlock(&signal_mtx), ==, thrd_success);
290 289 VERIFY3S(cnd_signal(&signal_cnd), ==, thrd_success);
291 290
292 291 for (i = 0; i < STRESS_NTHREADS; i++) {
293 292 VERIFY3S(thrd_join(threads[i], NULL), ==, thrd_success);
294 293 }
295 294
296 295 mtx_destroy(&signal_mtx);
297 296 cnd_destroy(&signal_cnd);
298 297 }
299 298
300 299 static void
301 300 cthr_test_cndtime(void)
302 301 {
303 302 mtx_t mtx;
304 303 cnd_t cnd;
305 304 struct timespec ts;
306 305
307 306 ts.tv_sec = 0;
308 307 ts.tv_nsec = 1 * NANOSEC / MILLISEC;
309 308 VERIFY3S(mtx_init(&mtx, mtx_plain), ==, thrd_success);
310 309 VERIFY3S(cnd_init(&cnd), ==, thrd_success);
311 310
312 311 VERIFY3S(mtx_lock(&mtx), ==, thrd_success);
313 312 VERIFY3S(cnd_timedwait(&cnd, &mtx, &ts), ==, thrd_timedout);
314 313 VERIFY3S(mtx_unlock(&mtx), ==, thrd_success);
315 314
316 315 mtx_destroy(&mtx);
317 316 cnd_destroy(&cnd);
318 317 }
319 318
320 319 static void
321 320 cthr_test_mtx_selftime(void)
322 321 {
323 322 mtx_t mtx;
324 323 struct timespec ts;
325 324
326 325 ts.tv_sec = 0;
327 326 ts.tv_nsec = 1 * NANOSEC / MILLISEC;
328 327 VERIFY3S(mtx_init(&mtx, mtx_timed), ==, thrd_success);
329 328 VERIFY3S(mtx_lock(&mtx), ==, thrd_success);
330 329 VERIFY3S(mtx_timedlock(&mtx, &ts), ==, thrd_timedout);
331 330 VERIFY3S(mtx_unlock(&mtx), ==, thrd_success);
332 331 mtx_destroy(&mtx);
333 332 }
334 333
335 334 static int
336 335 cthr_test_mtx_busy_thr(void *arg)
337 336 {
338 337 mtx_t *mtx = arg;
339 338 struct timespec ts;
340 339
341 340 ts.tv_sec = 0;
342 341 ts.tv_nsec = 1 * NANOSEC / MILLISEC;
343 342
344 343 VERIFY3S(mtx_trylock(mtx), ==, thrd_busy);
345 344 VERIFY3S(mtx_timedlock(mtx, &ts), ==, thrd_timedout);
346 345
347 346 return (0);
348 347 }
349 348
350 349 static void
351 350 cthr_test_mtx_busy(void)
352 351 {
353 352 mtx_t mtx;
354 353 thrd_t thrd;
355 354
356 355 VERIFY3S(mtx_init(&mtx, mtx_timed), ==, thrd_success);
357 356 VERIFY3S(mtx_lock(&mtx), ==, thrd_success);
358 357
359 358 VERIFY3S(thrd_create(&thrd, cthr_test_mtx_busy_thr, &mtx), ==,
360 359 thrd_success);
361 360 VERIFY3S(thrd_join(thrd, NULL), ==, thrd_success);
362 361
363 362 VERIFY3S(mtx_unlock(&mtx), ==, thrd_success);
364 363 mtx_destroy(&mtx);
365 364 }
366 365
367 366 int
368 367 main(void)
369 368 {
370 369 cthr_test_mtx_init();
371 370 cthr_test_mtx_lockrec();
372 371 cthr_test_mtx_trylock();
373 372 cthr_test_stress();
374 373 cthr_test_equal();
375 374 cthr_test_detach_err();
376 375 cthr_test_detach();
377 376 cthr_test_sleep();
378 377 cthr_test_broadcast();
379 378 cthr_test_signal();
380 379 cthr_test_cndtime();
381 380 cthr_test_mtx_selftime();
382 381 cthr_test_mtx_busy();
383 382
384 383 return (0);
385 384 }
↓ open down ↓ |
200 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX