1 /* $NetBSD: t_thrd.c,v 1.2 2020/05/14 08:34:19 msaitoh 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.2 2020/05/14 08:34:19 msaitoh 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);
ATF_TC_HEAD(thrd_create,tc)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
tcr_func(void * arg)53 tcr_func(void *arg)
54 {
55 int a;
56
57 a = (int)(intptr_t)arg;
58
59 return a + TC_ADDON;
60 }
61
ATF_TC_BODY(thrd_create,tc)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);
ATF_TC_HEAD(thrd_current,tc)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
tcur_func(void * arg __unused)83 tcur_func(void *arg __unused)
84 {
85
86 return 0;
87 }
88
ATF_TC_BODY(thrd_current,tc)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);
ATF_TC_HEAD(thrd_detach,tc)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
tdet_func(void * arg __unused)111 tdet_func(void *arg __unused)
112 {
113
114 return 0;
115 }
116
ATF_TC_BODY(thrd_detach,tc)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);
ATF_TC_HEAD(thrd_exit,tc)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
tex_func2(void)132 tex_func2(void)
133 {
134
135 thrd_exit(1);
136 }
137
138 static int
tex_func(void * arg __unused)139 tex_func(void *arg __unused)
140 {
141
142 tex_func2();
143
144 return -1;
145 }
146
ATF_TC_BODY(thrd_exit,tc)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);
ATF_TC_HEAD(thrd_sleep,tc)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
alarm_handler(int signum)166 alarm_handler(int signum)
167 {
168
169 ATF_REQUIRE_EQ(signum, SIGALRM);
170 ++alarmed;
171 }
172
ATF_TC_BODY(thrd_sleep,tc)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);
ATF_TC_HEAD(thrd_yield,tc)216 ATF_TC_HEAD(thrd_yield, tc)
217 {
218 atf_tc_set_md_var(tc, "descr", "Test C11 thrd_yield(3)");
219 }
220
ATF_TC_BODY(thrd_yield,tc)221 ATF_TC_BODY(thrd_yield, tc)
222 {
223
224 thrd_yield();
225 }
226
ATF_TP_ADD_TCS(tp)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