]> git.proxmox.com Git - mirror_zfs.git/blame - module/os/linux/spl/spl-thread.c
Linux 6.8 compat: implement strlcpy fallback
[mirror_zfs.git] / module / os / linux / spl / spl-thread.c
CommitLineData
4b393c50 1/*
716154c5
BB
2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
3 * Copyright (C) 2007 The Regents of the University of California.
4 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
5 * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
715f6251
BB
6 * UCRL-CODE-235197
7 *
716154c5 8 * This file is part of the SPL, Solaris Porting Layer.
715f6251 9 *
716154c5
BB
10 * The SPL is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * The SPL is distributed in the hope that it will be useful, but WITHOUT
715f6251
BB
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
716154c5 21 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
5461eefe 22 *
716154c5 23 * Solaris Porting Layer (SPL) Thread Implementation.
4b393c50 24 */
715f6251 25
f4b37741 26#include <sys/thread.h>
115aed0d 27#include <sys/kmem.h>
9fe45dc1 28#include <sys/tsd.h>
84980ee0 29#include <sys/string.h>
937879f1 30
f1ca4da6
BB
31/*
32 * Thread interfaces
33 */
34typedef struct thread_priv_s {
35 unsigned long tp_magic; /* Magic */
5461eefe
BB
36 int tp_name_size; /* Name size */
37 char *tp_name; /* Name (without _thread suffix) */
f1ca4da6
BB
38 void (*tp_func)(void *); /* Registered function */
39 void *tp_args; /* Args to be passed to function */
40 size_t tp_len; /* Len to be passed to function */
41 int tp_state; /* State to start thread at */
42 pri_t tp_pri; /* Priority to start threat at */
f1ca4da6
BB
43} thread_priv_t;
44
f1b59d26 45static int
f1ca4da6
BB
46thread_generic_wrapper(void *arg)
47{
48 thread_priv_t *tp = (thread_priv_t *)arg;
49 void (*func)(void *);
50 void *args;
f1ca4da6 51
937879f1 52 ASSERT(tp->tp_magic == TP_MAGIC);
f1ca4da6
BB
53 func = tp->tp_func;
54 args = tp->tp_args;
f1ca4da6 55 set_current_state(tp->tp_state);
44e406d7 56 set_user_nice((kthread_t *)current, PRIO_TO_NICE(tp->tp_pri));
a97df54e 57 kmem_free(tp->tp_name, tp->tp_name_size);
5461eefe 58 kmem_free(tp, sizeof (thread_priv_t));
f1ca4da6 59
f1ca4da6
BB
60 if (func)
61 func(args);
62
5461eefe 63 return (0);
f1ca4da6
BB
64}
65
5461eefe
BB
66/*
67 * thread_create() may block forever if it cannot create a thread or
f1ca4da6 68 * allocate memory. This is preferable to returning a NULL which Solaris
5461eefe
BB
69 * style callers likely never check for... since it can't fail.
70 */
f1ca4da6 71kthread_t *
51f443a0 72__thread_create(caddr_t stk, size_t stksize, thread_func_t func,
3673d032 73 const char *name, void *args, size_t len, proc_t *pp, int state, pri_t pri)
f1ca4da6 74{
115aed0d 75 thread_priv_t *tp;
968eccd1 76 struct task_struct *tsk;
a97df54e 77 char *p;
f1ca4da6
BB
78
79 /* Option pp is simply ignored */
80 /* Variable stack size unsupported */
937879f1 81 ASSERT(stk == NULL);
f1ca4da6 82
5461eefe 83 tp = kmem_alloc(sizeof (thread_priv_t), KM_PUSHPAGE);
115aed0d 84 if (tp == NULL)
8d9a23e8 85 return (NULL);
f1ca4da6 86
115aed0d 87 tp->tp_magic = TP_MAGIC;
a97df54e
BB
88 tp->tp_name_size = strlen(name) + 1;
89
3050c931 90 tp->tp_name = kmem_alloc(tp->tp_name_size, KM_PUSHPAGE);
5461eefe
BB
91 if (tp->tp_name == NULL) {
92 kmem_free(tp, sizeof (thread_priv_t));
8d9a23e8 93 return (NULL);
a97df54e
BB
94 }
95
7584fbe8 96 strlcpy(tp->tp_name, name, tp->tp_name_size);
a97df54e 97
5461eefe
BB
98 /*
99 * Strip trailing "_thread" from passed name which will be the func
a97df54e
BB
100 * name since the exposed API has no parameter for passing a name.
101 */
102 p = strstr(tp->tp_name, "_thread");
103 if (p)
104 p[0] = '\0';
105
115aed0d
BB
106 tp->tp_func = func;
107 tp->tp_args = args;
108 tp->tp_len = len;
109 tp->tp_state = state;
110 tp->tp_pri = pri;
f1ca4da6 111
17a527cb 112 tsk = spl_kthread_create(thread_generic_wrapper, (void *)tp,
5461eefe 113 "%s", tp->tp_name);
8d9a23e8
BB
114 if (IS_ERR(tsk))
115 return (NULL);
968eccd1
BB
116
117 wake_up_process(tsk);
8d9a23e8 118 return ((kthread_t *)tsk);
f1ca4da6 119}
f1b59d26 120EXPORT_SYMBOL(__thread_create);
ed650dee
TC
121
122/*
123 * spl_kthread_create - Wrapper providing pre-3.13 semantics for
124 * kthread_create() in which it is not killable and less likely
125 * to return -ENOMEM.
126 */
127struct task_struct *
128spl_kthread_create(int (*func)(void *), void *data, const char namefmt[], ...)
129{
130 struct task_struct *tsk;
131 va_list args;
3ceb71e8 132 char name[TASK_COMM_LEN];
ed650dee
TC
133
134 va_start(args, namefmt);
5461eefe 135 vsnprintf(name, sizeof (name), namefmt, args);
3ceb71e8 136 va_end(args);
ed650dee 137 do {
3ceb71e8 138 tsk = kthread_create(func, data, "%s", name);
ed650dee
TC
139 if (IS_ERR(tsk)) {
140 if (signal_pending(current)) {
141 clear_thread_flag(TIF_SIGPENDING);
142 continue;
143 }
144 if (PTR_ERR(tsk) == -ENOMEM)
145 continue;
146 return (NULL);
8062b768 147 } else {
ed650dee 148 return (tsk);
8062b768 149 }
ed650dee
TC
150 } while (1);
151}
152EXPORT_SYMBOL(spl_kthread_create);
414f7249
PD
153
154/*
155 * The "why" argument indicates the allowable side-effects of the call:
156 *
157 * FORREAL: Extract the next pending signal from p_sig into p_cursig;
158 * stop the process if a stop has been requested or if a traced signal
159 * is pending.
160 *
161 * JUSTLOOKING: Don't stop the process, just indicate whether or not
162 * a signal might be pending (FORREAL is needed to tell for sure).
163 */
164int
165issig(int why)
166{
167 ASSERT(why == FORREAL || why == JUSTLOOKING);
168
169 if (!signal_pending(current))
170 return (0);
171
172 if (why != FORREAL)
173 return (1);
174
175 struct task_struct *task = current;
176 spl_kernel_siginfo_t __info;
177 sigset_t set;
178 siginitsetinv(&set, 1ULL << (SIGSTOP - 1) | 1ULL << (SIGTSTP - 1));
179 sigorsets(&set, &task->blocked, &set);
180
181 spin_lock_irq(&task->sighand->siglock);
a4623710
AZ
182#ifdef HAVE_DEQUEUE_SIGNAL_4ARG
183 enum pid_type __type;
2e7f664f 184 if (dequeue_signal(task, &set, &__info, &__type) != 0) {
a4623710 185#else
2e7f664f 186 if (dequeue_signal(task, &set, &__info) != 0) {
a4623710 187#endif
414f7249
PD
188#ifdef HAVE_SIGNAL_STOP
189 spin_unlock_irq(&task->sighand->siglock);
190 kernel_signal_stop();
191#else
192 if (current->jobctl & JOBCTL_STOP_DEQUEUED)
193 spl_set_special_state(TASK_STOPPED);
194
195 spin_unlock_irq(&current->sighand->siglock);
196
197 schedule();
198#endif
199 return (0);
200 }
201
202 spin_unlock_irq(&task->sighand->siglock);
203
204 return (1);
205}
206
207EXPORT_SYMBOL(issig);