xref: /netbsd-src/tests/lib/libpthread/t_join.c (revision 8265fdce6013b7f1e3c77205ea7bba35a3f19057)
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