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