1fc2512cfSRobert Mustacchi /*
2fc2512cfSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3fc2512cfSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4fc2512cfSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5fc2512cfSRobert Mustacchi  * 1.0 of the CDDL.
6fc2512cfSRobert Mustacchi  *
7fc2512cfSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8fc2512cfSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9fc2512cfSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10fc2512cfSRobert Mustacchi  */
11fc2512cfSRobert Mustacchi 
12fc2512cfSRobert Mustacchi /*
13fc2512cfSRobert Mustacchi  * Copyright 2016 Joyent, Inc.
14fc2512cfSRobert Mustacchi  */
15fc2512cfSRobert Mustacchi 
16fc2512cfSRobert Mustacchi /*
17fc2512cfSRobert Mustacchi  * Test call_once(3C)
18fc2512cfSRobert Mustacchi  */
19fc2512cfSRobert Mustacchi 
20fc2512cfSRobert Mustacchi #include <threads.h>
21fc2512cfSRobert Mustacchi #include <sys/debug.h>
22fc2512cfSRobert Mustacchi 
23fc2512cfSRobert Mustacchi #define	CO_NTHREADS	32
24fc2512cfSRobert Mustacchi 
25fc2512cfSRobert Mustacchi static int co_val = 41;
26fc2512cfSRobert Mustacchi static mtx_t co_once_mtx;
27fc2512cfSRobert Mustacchi static mtx_t co_mtx;
28fc2512cfSRobert Mustacchi static boolean_t co_go = B_FALSE;
29fc2512cfSRobert Mustacchi static once_flag co_once = ONCE_FLAG_INIT;
30fc2512cfSRobert Mustacchi static cnd_t co_cnd;
31fc2512cfSRobert Mustacchi 
32fc2512cfSRobert Mustacchi static void
co_once_func(void)33fc2512cfSRobert Mustacchi co_once_func(void)
34fc2512cfSRobert Mustacchi {
35fc2512cfSRobert Mustacchi 	VERIFY3S(mtx_lock(&co_once_mtx), ==, thrd_success);
36fc2512cfSRobert Mustacchi 	co_val++;
37fc2512cfSRobert Mustacchi 	VERIFY3S(mtx_unlock(&co_once_mtx), ==, thrd_success);
38fc2512cfSRobert Mustacchi }
39fc2512cfSRobert Mustacchi 
40fc2512cfSRobert Mustacchi /*ARGSUSED*/
41fc2512cfSRobert Mustacchi static int
co_thr(void * arg)42fc2512cfSRobert Mustacchi co_thr(void *arg)
43fc2512cfSRobert Mustacchi {
44fc2512cfSRobert Mustacchi 	VERIFY3S(mtx_lock(&co_mtx), ==, thrd_success);
45*b36afad7SRobert Mustacchi 	while (co_go == B_FALSE) {
46*b36afad7SRobert Mustacchi 		(void) cnd_wait(&co_cnd, &co_mtx);
47*b36afad7SRobert Mustacchi 	}
48fc2512cfSRobert Mustacchi 	VERIFY3S(mtx_unlock(&co_mtx), ==, thrd_success);
49fc2512cfSRobert Mustacchi 	call_once(&co_once, co_once_func);
50fc2512cfSRobert Mustacchi 	return (0);
51fc2512cfSRobert Mustacchi }
52fc2512cfSRobert Mustacchi 
53fc2512cfSRobert Mustacchi int
main(void)54fc2512cfSRobert Mustacchi main(void)
55fc2512cfSRobert Mustacchi {
56fc2512cfSRobert Mustacchi 	int i;
57fc2512cfSRobert Mustacchi 	thrd_t threads[CO_NTHREADS];
58fc2512cfSRobert Mustacchi 
59fc2512cfSRobert Mustacchi 	VERIFY3S(mtx_init(&co_once_mtx, mtx_plain), ==, thrd_success);
60fc2512cfSRobert Mustacchi 	VERIFY3S(mtx_init(&co_mtx, mtx_plain), ==, thrd_success);
61fc2512cfSRobert Mustacchi 	VERIFY3S(cnd_init(&co_cnd), ==, thrd_success);
62fc2512cfSRobert Mustacchi 
63fc2512cfSRobert Mustacchi 	for (i = 0; i < CO_NTHREADS; i++) {
64fc2512cfSRobert Mustacchi 		VERIFY3S(thrd_create(&threads[i], co_thr, NULL), ==,
65fc2512cfSRobert Mustacchi 		    thrd_success);
66fc2512cfSRobert Mustacchi 	}
67fc2512cfSRobert Mustacchi 
68fc2512cfSRobert Mustacchi 	VERIFY3S(mtx_lock(&co_mtx), ==, thrd_success);
69fc2512cfSRobert Mustacchi 	co_go = B_TRUE;
70fc2512cfSRobert Mustacchi 	VERIFY3S(mtx_unlock(&co_mtx), ==, thrd_success);
71fc2512cfSRobert Mustacchi 	VERIFY3S(cnd_broadcast(&co_cnd), ==, thrd_success);
72fc2512cfSRobert Mustacchi 
73fc2512cfSRobert Mustacchi 	for (i = 0; i < CO_NTHREADS; i++) {
74fc2512cfSRobert Mustacchi 		VERIFY3S(thrd_join(threads[i], NULL), ==, thrd_success);
75fc2512cfSRobert Mustacchi 	}
76fc2512cfSRobert Mustacchi 	VERIFY3S(co_val, ==, 42);
77fc2512cfSRobert Mustacchi 
78fc2512cfSRobert Mustacchi 	return (0);
79fc2512cfSRobert Mustacchi }
80