6951 Initial c11 support
[unleashed.git] / usr / src / test / libc-tests / tests / c11_threads.c
blobdffadcc2af60f7ef88771b58f599c323b307a243
1 /*
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
5 * 1.0 of the CDDL.
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:
19 * o threads
20 * o mutexes
21 * o condition variables
24 #include <threads.h>
25 #include <sys/debug.h>
26 #include <stdlib.h>
27 #include <unistd.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.
50 static int
51 cthr_test_sleep_thr(void *arg)
53 for (;;) {
54 sleep(1000);
57 abort();
60 static void
61 cthr_test_mtx_init(void)
63 mtx_t mtx;
65 VERIFY3S(mtx_init(&mtx, mtx_plain), ==, thrd_success);
66 mtx_destroy(&mtx);
67 VERIFY3S(mtx_init(&mtx, mtx_timed), ==, thrd_success);
68 mtx_destroy(&mtx);
69 VERIFY3S(mtx_init(&mtx, mtx_plain | mtx_recursive), ==, thrd_success);
70 mtx_destroy(&mtx);
71 VERIFY3S(mtx_init(&mtx, mtx_timed | mtx_recursive), ==, thrd_success);
72 mtx_destroy(&mtx);
74 VERIFY3S(mtx_init(&mtx, UINT32_MAX), ==, thrd_error);
75 VERIFY3S(mtx_init(&mtx, 42), ==, thrd_error);
78 static void
79 cthr_test_mtx_lockrec(void)
81 mtx_t mtx;
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);
90 mtx_destroy(&mtx);
93 static void
94 cthr_test_mtx_trylock(void)
96 mtx_t mtx;
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);
102 mtx_destroy(&mtx);
105 static int
106 cthr_test_stress_thr(void *arg)
108 int i;
109 int *ip = arg;
111 for (i = 0; i < STRESS_COUNT; i++) {
112 VERIFY3S(mtx_lock(&stress_mtx), ==, thrd_success);
113 *ip = *ip + 1;
114 VERIFY3S(mtx_unlock(&stress_mtx), ==, thrd_success);
117 return (0);
120 static void
121 cthr_test_stress(void)
123 int i;
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);
140 static void
141 cthr_test_equal(void)
143 thrd_t self, other;
145 self = thrd_current();
147 VERIFY0(thrd_equal(self, self));
148 VERIFY3S(thrd_create(&other, cthr_test_sleep_thr, NULL), ==,
149 thrd_success);
150 VERIFY3S(thrd_equal(self, other), !=, 0);
151 VERIFY3S(thrd_equal(other, other), ==, 0);
152 VERIFY3S(thrd_detach(other), ==, thrd_success);
155 static void
156 cthr_test_detach_err(void)
158 thrd_t self, other;
160 self = thrd_current();
162 VERIFY0(thrd_equal(self, self));
163 VERIFY3S(thrd_create(&other, cthr_test_sleep_thr, NULL), ==,
164 thrd_success);
165 VERIFY3S(thrd_detach(other), ==, thrd_success);
167 VERIFY3S(thrd_join(self, NULL), ==, thrd_error);
168 VERIFY3S(thrd_join(other, NULL), ==, thrd_error);
171 static int
172 cthr_test_detach_thr0(void *arg)
174 thrd_exit(23);
175 abort();
178 static int
179 cthr_test_detach_thr1(void *arg)
181 return (42);
184 static void
185 cthr_test_detach(void)
187 int status;
188 thrd_t thrd;
190 VERIFY3S(thrd_create(&thrd, cthr_test_detach_thr0, NULL), ==,
191 thrd_success);
192 VERIFY3S(thrd_join(thrd, &status), ==, thrd_success);
193 VERIFY3S(status, ==, 23);
195 VERIFY3S(thrd_create(&thrd, cthr_test_detach_thr1, NULL), ==,
196 thrd_success);
197 VERIFY3S(thrd_join(thrd, &status), ==, thrd_success);
198 VERIFY3S(status, ==, 42);
201 static void
202 cthr_test_sleep(void)
204 struct timespec ts;
205 hrtime_t start, end;
206 long stime = 10 * NANOSEC / MILLISEC;
208 ts.tv_sec = 1;
209 ts.tv_nsec = -1;
211 VERIFY3S(thrd_sleep(&ts, NULL), <, -1);
213 ts.tv_sec = 0;
214 ts.tv_nsec = stime;
215 start = gethrtime();
216 VERIFY3S(thrd_sleep(&ts, NULL), ==, 0);
217 end = gethrtime();
219 VERIFY3S(end - start, >, stime);
222 static int
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), ==,
228 thrd_success);
229 VERIFY3S(mtx_unlock(&broadcast_mtx), ==, thrd_success);
231 return (0);
234 static void
235 cthr_test_broadcast(void)
237 int i;
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);
261 static int
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), ==,
267 thrd_success);
268 VERIFY3S(mtx_unlock(&signal_mtx), ==, thrd_success);
269 VERIFY3S(cnd_signal(&signal_cnd), ==, thrd_success);
271 return (0);
274 static void
275 cthr_test_signal(void)
277 int i;
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),
284 ==, thrd_success);
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);
300 static void
301 cthr_test_cndtime(void)
303 mtx_t mtx;
304 cnd_t cnd;
305 struct timespec ts;
307 ts.tv_sec = 0;
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);
316 mtx_destroy(&mtx);
317 cnd_destroy(&cnd);
320 static void
321 cthr_test_mtx_selftime(void)
323 mtx_t mtx;
324 struct timespec ts;
326 ts.tv_sec = 0;
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);
332 mtx_destroy(&mtx);
335 static int
336 cthr_test_mtx_busy_thr(void *arg)
338 mtx_t *mtx = arg;
339 struct timespec ts;
341 ts.tv_sec = 0;
342 ts.tv_nsec = 1 * NANOSEC / MILLISEC;
344 VERIFY3S(mtx_trylock(mtx), ==, thrd_busy);
345 VERIFY3S(mtx_timedlock(mtx, &ts), ==, thrd_timedout);
347 return (0);
350 static void
351 cthr_test_mtx_busy(void)
353 mtx_t mtx;
354 thrd_t thrd;
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), ==,
360 thrd_success);
361 VERIFY3S(thrd_join(thrd, NULL), ==, thrd_success);
363 VERIFY3S(mtx_unlock(&mtx), ==, thrd_success);
364 mtx_destroy(&mtx);
368 main(void)
370 cthr_test_mtx_init();
371 cthr_test_mtx_lockrec();
372 cthr_test_mtx_trylock();
373 cthr_test_stress();
374 cthr_test_equal();
375 cthr_test_detach_err();
376 cthr_test_detach();
377 cthr_test_sleep();
378 cthr_test_broadcast();
379 cthr_test_signal();
380 cthr_test_cndtime();
381 cthr_test_mtx_selftime();
382 cthr_test_mtx_busy();
384 return (0);