xref: /netbsd-src/tests/lib/libpthread/t_once.c (revision af29f831e2a90d6e143ec09ba662218a53b1d3c5)
1*af29f831Sginsbach /* $NetBSD: t_once.c,v 1.2 2017/08/25 22:59:47 ginsbach Exp $ */
2ac555471Sjmmv 
3ac555471Sjmmv /*
4ac555471Sjmmv  * Copyright (c) 2008 The NetBSD Foundation, Inc.
5ac555471Sjmmv  * All rights reserved.
6ac555471Sjmmv  *
7ac555471Sjmmv  * Redistribution and use in source and binary forms, with or without
8ac555471Sjmmv  * modification, are permitted provided that the following conditions
9ac555471Sjmmv  * are met:
10ac555471Sjmmv  * 1. Redistributions of source code must retain the above copyright
11ac555471Sjmmv  *    notice, this list of conditions and the following disclaimer.
12ac555471Sjmmv  * 2. Redistributions in binary form must reproduce the above copyright
13ac555471Sjmmv  *    notice, this list of conditions and the following disclaimer in the
14ac555471Sjmmv  *    documentation and/or other materials provided with the distribution.
15ac555471Sjmmv  *
16ac555471Sjmmv  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17ac555471Sjmmv  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18ac555471Sjmmv  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19ac555471Sjmmv  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20ac555471Sjmmv  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21ac555471Sjmmv  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22ac555471Sjmmv  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23ac555471Sjmmv  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24ac555471Sjmmv  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25ac555471Sjmmv  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26ac555471Sjmmv  * POSSIBILITY OF SUCH DAMAGE.
27ac555471Sjmmv  */
28ac555471Sjmmv 
29ac555471Sjmmv #include <sys/cdefs.h>
30ac555471Sjmmv __COPYRIGHT("@(#) Copyright (c) 2008\
31ac555471Sjmmv  The NetBSD Foundation, inc. All rights reserved.");
32*af29f831Sginsbach __RCSID("$NetBSD: t_once.c,v 1.2 2017/08/25 22:59:47 ginsbach Exp $");
33ac555471Sjmmv 
34*af29f831Sginsbach #include <sys/time.h>
35ac555471Sjmmv #include <pthread.h>
36ac555471Sjmmv #include <signal.h>
37ac555471Sjmmv #include <stdio.h>
38ac555471Sjmmv #include <stdlib.h>
39ac555471Sjmmv 
40ac555471Sjmmv #include <atf-c.h>
41ac555471Sjmmv 
42ac555471Sjmmv #include "h_common.h"
43ac555471Sjmmv 
44ac555471Sjmmv static pthread_once_t once = PTHREAD_ONCE_INIT;
45ac555471Sjmmv static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
46ac555471Sjmmv static int x;
47ac555471Sjmmv 
48ac555471Sjmmv #define NTHREADS 25
49ac555471Sjmmv 
50ac555471Sjmmv static void
ofunc(void)51ac555471Sjmmv ofunc(void)
52ac555471Sjmmv {
53ac555471Sjmmv 	printf("Variable x has value %d\n", x);
54ac555471Sjmmv 	x++;
55ac555471Sjmmv }
56ac555471Sjmmv 
57ac555471Sjmmv ATF_TC(once1);
ATF_TC_HEAD(once1,tc)58ac555471Sjmmv ATF_TC_HEAD(once1, tc)
59ac555471Sjmmv {
60ac555471Sjmmv 	atf_tc_set_md_var(tc, "descr", "Checks pthread_once()");
61ac555471Sjmmv }
ATF_TC_BODY(once1,tc)62ac555471Sjmmv ATF_TC_BODY(once1, tc)
63ac555471Sjmmv {
64ac555471Sjmmv 
65ac555471Sjmmv 	printf("1: Test 1 of pthread_once()\n");
66ac555471Sjmmv 
67ac555471Sjmmv 	PTHREAD_REQUIRE(pthread_once(&once, ofunc));
68ac555471Sjmmv 	PTHREAD_REQUIRE(pthread_once(&once, ofunc));
69ac555471Sjmmv 
70ac555471Sjmmv 	printf("1: X has value %d\n",x );
71ac555471Sjmmv 	ATF_REQUIRE_EQ(x, 1);
72ac555471Sjmmv }
73ac555471Sjmmv 
74ac555471Sjmmv static void
once2_ofunc(void)75ac555471Sjmmv once2_ofunc(void)
76ac555471Sjmmv {
77ac555471Sjmmv 	x++;
78ac555471Sjmmv 	printf("ofunc: Variable x has value %d\n", x);
79ac555471Sjmmv 	x++;
80ac555471Sjmmv }
81ac555471Sjmmv 
82ac555471Sjmmv static void *
once2_threadfunc(void * arg)83ac555471Sjmmv once2_threadfunc(void *arg)
84ac555471Sjmmv {
85ac555471Sjmmv 	int num;
86ac555471Sjmmv 
87ac555471Sjmmv 	PTHREAD_REQUIRE(pthread_once(&once, once2_ofunc));
88ac555471Sjmmv 
89ac555471Sjmmv 	num = *(int *)arg;
90ac555471Sjmmv 	printf("Thread %d sees x with value %d\n", num, x);
91ac555471Sjmmv 	ATF_REQUIRE_EQ(x, 2);
92ac555471Sjmmv 
93ac555471Sjmmv 	return NULL;
94ac555471Sjmmv }
95ac555471Sjmmv 
96ac555471Sjmmv ATF_TC(once2);
ATF_TC_HEAD(once2,tc)97ac555471Sjmmv ATF_TC_HEAD(once2, tc)
98ac555471Sjmmv {
99ac555471Sjmmv 	atf_tc_set_md_var(tc, "descr", "Checks pthread_once()");
100ac555471Sjmmv }
ATF_TC_BODY(once2,tc)101ac555471Sjmmv ATF_TC_BODY(once2, tc)
102ac555471Sjmmv {
103ac555471Sjmmv 	pthread_t  threads[NTHREADS];
104ac555471Sjmmv 	int id[NTHREADS];
105ac555471Sjmmv 	int i;
106ac555471Sjmmv 
107ac555471Sjmmv 	printf("1: Test 2 of pthread_once()\n");
108ac555471Sjmmv 
109ac555471Sjmmv 	for (i=0; i < NTHREADS; i++) {
110ac555471Sjmmv 		id[i] = i;
111ac555471Sjmmv 		PTHREAD_REQUIRE(pthread_create(&threads[i], NULL, once2_threadfunc, &id[i]));
112ac555471Sjmmv 	}
113ac555471Sjmmv 
114ac555471Sjmmv 	for (i=0; i < NTHREADS; i++)
115ac555471Sjmmv 		PTHREAD_REQUIRE(pthread_join(threads[i], NULL));
116ac555471Sjmmv 
117ac555471Sjmmv 	printf("1: X has value %d\n",x );
118ac555471Sjmmv 	ATF_REQUIRE_EQ(x, 2);
119ac555471Sjmmv }
120ac555471Sjmmv 
121ac555471Sjmmv static void
once3_cleanup(void * m)122ac555471Sjmmv once3_cleanup(void *m)
123ac555471Sjmmv {
124ac555471Sjmmv 	pthread_mutex_t *mu = m;
125ac555471Sjmmv 
126ac555471Sjmmv 	PTHREAD_REQUIRE(pthread_mutex_unlock(mu));
127ac555471Sjmmv }
128ac555471Sjmmv 
129ac555471Sjmmv static void
once3_ofunc(void)130ac555471Sjmmv once3_ofunc(void)
131ac555471Sjmmv {
132ac555471Sjmmv 	pthread_testcancel();
133ac555471Sjmmv }
134ac555471Sjmmv 
135ac555471Sjmmv static void *
once3_threadfunc(void * arg)136ac555471Sjmmv once3_threadfunc(void *arg)
137ac555471Sjmmv {
138ac555471Sjmmv 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
139ac555471Sjmmv 	pthread_cleanup_push(once3_cleanup, &mutex);
140ac555471Sjmmv 	PTHREAD_REQUIRE(pthread_once(&once, once3_ofunc));
141ac555471Sjmmv 	pthread_cleanup_pop(1);
142ac555471Sjmmv 
143ac555471Sjmmv 	return NULL;
144ac555471Sjmmv }
145ac555471Sjmmv 
146ac555471Sjmmv static void
handler(int sig,siginfo_t * info,void * ctx)147ac555471Sjmmv handler(int sig, siginfo_t *info, void *ctx)
148ac555471Sjmmv {
149ac555471Sjmmv 	atf_tc_fail("Signal handler was called; "
150ac555471Sjmmv 		"main thread deadlocked in pthread_once()");
151ac555471Sjmmv }
152ac555471Sjmmv 
153ac555471Sjmmv ATF_TC(once3);
ATF_TC_HEAD(once3,tc)154ac555471Sjmmv ATF_TC_HEAD(once3, tc)
155ac555471Sjmmv {
156ac555471Sjmmv 	atf_tc_set_md_var(tc, "descr", "Checks pthread_once()");
157ac555471Sjmmv }
ATF_TC_BODY(once3,tc)158ac555471Sjmmv ATF_TC_BODY(once3, tc)
159ac555471Sjmmv {
160ac555471Sjmmv 	pthread_t thread;
161ac555471Sjmmv 	struct sigaction act;
162ac555471Sjmmv 	struct itimerval it;
163ac555471Sjmmv 	printf("Test 3 of pthread_once() (test versus cancellation)\n");
164ac555471Sjmmv 
165ac555471Sjmmv 	act.sa_sigaction = handler;
166ac555471Sjmmv 	sigemptyset(&act.sa_mask);
167ac555471Sjmmv 	act.sa_flags = SA_SIGINFO;
168ac555471Sjmmv 	sigaction(SIGALRM, &act, NULL);
169ac555471Sjmmv 
170ac555471Sjmmv 	timerclear(&it.it_value);
171ac555471Sjmmv 	it.it_value.tv_usec = 500000;
172ac555471Sjmmv 	timerclear(&it.it_interval);
173ac555471Sjmmv 	setitimer(ITIMER_REAL, &it, NULL);
174ac555471Sjmmv 
175ac555471Sjmmv 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
176ac555471Sjmmv 	PTHREAD_REQUIRE(pthread_create(&thread, NULL, once3_threadfunc, NULL));
177ac555471Sjmmv 	PTHREAD_REQUIRE(pthread_cancel(thread));
178ac555471Sjmmv 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
179ac555471Sjmmv 	PTHREAD_REQUIRE(pthread_join(thread, NULL));
180ac555471Sjmmv 
181ac555471Sjmmv 	PTHREAD_REQUIRE(pthread_once(&once, ofunc));
182ac555471Sjmmv 
183ac555471Sjmmv 	/* Cancel timer */
184ac555471Sjmmv 	timerclear(&it.it_value);
185ac555471Sjmmv 	setitimer(ITIMER_REAL, &it, NULL);
186ac555471Sjmmv 
187ac555471Sjmmv 	printf("Test succeeded\n");
188ac555471Sjmmv }
189ac555471Sjmmv 
ATF_TP_ADD_TCS(tp)190ac555471Sjmmv ATF_TP_ADD_TCS(tp)
191ac555471Sjmmv {
192ac555471Sjmmv 	ATF_TP_ADD_TC(tp, once1);
193ac555471Sjmmv 	ATF_TP_ADD_TC(tp, once2);
194ac555471Sjmmv 	ATF_TP_ADD_TC(tp, once3);
195ac555471Sjmmv 
196ac555471Sjmmv 	return atf_no_error();
197ac555471Sjmmv }
198