2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright 2016 Joyent, Inc.
17 * Validate various C11 threads routines. Specifically we want to cover:
21 * o condition variables
25 #include <sys/debug.h>
29 #define STRESS_NTHREADS 128
30 #define STRESS_COUNT 1000
32 static mtx_t stress_mtx
;
33 static int stress_count
;
35 #define BROADCAST_NTHREADS 128
37 static mtx_t broadcast_mtx
;
38 static cnd_t broadcast_cnd
;
39 static boolean_t broadcast_done
;
41 #define SIGNAL_NTHREADS 128
43 static mtx_t signal_mtx
;
44 static cnd_t signal_cnd
;
45 static boolean_t signal_done
;
48 * This thread should only ever be used for detach.
51 cthr_test_sleep_thr(void *arg
)
61 cthr_test_mtx_init(void)
65 VERIFY3S(mtx_init(&mtx
, mtx_plain
), ==, thrd_success
);
67 VERIFY3S(mtx_init(&mtx
, mtx_timed
), ==, thrd_success
);
69 VERIFY3S(mtx_init(&mtx
, mtx_plain
| mtx_recursive
), ==, thrd_success
);
71 VERIFY3S(mtx_init(&mtx
, mtx_timed
| mtx_recursive
), ==, thrd_success
);
74 VERIFY3S(mtx_init(&mtx
, UINT32_MAX
), ==, thrd_error
);
75 VERIFY3S(mtx_init(&mtx
, 42), ==, thrd_error
);
79 cthr_test_mtx_lockrec(void)
83 VERIFY3S(mtx_init(&mtx
, mtx_plain
| mtx_recursive
), ==, thrd_success
);
84 VERIFY3S(mtx_lock(&mtx
), ==, thrd_success
);
85 VERIFY3S(mtx_lock(&mtx
), ==, thrd_success
);
86 VERIFY3S(mtx_trylock(&mtx
), ==, thrd_success
);
87 VERIFY3S(mtx_unlock(&mtx
), ==, thrd_success
);
88 VERIFY3S(mtx_unlock(&mtx
), ==, thrd_success
);
89 VERIFY3S(mtx_unlock(&mtx
), ==, thrd_success
);
94 cthr_test_mtx_trylock(void)
98 VERIFY3S(mtx_init(&mtx
, mtx_plain
), ==, thrd_success
);
99 VERIFY3S(mtx_trylock(&mtx
), ==, thrd_success
);
100 VERIFY3S(mtx_trylock(&mtx
), ==, thrd_busy
);
101 VERIFY3S(mtx_unlock(&mtx
), ==, thrd_success
);
106 cthr_test_stress_thr(void *arg
)
111 for (i
= 0; i
< STRESS_COUNT
; i
++) {
112 VERIFY3S(mtx_lock(&stress_mtx
), ==, thrd_success
);
114 VERIFY3S(mtx_unlock(&stress_mtx
), ==, thrd_success
);
121 cthr_test_stress(void)
124 thrd_t threads
[STRESS_NTHREADS
];
126 VERIFY3S(mtx_init(&stress_mtx
, mtx_plain
), ==, thrd_success
);
127 for (i
= 0; i
< STRESS_NTHREADS
; i
++) {
128 VERIFY3S(thrd_create(&threads
[i
], cthr_test_stress_thr
,
129 &stress_count
), ==, thrd_success
);
132 for (i
= 0; i
< STRESS_NTHREADS
; i
++) {
133 VERIFY3S(thrd_join(threads
[i
], NULL
), ==, thrd_success
);
135 mtx_destroy(&stress_mtx
);
137 VERIFY3S(stress_count
, ==, STRESS_NTHREADS
* STRESS_COUNT
);
141 cthr_test_equal(void)
145 self
= thrd_current();
147 VERIFY0(thrd_equal(self
, self
));
148 VERIFY3S(thrd_create(&other
, cthr_test_sleep_thr
, NULL
), ==,
150 VERIFY3S(thrd_equal(self
, other
), !=, 0);
151 VERIFY3S(thrd_equal(other
, other
), ==, 0);
152 VERIFY3S(thrd_detach(other
), ==, thrd_success
);
156 cthr_test_detach_err(void)
160 self
= thrd_current();
162 VERIFY0(thrd_equal(self
, self
));
163 VERIFY3S(thrd_create(&other
, cthr_test_sleep_thr
, NULL
), ==,
165 VERIFY3S(thrd_detach(other
), ==, thrd_success
);
167 VERIFY3S(thrd_join(self
, NULL
), ==, thrd_error
);
168 VERIFY3S(thrd_join(other
, NULL
), ==, thrd_error
);
172 cthr_test_detach_thr0(void *arg
)
179 cthr_test_detach_thr1(void *arg
)
185 cthr_test_detach(void)
190 VERIFY3S(thrd_create(&thrd
, cthr_test_detach_thr0
, NULL
), ==,
192 VERIFY3S(thrd_join(thrd
, &status
), ==, thrd_success
);
193 VERIFY3S(status
, ==, 23);
195 VERIFY3S(thrd_create(&thrd
, cthr_test_detach_thr1
, NULL
), ==,
197 VERIFY3S(thrd_join(thrd
, &status
), ==, thrd_success
);
198 VERIFY3S(status
, ==, 42);
202 cthr_test_sleep(void)
206 long stime
= 10 * NANOSEC
/ MILLISEC
;
211 VERIFY3S(thrd_sleep(&ts
, NULL
), <, -1);
216 VERIFY3S(thrd_sleep(&ts
, NULL
), ==, 0);
219 VERIFY3S(end
- start
, >, stime
);
223 cthr_test_broadcast_thr(void *arg
)
225 VERIFY3S(mtx_lock(&broadcast_mtx
), ==, thrd_success
);
226 while (broadcast_done
== B_FALSE
)
227 VERIFY3S(cnd_wait(&broadcast_cnd
, &broadcast_mtx
), ==,
229 VERIFY3S(mtx_unlock(&broadcast_mtx
), ==, thrd_success
);
235 cthr_test_broadcast(void)
238 thrd_t threads
[BROADCAST_NTHREADS
];
240 VERIFY3S(mtx_init(&broadcast_mtx
, mtx_plain
), ==, thrd_success
);
241 VERIFY3S(cnd_init(&broadcast_cnd
), ==, thrd_success
);
242 for (i
= 0; i
< BROADCAST_NTHREADS
; i
++) {
243 VERIFY3S(thrd_create(&threads
[i
], cthr_test_broadcast_thr
,
244 NULL
), ==, thrd_success
);
247 VERIFY3S(mtx_lock(&broadcast_mtx
), ==, thrd_success
);
248 broadcast_done
= B_TRUE
;
249 VERIFY3S(mtx_unlock(&broadcast_mtx
), ==, thrd_success
);
250 VERIFY3S(cnd_broadcast(&broadcast_cnd
), ==, thrd_success
);
252 for (i
= 0; i
< STRESS_NTHREADS
; i
++) {
253 VERIFY3S(thrd_join(threads
[i
], NULL
), ==, thrd_success
);
256 mtx_destroy(&broadcast_mtx
);
257 cnd_destroy(&broadcast_cnd
);
262 cthr_test_signal_thr(void *arg
)
264 VERIFY3S(mtx_lock(&signal_mtx
), ==, thrd_success
);
265 while (signal_done
== B_FALSE
)
266 VERIFY3S(cnd_wait(&signal_cnd
, &signal_mtx
), ==,
268 VERIFY3S(mtx_unlock(&signal_mtx
), ==, thrd_success
);
269 VERIFY3S(cnd_signal(&signal_cnd
), ==, thrd_success
);
275 cthr_test_signal(void)
278 thrd_t threads
[SIGNAL_NTHREADS
];
280 VERIFY3S(mtx_init(&signal_mtx
, mtx_plain
), ==, thrd_success
);
281 VERIFY3S(cnd_init(&signal_cnd
), ==, thrd_success
);
282 for (i
= 0; i
< SIGNAL_NTHREADS
; i
++) {
283 VERIFY3S(thrd_create(&threads
[i
], cthr_test_signal_thr
, NULL
),
287 VERIFY3S(mtx_lock(&signal_mtx
), ==, thrd_success
);
288 signal_done
= B_TRUE
;
289 VERIFY3S(mtx_unlock(&signal_mtx
), ==, thrd_success
);
290 VERIFY3S(cnd_signal(&signal_cnd
), ==, thrd_success
);
292 for (i
= 0; i
< STRESS_NTHREADS
; i
++) {
293 VERIFY3S(thrd_join(threads
[i
], NULL
), ==, thrd_success
);
296 mtx_destroy(&signal_mtx
);
297 cnd_destroy(&signal_cnd
);
301 cthr_test_cndtime(void)
308 ts
.tv_nsec
= 1 * NANOSEC
/ MILLISEC
;
309 VERIFY3S(mtx_init(&mtx
, mtx_plain
), ==, thrd_success
);
310 VERIFY3S(cnd_init(&cnd
), ==, thrd_success
);
312 VERIFY3S(mtx_lock(&mtx
), ==, thrd_success
);
313 VERIFY3S(cnd_timedwait(&cnd
, &mtx
, &ts
), ==, thrd_timedout
);
314 VERIFY3S(mtx_unlock(&mtx
), ==, thrd_success
);
321 cthr_test_mtx_selftime(void)
327 ts
.tv_nsec
= 1 * NANOSEC
/ MILLISEC
;
328 VERIFY3S(mtx_init(&mtx
, mtx_timed
), ==, thrd_success
);
329 VERIFY3S(mtx_lock(&mtx
), ==, thrd_success
);
330 VERIFY3S(mtx_timedlock(&mtx
, &ts
), ==, thrd_timedout
);
331 VERIFY3S(mtx_unlock(&mtx
), ==, thrd_success
);
336 cthr_test_mtx_busy_thr(void *arg
)
342 ts
.tv_nsec
= 1 * NANOSEC
/ MILLISEC
;
344 VERIFY3S(mtx_trylock(mtx
), ==, thrd_busy
);
345 VERIFY3S(mtx_timedlock(mtx
, &ts
), ==, thrd_timedout
);
351 cthr_test_mtx_busy(void)
356 VERIFY3S(mtx_init(&mtx
, mtx_timed
), ==, thrd_success
);
357 VERIFY3S(mtx_lock(&mtx
), ==, thrd_success
);
359 VERIFY3S(thrd_create(&thrd
, cthr_test_mtx_busy_thr
, &mtx
), ==,
361 VERIFY3S(thrd_join(thrd
, NULL
), ==, thrd_success
);
363 VERIFY3S(mtx_unlock(&mtx
), ==, thrd_success
);
370 cthr_test_mtx_init();
371 cthr_test_mtx_lockrec();
372 cthr_test_mtx_trylock();
375 cthr_test_detach_err();
378 cthr_test_broadcast();
381 cthr_test_mtx_selftime();
382 cthr_test_mtx_busy();