xref: /netbsd-src/tests/lib/libpthread/t_thrd.c (revision 76c7fc5f6b13ed0b1508e6b313e88e59977ed78e)
1 /*	$NetBSD: t_thrd.c,v 1.1 2019/04/24 11:43:19 kamil Exp $	*/
2 
3 /*-
4  * Copyright (c) 2019 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Kamil Rytarowski.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 __COPYRIGHT("@(#) Copyright (c) 2019\
34  The NetBSD Foundation, inc. All rights reserved.");
35 __RCSID("$NetBSD: t_thrd.c,v 1.1 2019/04/24 11:43:19 kamil Exp $");
36 
37 #include <signal.h>
38 #include <stdbool.h>
39 #include <threads.h>
40 #include <time.h>
41 
42 #include <atf-c.h>
43 
44 ATF_TC(thrd_create);
45 ATF_TC_HEAD(thrd_create, tc)
46 {
47 	atf_tc_set_md_var(tc, "descr", "Test C11 thrd_create(3)");
48 }
49 
50 #define TC_ADDON 5
51 
52 static int
53 tcr_func(void *arg)
54 {
55 	int a;
56 
57 	a = (int)(intptr_t)arg;
58 
59 	return a + TC_ADDON;
60 }
61 
62 ATF_TC_BODY(thrd_create, tc)
63 {
64 	thrd_t t;
65 	const int a = 5;
66 	int b;
67 	void *v;
68 
69 	v = (void *)(intptr_t)a;
70 
71 	ATF_REQUIRE_EQ(thrd_create(&t, tcr_func, v), thrd_success);
72 	ATF_REQUIRE_EQ(thrd_join(t, &b), thrd_success);
73 	ATF_REQUIRE_EQ(a + TC_ADDON, b);
74 }
75 
76 ATF_TC(thrd_current);
77 ATF_TC_HEAD(thrd_current, tc)
78 {
79 	atf_tc_set_md_var(tc, "descr", "Test C11 thrd_current(3)");
80 }
81 
82 static int
83 tcur_func(void *arg __unused)
84 {
85 
86 	return 0;
87 }
88 
89 ATF_TC_BODY(thrd_current, tc)
90 {
91 	thrd_t s, t;
92 
93 	s = thrd_current();
94 
95 	ATF_REQUIRE(thrd_equal(s, s) != 0);
96 	ATF_REQUIRE_EQ(thrd_create(&t, tcur_func, NULL), thrd_success);
97 	ATF_REQUIRE(thrd_equal(t, s) == 0);
98 	ATF_REQUIRE(thrd_equal(s, t) == 0);
99 	ATF_REQUIRE(thrd_equal(t, t) != 0);
100 
101 	ATF_REQUIRE_EQ(thrd_join(t, NULL), thrd_success);
102 }
103 
104 ATF_TC(thrd_detach);
105 ATF_TC_HEAD(thrd_detach, tc)
106 {
107 	atf_tc_set_md_var(tc, "descr", "Test C11 thrd_detach(3)");
108 }
109 
110 static int
111 tdet_func(void *arg __unused)
112 {
113 
114 	return 0;
115 }
116 
117 ATF_TC_BODY(thrd_detach, tc)
118 {
119 	thrd_t t;
120 
121 	ATF_REQUIRE_EQ(thrd_create(&t, tdet_func, NULL), thrd_success);
122 	ATF_REQUIRE_EQ(thrd_detach(t), thrd_success);
123 }
124 
125 ATF_TC(thrd_exit);
126 ATF_TC_HEAD(thrd_exit, tc)
127 {
128 	atf_tc_set_md_var(tc, "descr", "Test C11 thrd_exit(3)");
129 }
130 
131 static void
132 tex_func2(void)
133 {
134 
135 	thrd_exit(1);
136 }
137 
138 static int
139 tex_func(void *arg __unused)
140 {
141 
142 	tex_func2();
143 
144 	return -1;
145 }
146 
147 ATF_TC_BODY(thrd_exit, tc)
148 {
149 	thrd_t t;
150 	int b = 0;
151 
152 	ATF_REQUIRE_EQ(thrd_create(&t, tex_func, NULL), thrd_success);
153 	ATF_REQUIRE_EQ(thrd_join(t, &b), thrd_success);
154 	ATF_REQUIRE_EQ(b, 1);
155 }
156 
157 ATF_TC(thrd_sleep);
158 ATF_TC_HEAD(thrd_sleep, tc)
159 {
160 	atf_tc_set_md_var(tc, "descr", "Test C11 thrd_sleep(3)");
161 }
162 
163 static int alarmed;
164 
165 static void
166 alarm_handler(int signum)
167 {
168 
169 	ATF_REQUIRE_EQ(signum, SIGALRM);
170 	++alarmed;
171 }
172 
173 ATF_TC_BODY(thrd_sleep, tc)
174 {
175 	struct timespec start, stop, diff;
176 	struct timespec ts, rem;
177 	struct timespec zero;
178 	struct sigaction sa;
179 	struct itimerval timer;
180 
181 	zero.tv_sec = 0;
182 	zero.tv_nsec = 0;
183 
184 	ts.tv_sec = 1;
185 	ts.tv_nsec = -1;
186 	ATF_REQUIRE_EQ(!thrd_sleep(&ts, NULL), 0);
187 
188 	ts.tv_sec = 0;
189 	ts.tv_nsec = 1000000000/100; /* 1/100 sec */
190 	ATF_REQUIRE_EQ(clock_gettime(CLOCK_MONOTONIC, &start), 0);
191 	ATF_REQUIRE_EQ(thrd_sleep(&ts, &rem), 0);
192 	ATF_REQUIRE_EQ(clock_gettime(CLOCK_MONOTONIC, &stop), 0);
193 	timespecsub(&stop, &start, &diff);
194 	ATF_REQUIRE(timespeccmp(&diff, &ts, >=));
195 	ATF_REQUIRE(timespeccmp(&zero, &rem, ==));
196 
197 	ts.tv_sec = 1;
198 	ts.tv_nsec = 0;
199 	memset(&sa, 0, sizeof(sa));
200 	sa.sa_handler = alarm_handler;
201 	sigaction(SIGALRM, &sa, NULL);
202 	memset(&timer, 0, sizeof(timer));
203 	timer.it_value.tv_sec = 0;
204 	timer.it_value.tv_usec = 100000; /* 100 msec */
205 	ATF_REQUIRE_EQ(setitimer(ITIMER_MONOTONIC, &timer, NULL), 0);
206 	ATF_REQUIRE_EQ(clock_gettime(CLOCK_MONOTONIC, &start), 0);
207 	ATF_REQUIRE_EQ(!thrd_sleep(&ts, &rem), 0);
208 	ATF_REQUIRE_EQ(clock_gettime(CLOCK_MONOTONIC, &stop), 0);
209 	timespecsub(&stop, &start, &diff);
210 	ATF_REQUIRE(timespeccmp(&diff, &ts, <));
211 	ATF_REQUIRE(timespeccmp(&zero, &rem, !=));
212 	ATF_REQUIRE_EQ(alarmed, 1);
213 }
214 
215 ATF_TC(thrd_yield);
216 ATF_TC_HEAD(thrd_yield, tc)
217 {
218 	atf_tc_set_md_var(tc, "descr", "Test C11 thrd_yield(3)");
219 }
220 
221 ATF_TC_BODY(thrd_yield, tc)
222 {
223 
224 	thrd_yield();
225 }
226 
227 ATF_TP_ADD_TCS(tp)
228 {
229 	ATF_TP_ADD_TC(tp, thrd_create);
230 	ATF_TP_ADD_TC(tp, thrd_current);
231 	ATF_TP_ADD_TC(tp, thrd_detach);
232 	ATF_TP_ADD_TC(tp, thrd_exit);
233 	ATF_TP_ADD_TC(tp, thrd_sleep);
234 	ATF_TP_ADD_TC(tp, thrd_yield);;
235 
236 	return atf_no_error();
237 }
238