1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3 * CDDL HEADER START
4 *
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License (the "License").
7 * You may not use this file except in compliance with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or https://opensource.org/licenses/CDDL-1.0.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
25 * Copyright (c) 2016 Actifio, Inc. All rights reserved.
26 * Copyright (c) 2025, Klara, Inc.
27 */
28
29 #include <assert.h>
30 #include <pthread.h>
31 #include <string.h>
32 #include <sys/thread.h>
33
34 /* this only exists to have its address taken */
p0(void)35 void p0(void) {}
36
37 /*
38 * =========================================================================
39 * threads
40 * =========================================================================
41 *
42 * TS_STACK_MIN is dictated by the minimum allowed pthread stack size. While
43 * TS_STACK_MAX is somewhat arbitrary, it was selected to be large enough for
44 * the expected stack depth while small enough to avoid exhausting address
45 * space with high thread counts.
46 */
47 #define TS_STACK_MIN MAX(PTHREAD_STACK_MIN, 32768)
48 #define TS_STACK_MAX (256 * 1024)
49
50 struct zk_thread_wrapper {
51 void (*func)(void *);
52 void *arg;
53 };
54
55 static void *
zk_thread_wrapper(void * arg)56 zk_thread_wrapper(void *arg)
57 {
58 struct zk_thread_wrapper ztw;
59 memcpy(&ztw, arg, sizeof (ztw));
60 free(arg);
61 ztw.func(ztw.arg);
62 return (NULL);
63 }
64
65 kthread_t *
zk_thread_create(const char * name,void (* func)(void *),void * arg,size_t stksize,int state)66 zk_thread_create(const char *name, void (*func)(void *), void *arg,
67 size_t stksize, int state)
68 {
69 pthread_attr_t attr;
70 pthread_t tid;
71 char *stkstr;
72 struct zk_thread_wrapper *ztw;
73 int detachstate = PTHREAD_CREATE_DETACHED;
74
75 VERIFY0(pthread_attr_init(&attr));
76
77 if (state & TS_JOINABLE)
78 detachstate = PTHREAD_CREATE_JOINABLE;
79
80 VERIFY0(pthread_attr_setdetachstate(&attr, detachstate));
81
82 /*
83 * We allow the default stack size in user space to be specified by
84 * setting the ZFS_STACK_SIZE environment variable. This allows us
85 * the convenience of observing and debugging stack overruns in
86 * user space. Explicitly specified stack sizes will be honored.
87 * The usage of ZFS_STACK_SIZE is discussed further in the
88 * ENVIRONMENT VARIABLES sections of the ztest(1) man page.
89 */
90 if (stksize == 0) {
91 stkstr = getenv("ZFS_STACK_SIZE");
92
93 if (stkstr == NULL)
94 stksize = TS_STACK_MAX;
95 else
96 stksize = MAX(atoi(stkstr), TS_STACK_MIN);
97 }
98
99 VERIFY3S(stksize, >, 0);
100 stksize = P2ROUNDUP(MAX(stksize, TS_STACK_MIN), PAGESIZE);
101
102 /*
103 * If this ever fails, it may be because the stack size is not a
104 * multiple of system page size.
105 */
106 VERIFY0(pthread_attr_setstacksize(&attr, stksize));
107 VERIFY0(pthread_attr_setguardsize(&attr, PAGESIZE));
108
109 VERIFY(ztw = malloc(sizeof (*ztw)));
110 ztw->func = func;
111 ztw->arg = arg;
112 VERIFY0(pthread_create(&tid, &attr, zk_thread_wrapper, ztw));
113 VERIFY0(pthread_attr_destroy(&attr));
114
115 pthread_setname_np(tid, name);
116
117 return ((void *)(uintptr_t)tid);
118 }
119