1*8265fdceSkamil /* $NetBSD: t_join.c,v 1.10 2020/01/29 13:40:23 kamil Exp $ */
2b226f3d0Sjruoho
3b226f3d0Sjruoho /*-
4b226f3d0Sjruoho * Copyright (c) 2010 The NetBSD Foundation, Inc.
5b226f3d0Sjruoho * All rights reserved.
6b226f3d0Sjruoho *
7b226f3d0Sjruoho * This code is derived from software contributed to The NetBSD Foundation
8b226f3d0Sjruoho * by Jukka Ruohonen.
9b226f3d0Sjruoho *
10b226f3d0Sjruoho * Redistribution and use in source and binary forms, with or without
11b226f3d0Sjruoho * modification, are permitted provided that the following conditions
12b226f3d0Sjruoho * are met:
13b226f3d0Sjruoho * 1. Redistributions of source code must retain the above copyright
14b226f3d0Sjruoho * notice, this list of conditions and the following disclaimer.
15b226f3d0Sjruoho * 2. Redistributions in binary form must reproduce the above copyright
16b226f3d0Sjruoho * notice, this list of conditions and the following disclaimer in the
17b226f3d0Sjruoho * documentation and/or other materials provided with the distribution.
18b226f3d0Sjruoho *
19b226f3d0Sjruoho * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20b226f3d0Sjruoho * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21b226f3d0Sjruoho * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22b226f3d0Sjruoho * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23b226f3d0Sjruoho * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24b226f3d0Sjruoho * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25b226f3d0Sjruoho * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26b226f3d0Sjruoho * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27b226f3d0Sjruoho * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28b226f3d0Sjruoho * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29b226f3d0Sjruoho * POSSIBILITY OF SUCH DAMAGE.
30b226f3d0Sjruoho */
31b226f3d0Sjruoho #include <sys/cdefs.h>
32*8265fdceSkamil __RCSID("$NetBSD: t_join.c,v 1.10 2020/01/29 13:40:23 kamil Exp $");
33b226f3d0Sjruoho
34b226f3d0Sjruoho #include <errno.h>
35b226f3d0Sjruoho #include <pthread.h>
36ef311a87Sdholland #include <stdint.h>
37b226f3d0Sjruoho
38b226f3d0Sjruoho #include <atf-c.h>
39b226f3d0Sjruoho
40b226f3d0Sjruoho #include "h_common.h"
41b226f3d0Sjruoho
42236a4409Sjoerg #ifdef CHECK_STACK_ALIGNMENT
43236a4409Sjoerg extern int check_stack_alignment(void);
44236a4409Sjoerg #endif
45236a4409Sjoerg
46e07445e0Sjoerg #define STACKSIZE 65536
47e07445e0Sjoerg
48b226f3d0Sjruoho static bool error;
49b226f3d0Sjruoho
50b226f3d0Sjruoho static void *threadfunc1(void *);
51b226f3d0Sjruoho static void *threadfunc2(void *);
52b226f3d0Sjruoho
53b226f3d0Sjruoho ATF_TC(pthread_join);
ATF_TC_HEAD(pthread_join,tc)54b226f3d0Sjruoho ATF_TC_HEAD(pthread_join, tc)
55b226f3d0Sjruoho {
56b226f3d0Sjruoho
57b226f3d0Sjruoho atf_tc_set_md_var(tc, "descr",
58b226f3d0Sjruoho "Checks basic error conditions in pthread_join(3)");
59b226f3d0Sjruoho }
60b226f3d0Sjruoho
ATF_TC_BODY(pthread_join,tc)61b226f3d0Sjruoho ATF_TC_BODY(pthread_join, tc)
62b226f3d0Sjruoho {
63b226f3d0Sjruoho pthread_t thread;
64b226f3d0Sjruoho
65b226f3d0Sjruoho PTHREAD_REQUIRE(pthread_create(&thread, NULL, threadfunc1, NULL));
66b226f3d0Sjruoho PTHREAD_REQUIRE(pthread_join(thread, NULL));
67b226f3d0Sjruoho }
68b226f3d0Sjruoho
69b226f3d0Sjruoho static void *
threadfunc1(void * arg)70b226f3d0Sjruoho threadfunc1(void *arg)
71b226f3d0Sjruoho {
72b226f3d0Sjruoho pthread_t thread[25];
73b226f3d0Sjruoho pthread_t caller;
74846cca4cShans void *val = NULL;
75846cca4cShans uintptr_t i;
76b226f3d0Sjruoho int rv;
77e07445e0Sjoerg pthread_attr_t attr;
78b226f3d0Sjruoho
79b226f3d0Sjruoho caller = pthread_self();
80b226f3d0Sjruoho
81236a4409Sjoerg #ifdef CHECK_STACK_ALIGNMENT
82236a4409Sjoerg /*
83236a4409Sjoerg * Check alignment of thread stack, if supported.
84236a4409Sjoerg */
85236a4409Sjoerg ATF_REQUIRE(check_stack_alignment());
86236a4409Sjoerg #endif
87236a4409Sjoerg
88b226f3d0Sjruoho /*
89b226f3d0Sjruoho * The behavior is undefined, but should error
90b226f3d0Sjruoho * out, if we try to join the calling thread.
91b226f3d0Sjruoho */
92b226f3d0Sjruoho rv = pthread_join(caller, NULL);
93b226f3d0Sjruoho
94b226f3d0Sjruoho /*
95b226f3d0Sjruoho * The specification recommends EDEADLK.
96b226f3d0Sjruoho */
97b226f3d0Sjruoho ATF_REQUIRE(rv != 0);
98b226f3d0Sjruoho ATF_REQUIRE_EQ(rv, EDEADLK);
99b226f3d0Sjruoho
100e07445e0Sjoerg ATF_REQUIRE(pthread_attr_init(&attr) == 0);
101e07445e0Sjoerg
102b226f3d0Sjruoho for (i = 0; i < __arraycount(thread); i++) {
103b226f3d0Sjruoho
104b226f3d0Sjruoho error = true;
105b226f3d0Sjruoho
106e07445e0Sjoerg ATF_REQUIRE(pthread_attr_setstacksize(&attr, STACKSIZE * (i + 1)) == 0);
1075f391f4aSjoerg ATF_REQUIRE(pthread_attr_setguardsize(&attr, STACKSIZE * (i + 2)) == 0);
108e07445e0Sjoerg
109e07445e0Sjoerg rv = pthread_create(&thread[i], &attr, threadfunc2, (void *)i);
110b226f3d0Sjruoho
111b226f3d0Sjruoho ATF_REQUIRE_EQ(rv, 0);
112b226f3d0Sjruoho
113b226f3d0Sjruoho /*
114b226f3d0Sjruoho * Check join and exit condition.
115b226f3d0Sjruoho */
116b226f3d0Sjruoho PTHREAD_REQUIRE(pthread_join(thread[i], &val));
117b226f3d0Sjruoho
118b226f3d0Sjruoho ATF_REQUIRE_EQ(error, false);
119b226f3d0Sjruoho
120846cca4cShans ATF_REQUIRE(val != NULL);
121846cca4cShans ATF_REQUIRE(val == (void *)(i + 1));
122846cca4cShans
123b226f3d0Sjruoho /*
124b226f3d0Sjruoho * Once the thread has returned, ESRCH should
125b226f3d0Sjruoho * again follow if we try to join it again.
126b226f3d0Sjruoho */
127b226f3d0Sjruoho rv = pthread_join(thread[i], NULL);
128b226f3d0Sjruoho
129b226f3d0Sjruoho ATF_REQUIRE_EQ(rv, ESRCH);
130b226f3d0Sjruoho
131b226f3d0Sjruoho /*
132b226f3d0Sjruoho * Try to detach the exited thread.
133b226f3d0Sjruoho */
134b226f3d0Sjruoho rv = pthread_detach(thread[i]);
135b226f3d0Sjruoho
136b226f3d0Sjruoho ATF_REQUIRE(rv != 0);
137b226f3d0Sjruoho }
138b226f3d0Sjruoho
139e07445e0Sjoerg ATF_REQUIRE(pthread_attr_destroy(&attr) == 0);
140e07445e0Sjoerg
141b226f3d0Sjruoho pthread_exit(NULL);
142b226f3d0Sjruoho
143b226f3d0Sjruoho return NULL;
144b226f3d0Sjruoho }
145b226f3d0Sjruoho
146b226f3d0Sjruoho static void *
threadfunc2(void * arg)147b226f3d0Sjruoho threadfunc2(void *arg)
148b226f3d0Sjruoho {
149846cca4cShans static uintptr_t i = 0;
150846cca4cShans uintptr_t j;
151e07445e0Sjoerg pthread_attr_t attr;
1525f391f4aSjoerg size_t stacksize, guardsize;
153b226f3d0Sjruoho
154846cca4cShans j = (uintptr_t)arg;
155b226f3d0Sjruoho
156*8265fdceSkamil ATF_REQUIRE(pthread_getattr_np(pthread_self(), &attr) == 0);
157e07445e0Sjoerg ATF_REQUIRE(pthread_attr_getstacksize(&attr, &stacksize) == 0);
158e07445e0Sjoerg ATF_REQUIRE(stacksize == STACKSIZE * (j + 1));
1595f391f4aSjoerg ATF_REQUIRE(pthread_attr_getguardsize(&attr, &guardsize) == 0);
1605f391f4aSjoerg ATF_REQUIRE(guardsize == STACKSIZE * (j + 2));
161e07445e0Sjoerg ATF_REQUIRE(pthread_attr_destroy(&attr) == 0);
162e07445e0Sjoerg
163b226f3d0Sjruoho if (i++ == j)
164b226f3d0Sjruoho error = false;
165b226f3d0Sjruoho
166846cca4cShans pthread_exit((void *)i);
167b226f3d0Sjruoho
168b226f3d0Sjruoho return NULL;
169b226f3d0Sjruoho }
170b226f3d0Sjruoho
ATF_TP_ADD_TCS(tp)171b226f3d0Sjruoho ATF_TP_ADD_TCS(tp)
172b226f3d0Sjruoho {
173b226f3d0Sjruoho
174b226f3d0Sjruoho ATF_TP_ADD_TC(tp, pthread_join);
175b226f3d0Sjruoho
176b226f3d0Sjruoho return atf_no_error();
177b226f3d0Sjruoho }
178