1139804Simp/*-
2112899Sjeff * Copyright (c) 2003, Jeffrey Roberson <jeff@freebsd.org>
3112899Sjeff * All rights reserved.
4112899Sjeff *
5112899Sjeff * Redistribution and use in source and binary forms, with or without
6112899Sjeff * modification, are permitted provided that the following conditions
7112899Sjeff * are met:
8112899Sjeff * 1. Redistributions of source code must retain the above copyright
9112899Sjeff *    notice unmodified, this list of conditions, and the following
10112899Sjeff *    disclaimer.
11112899Sjeff * 2. Redistributions in binary form must reproduce the above copyright
12112899Sjeff *    notice, this list of conditions and the following disclaimer in the
13112899Sjeff *    documentation and/or other materials provided with the distribution.
14112899Sjeff *
15112899Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16112899Sjeff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17112899Sjeff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18112899Sjeff * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19112899Sjeff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20112899Sjeff * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21112899Sjeff * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22112899Sjeff * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23112899Sjeff * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24112899Sjeff * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25112899Sjeff */
26112899Sjeff
27116182Sobrien#include <sys/cdefs.h>
28116182Sobrien__FBSDID("$FreeBSD: stable/11/sys/kern/kern_thr.c 337242 2018-08-03 14:05:22Z asomers $");
29116182Sobrien
30162551Sdavidxu#include "opt_compat.h"
31160319Sdavidxu#include "opt_posix.h"
32112899Sjeff#include <sys/param.h>
33112899Sjeff#include <sys/kernel.h>
34112899Sjeff#include <sys/lock.h>
35112899Sjeff#include <sys/mutex.h>
36164033Srwatson#include <sys/priv.h>
37112899Sjeff#include <sys/proc.h>
38164188Strhodes#include <sys/posix4.h>
39304188Sjhb#include <sys/ptrace.h>
40220222Strasz#include <sys/racct.h>
41112899Sjeff#include <sys/resourcevar.h>
42214238Sdavidxu#include <sys/rwlock.h>
43113373Sjeff#include <sys/sched.h>
44134886Sjulian#include <sys/sysctl.h>
45134791Sjulian#include <sys/smp.h>
46170404Sjhb#include <sys/syscallsubr.h>
47112899Sjeff#include <sys/sysent.h>
48112899Sjeff#include <sys/systm.h>
49112899Sjeff#include <sys/sysproto.h>
50112899Sjeff#include <sys/signalvar.h>
51218972Skib#include <sys/sysctl.h>
52112899Sjeff#include <sys/ucontext.h>
53112899Sjeff#include <sys/thr.h>
54160254Sdavidxu#include <sys/rtprio.h>
55151692Sdavidxu#include <sys/umtx.h>
56151692Sdavidxu#include <sys/limits.h>
57112899Sjeff
58285387Sadrian#include <vm/vm_domain.h>
59285387Sadrian
60112899Sjeff#include <machine/frame.h>
61112899Sjeff
62171859Sdavidxu#include <security/audit/audit.h>
63171859Sdavidxu
64227309Sedstatic SYSCTL_NODE(_kern, OID_AUTO, threads, CTLFLAG_RW, 0,
65227309Sed    "thread allocation");
66218972Skib
67218972Skibstatic int max_threads_per_proc = 1500;
68218972SkibSYSCTL_INT(_kern_threads, OID_AUTO, max_threads_per_proc, CTLFLAG_RW,
69228449Seadler    &max_threads_per_proc, 0, "Limit on threads per proc");
70218972Skib
71218972Skibstatic int max_threads_hits;
72218972SkibSYSCTL_INT(_kern_threads, OID_AUTO, max_threads_hits, CTLFLAG_RD,
73228449Seadler    &max_threads_hits, 0, "kern.threads.max_threads_per_proc hit count");
74218972Skib
75205014Snwhitehorn#ifdef COMPAT_FREEBSD32
76162551Sdavidxu
77162551Sdavidxustatic inline int
78162551Sdavidxusuword_lwpid(void *addr, lwpid_t lwpid)
79162551Sdavidxu{
80162551Sdavidxu	int error;
81162551Sdavidxu
82185169Skib	if (SV_CURPROC_FLAG(SV_LP64))
83162551Sdavidxu		error = suword(addr, lwpid);
84162551Sdavidxu	else
85162551Sdavidxu		error = suword32(addr, lwpid);
86162551Sdavidxu	return (error);
87162551Sdavidxu}
88162551Sdavidxu
89162551Sdavidxu#else
90162551Sdavidxu#define suword_lwpid	suword
91162551Sdavidxu#endif
92162551Sdavidxu
93112899Sjeff/*
94112899Sjeff * System call interface.
95112899Sjeff */
96285715Sed
97285715Sedstruct thr_create_initthr_args {
98285715Sed	ucontext_t ctx;
99285715Sed	long *tid;
100285715Sed};
101285715Sed
102285715Sedstatic int
103285715Sedthr_create_initthr(struct thread *td, void *thunk)
104285715Sed{
105285715Sed	struct thr_create_initthr_args *args;
106285715Sed
107285715Sed	/* Copy out the child tid. */
108285715Sed	args = thunk;
109285715Sed	if (args->tid != NULL && suword_lwpid(args->tid, td->td_tid))
110285715Sed		return (EFAULT);
111285715Sed
112285715Sed	return (set_mcontext(td, &args->ctx.uc_mcontext));
113285715Sed}
114285715Sed
115112899Sjeffint
116225617Skmacysys_thr_create(struct thread *td, struct thr_create_args *uap)
117131431Smarcel    /* ucontext_t *ctx, long *id, int flags */
118112899Sjeff{
119285715Sed	struct thr_create_initthr_args args;
120112899Sjeff	int error;
121145434Sdavidxu
122285715Sed	if ((error = copyin(uap->ctx, &args.ctx, sizeof(args.ctx))))
123145434Sdavidxu		return (error);
124285715Sed	args.tid = uap->id;
125285715Sed	return (thread_create(td, NULL, thr_create_initthr, &args));
126145434Sdavidxu}
127145434Sdavidxu
128145434Sdavidxuint
129225617Skmacysys_thr_new(struct thread *td, struct thr_new_args *uap)
130145434Sdavidxu    /* struct thr_param * */
131145434Sdavidxu{
132145434Sdavidxu	struct thr_param param;
133145434Sdavidxu	int error;
134145434Sdavidxu
135162551Sdavidxu	if (uap->param_size < 0 || uap->param_size > sizeof(param))
136145434Sdavidxu		return (EINVAL);
137162497Sdavidxu	bzero(&param, sizeof(param));
138162551Sdavidxu	if ((error = copyin(uap->param, &param, uap->param_size)))
139145434Sdavidxu		return (error);
140162551Sdavidxu	return (kern_thr_new(td, &param));
141162551Sdavidxu}
142162551Sdavidxu
143285715Sedstatic int
144285715Sedthr_new_initthr(struct thread *td, void *thunk)
145285715Sed{
146285715Sed	stack_t stack;
147285715Sed	struct thr_param *param;
148285715Sed
149285715Sed	/*
150285715Sed	 * Here we copy out tid to two places, one for child and one
151285715Sed	 * for parent, because pthread can create a detached thread,
152285715Sed	 * if parent wants to safely access child tid, it has to provide
153285715Sed	 * its storage, because child thread may exit quickly and
154285715Sed	 * memory is freed before parent thread can access it.
155285715Sed	 */
156285715Sed	param = thunk;
157285715Sed	if ((param->child_tid != NULL &&
158285715Sed	    suword_lwpid(param->child_tid, td->td_tid)) ||
159285715Sed	    (param->parent_tid != NULL &&
160285715Sed	    suword_lwpid(param->parent_tid, td->td_tid)))
161285715Sed		return (EFAULT);
162285715Sed
163285715Sed	/* Set up our machine context. */
164285715Sed	stack.ss_sp = param->stack_base;
165285715Sed	stack.ss_size = param->stack_size;
166285715Sed	/* Set upcall address to user thread entry function. */
167301961Skib	cpu_set_upcall(td, param->start_func, param->arg, &stack);
168285715Sed	/* Setup user TLS address and TLS pointer register. */
169285715Sed	return (cpu_set_user_tls(td, param->tls_base));
170285715Sed}
171285715Sed
172162551Sdavidxuint
173162551Sdavidxukern_thr_new(struct thread *td, struct thr_param *param)
174162551Sdavidxu{
175162551Sdavidxu	struct rtprio rtp, *rtpp;
176162551Sdavidxu	int error;
177162551Sdavidxu
178162497Sdavidxu	rtpp = NULL;
179162551Sdavidxu	if (param->rtp != 0) {
180162551Sdavidxu		error = copyin(param->rtp, &rtp, sizeof(struct rtprio));
181183846Srdivacky		if (error)
182183846Srdivacky			return (error);
183162497Sdavidxu		rtpp = &rtp;
184160254Sdavidxu	}
185285715Sed	return (thread_create(td, rtpp, thr_new_initthr, param));
186145434Sdavidxu}
187145434Sdavidxu
188285715Sedint
189285715Sedthread_create(struct thread *td, struct rtprio *rtp,
190285715Sed    int (*initialize_thread)(struct thread *, void *), void *thunk)
191145434Sdavidxu{
192145434Sdavidxu	struct thread *newtd;
193134791Sjulian	struct proc *p;
194160252Sdavidxu	int error;
195112899Sjeff
196134791Sjulian	p = td->td_proc;
197112899Sjeff
198162497Sdavidxu	if (rtp != NULL) {
199162497Sdavidxu		switch(rtp->type) {
200162497Sdavidxu		case RTP_PRIO_REALTIME:
201162497Sdavidxu		case RTP_PRIO_FIFO:
202160259Sdavidxu			/* Only root can set scheduler policy */
203164033Srwatson			if (priv_check(td, PRIV_SCHED_SETPOLICY) != 0)
204160254Sdavidxu				return (EPERM);
205162497Sdavidxu			if (rtp->prio > RTP_PRIO_MAX)
206160254Sdavidxu				return (EINVAL);
207160259Sdavidxu			break;
208162497Sdavidxu		case RTP_PRIO_NORMAL:
209162497Sdavidxu			rtp->prio = 0;
210160259Sdavidxu			break;
211160259Sdavidxu		default:
212160259Sdavidxu			return (EINVAL);
213160254Sdavidxu		}
214160254Sdavidxu	}
215160254Sdavidxu
216223825Strasz#ifdef RACCT
217282213Strasz	if (racct_enable) {
218282213Strasz		PROC_LOCK(p);
219282213Strasz		error = racct_add(p, RACCT_NTHR, 1);
220282213Strasz		PROC_UNLOCK(p);
221282213Strasz		if (error != 0)
222282213Strasz			return (EPROCLIM);
223282213Strasz	}
224223825Strasz#endif
225220222Strasz
226164936Sjulian	/* Initialize our td */
227283373Sdchagin	error = kern_thr_alloc(p, 0, &newtd);
228283373Sdchagin	if (error)
229220222Strasz		goto fail;
230145434Sdavidxu
231301961Skib	cpu_copy_thread(newtd, td);
232228360Spho
233134791Sjulian	bzero(&newtd->td_startzero,
234137946Sdas	    __rangeof(struct thread, td_startzero, td_endzero));
235304883Skib	newtd->td_sleeptimo = 0;
236331842Skib	newtd->td_vslock_sz = 0;
237324932Sbdrewery	bzero(&newtd->td_si, sizeof(newtd->td_si));
238134791Sjulian	bcopy(&td->td_startcopy, &newtd->td_startcopy,
239137946Sdas	    __rangeof(struct thread, td_startcopy, td_endcopy));
240321343Skib	newtd->td_sa = td->td_sa;
241134791Sjulian	newtd->td_proc = td->td_proc;
242302195Skib	newtd->td_rb_list = newtd->td_rbp_list = newtd->td_rb_inact = 0;
243284214Smjg	thread_cow_get(newtd, td);
244112899Sjeff
245285715Sed	error = initialize_thread(newtd, thunk);
246285715Sed	if (error != 0) {
247285715Sed		thread_cow_free(newtd);
248285715Sed		thread_free(newtd);
249285715Sed		goto fail;
250131431Smarcel	}
251112899Sjeff
252282032Smjg	PROC_LOCK(p);
253282032Smjg	p->p_flag |= P_HADTHREADS;
254282032Smjg	thread_link(newtd, p);
255173625Sjulian	bcopy(p->p_comm, newtd->td_name, sizeof(newtd->td_name));
256170307Sjeff	thread_lock(td);
257134791Sjulian	/* let the scheduler know about these things. */
258134791Sjulian	sched_fork_thread(td, newtd);
259170307Sjeff	thread_unlock(td);
260177471Sjeff	if (P_SHOULDSTOP(p))
261177471Sjeff		newtd->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK;
262304188Sjhb	if (p->p_ptevents & PTRACE_LWP)
263292894Sjhb		newtd->td_dbgflags |= TDB_BORN;
264285387Sadrian
265285387Sadrian	/*
266285387Sadrian	 * Copy the existing thread VM policy into the new thread.
267285387Sadrian	 */
268285387Sadrian	vm_domain_policy_localcopy(&newtd->td_vm_dom_policy,
269285387Sadrian	    &td->td_vm_dom_policy);
270285387Sadrian
271170307Sjeff	PROC_UNLOCK(p);
272213642Sdavidxu
273213642Sdavidxu	tidhash_add(newtd);
274213642Sdavidxu
275170307Sjeff	thread_lock(newtd);
276162497Sdavidxu	if (rtp != NULL) {
277163709Sjb		if (!(td->td_pri_class == PRI_TIMESHARE &&
278163709Sjb		      rtp->type == RTP_PRIO_NORMAL)) {
279163709Sjb			rtp_to_pri(rtp, newtd);
280163709Sjb			sched_prio(newtd, newtd->td_user_pri);
281163709Sjb		} /* ignore timesharing class */
282163709Sjb	}
283134791Sjulian	TD_SET_CAN_RUN(newtd);
284177514Sdavidxu	sched_add(newtd, SRQ_BORING);
285170307Sjeff	thread_unlock(newtd);
286112899Sjeff
287189074Sed	return (0);
288220222Strasz
289220222Straszfail:
290223825Strasz#ifdef RACCT
291282213Strasz	if (racct_enable) {
292282213Strasz		PROC_LOCK(p);
293282213Strasz		racct_sub(p, RACCT_NTHR, 1);
294282213Strasz		PROC_UNLOCK(p);
295282213Strasz	}
296223825Strasz#endif
297220222Strasz	return (error);
298112899Sjeff}
299112899Sjeff
300112899Sjeffint
301225617Skmacysys_thr_self(struct thread *td, struct thr_self_args *uap)
302131431Smarcel    /* long *id */
303112899Sjeff{
304112899Sjeff	int error;
305112899Sjeff
306162551Sdavidxu	error = suword_lwpid(uap->id, (unsigned)td->td_tid);
307162551Sdavidxu	if (error == -1)
308162551Sdavidxu		return (EFAULT);
309112899Sjeff	return (0);
310112899Sjeff}
311112899Sjeff
312112899Sjeffint
313225617Skmacysys_thr_exit(struct thread *td, struct thr_exit_args *uap)
314136192Smtm    /* long *state */
315112899Sjeff{
316112899Sjeff
317300043Skib	umtx_thread_exit(td);
318300043Skib
319136192Smtm	/* Signal userland that it can free the stack. */
320151692Sdavidxu	if ((void *)uap->state != NULL) {
321162551Sdavidxu		suword_lwpid(uap->state, 1);
322178648Sdavidxu		kern_umtx_wake(td, uap->state, INT_MAX, 0);
323151692Sdavidxu	}
324136192Smtm
325283372Sdchagin	return (kern_thr_exit(td));
326283372Sdchagin}
327283372Sdchagin
328283372Sdchaginint
329283372Sdchaginkern_thr_exit(struct thread *td)
330283372Sdchagin{
331283372Sdchagin	struct proc *p;
332283372Sdchagin
333283372Sdchagin	p = td->td_proc;
334283372Sdchagin
335292894Sjhb	/*
336292894Sjhb	 * If all of the threads in a process call this routine to
337292894Sjhb	 * exit (e.g. all threads call pthread_exit()), exactly one
338292894Sjhb	 * thread should return to the caller to terminate the process
339292894Sjhb	 * instead of the thread.
340292894Sjhb	 *
341292894Sjhb	 * Checking p_numthreads alone is not sufficient since threads
342292894Sjhb	 * might be committed to terminating while the PROC_LOCK is
343292894Sjhb	 * dropped in either ptracestop() or while removing this thread
344292894Sjhb	 * from the tidhash.  Instead, the p_pendingexits field holds
345292894Sjhb	 * the count of threads in either of those states and a thread
346292894Sjhb	 * is considered the "last" thread if all of the other threads
347292894Sjhb	 * in a process are already terminating.
348292894Sjhb	 */
349112899Sjeff	PROC_LOCK(p);
350292894Sjhb	if (p->p_numthreads == p->p_pendingexits + 1) {
351292894Sjhb		/*
352292894Sjhb		 * Ignore attempts to shut down last thread in the
353292894Sjhb		 * proc.  This will actually call _exit(2) in the
354292894Sjhb		 * usermode trampoline when it returns.
355292894Sjhb		 */
356292894Sjhb		PROC_UNLOCK(p);
357292894Sjhb		return (0);
358134791Sjulian	}
359274038Skib
360292894Sjhb	p->p_pendingexits++;
361292894Sjhb	td->td_dbgflags |= TDB_EXIT;
362304188Sjhb	if (p->p_ptevents & PTRACE_LWP)
363315949Sbadger		ptracestop(td, SIGTRAP, NULL);
364292894Sjhb	PROC_UNLOCK(p);
365292894Sjhb	tidhash_remove(td);
366292894Sjhb	PROC_LOCK(p);
367292894Sjhb	p->p_pendingexits--;
368292894Sjhb
369274038Skib	/*
370292894Sjhb	 * The check above should prevent all other threads from this
371292894Sjhb	 * process from exiting while the PROC_LOCK is dropped, so
372292894Sjhb	 * there must be at least one other thread other than the
373292894Sjhb	 * current thread.
374274038Skib	 */
375292894Sjhb	KASSERT(p->p_numthreads > 1, ("too few threads"));
376292894Sjhb	racct_sub(p, RACCT_NTHR, 1);
377292894Sjhb	tdsigcleanup(td);
378337242Sasomers
379337242Sasomers#ifdef AUDIT
380337242Sasomers	AUDIT_SYSCALL_EXIT(0, td);
381337242Sasomers#endif
382337242Sasomers
383292894Sjhb	PROC_SLOCK(p);
384292894Sjhb	thread_stopped(p);
385292894Sjhb	thread_exit();
386292894Sjhb	/* NOTREACHED */
387112899Sjeff}
388112899Sjeff
389112899Sjeffint
390225617Skmacysys_thr_kill(struct thread *td, struct thr_kill_args *uap)
391131431Smarcel    /* long id, int sig */
392112899Sjeff{
393204519Sbruno	ksiginfo_t ksi;
394112899Sjeff	struct thread *ttd;
395112899Sjeff	struct proc *p;
396112899Sjeff	int error;
397112899Sjeff
398112899Sjeff	p = td->td_proc;
399204519Sbruno	ksiginfo_init(&ksi);
400204519Sbruno	ksi.ksi_signo = uap->sig;
401211732Sdavidxu	ksi.ksi_code = SI_LWP;
402204519Sbruno	ksi.ksi_pid = p->p_pid;
403204519Sbruno	ksi.ksi_uid = td->td_ucred->cr_ruid;
404154093Sdavidxu	if (uap->id == -1) {
405154093Sdavidxu		if (uap->sig != 0 && !_SIG_VALID(uap->sig)) {
406154093Sdavidxu			error = EINVAL;
407154093Sdavidxu		} else {
408154093Sdavidxu			error = ESRCH;
409213642Sdavidxu			PROC_LOCK(p);
410154093Sdavidxu			FOREACH_THREAD_IN_PROC(p, ttd) {
411154093Sdavidxu				if (ttd != td) {
412154093Sdavidxu					error = 0;
413154093Sdavidxu					if (uap->sig == 0)
414154093Sdavidxu						break;
415209592Sjhb					tdksignal(ttd, uap->sig, &ksi);
416154093Sdavidxu				}
417154093Sdavidxu			}
418213642Sdavidxu			PROC_UNLOCK(p);
419154093Sdavidxu		}
420154093Sdavidxu	} else {
421213642Sdavidxu		error = 0;
422213642Sdavidxu		ttd = tdfind((lwpid_t)uap->id, p->p_pid);
423154093Sdavidxu		if (ttd == NULL)
424213642Sdavidxu			return (ESRCH);
425213642Sdavidxu		if (uap->sig == 0)
426154093Sdavidxu			;
427154093Sdavidxu		else if (!_SIG_VALID(uap->sig))
428154093Sdavidxu			error = EINVAL;
429213642Sdavidxu		else
430209592Sjhb			tdksignal(ttd, uap->sig, &ksi);
431213642Sdavidxu		PROC_UNLOCK(ttd->td_proc);
432112899Sjeff	}
433112899Sjeff	return (error);
434112899Sjeff}
435127482Smtm
436127482Smtmint
437225617Skmacysys_thr_kill2(struct thread *td, struct thr_kill2_args *uap)
438171859Sdavidxu    /* pid_t pid, long id, int sig */
439171859Sdavidxu{
440204519Sbruno	ksiginfo_t ksi;
441171859Sdavidxu	struct thread *ttd;
442171859Sdavidxu	struct proc *p;
443171859Sdavidxu	int error;
444171859Sdavidxu
445195104Srwatson	AUDIT_ARG_SIGNUM(uap->sig);
446171859Sdavidxu
447213642Sdavidxu	ksiginfo_init(&ksi);
448213642Sdavidxu	ksi.ksi_signo = uap->sig;
449213642Sdavidxu	ksi.ksi_code = SI_LWP;
450213642Sdavidxu	ksi.ksi_pid = td->td_proc->p_pid;
451213642Sdavidxu	ksi.ksi_uid = td->td_ucred->cr_ruid;
452213642Sdavidxu	if (uap->id == -1) {
453213642Sdavidxu		if ((p = pfind(uap->pid)) == NULL)
454213642Sdavidxu			return (ESRCH);
455213642Sdavidxu		AUDIT_ARG_PROCESS(p);
456213642Sdavidxu		error = p_cansignal(td, p, uap->sig);
457213642Sdavidxu		if (error) {
458213642Sdavidxu			PROC_UNLOCK(p);
459213642Sdavidxu			return (error);
460213642Sdavidxu		}
461213642Sdavidxu		if (uap->sig != 0 && !_SIG_VALID(uap->sig)) {
462213642Sdavidxu			error = EINVAL;
463213642Sdavidxu		} else {
464213642Sdavidxu			error = ESRCH;
465213642Sdavidxu			FOREACH_THREAD_IN_PROC(p, ttd) {
466213642Sdavidxu				if (ttd != td) {
467213642Sdavidxu					error = 0;
468213642Sdavidxu					if (uap->sig == 0)
469213642Sdavidxu						break;
470213642Sdavidxu					tdksignal(ttd, uap->sig, &ksi);
471171859Sdavidxu				}
472171859Sdavidxu			}
473171859Sdavidxu		}
474213642Sdavidxu		PROC_UNLOCK(p);
475213642Sdavidxu	} else {
476213642Sdavidxu		ttd = tdfind((lwpid_t)uap->id, uap->pid);
477213642Sdavidxu		if (ttd == NULL)
478213642Sdavidxu			return (ESRCH);
479213642Sdavidxu		p = ttd->td_proc;
480213642Sdavidxu		AUDIT_ARG_PROCESS(p);
481213642Sdavidxu		error = p_cansignal(td, p, uap->sig);
482213642Sdavidxu		if (uap->sig == 0)
483213642Sdavidxu			;
484213642Sdavidxu		else if (!_SIG_VALID(uap->sig))
485213642Sdavidxu			error = EINVAL;
486213642Sdavidxu		else
487213642Sdavidxu			tdksignal(ttd, uap->sig, &ksi);
488213642Sdavidxu		PROC_UNLOCK(p);
489171859Sdavidxu	}
490171859Sdavidxu	return (error);
491171859Sdavidxu}
492171859Sdavidxu
493171859Sdavidxuint
494225617Skmacysys_thr_suspend(struct thread *td, struct thr_suspend_args *uap)
495127482Smtm	/* const struct timespec *timeout */
496127482Smtm{
497162551Sdavidxu	struct timespec ts, *tsp;
498127482Smtm	int error;
499127482Smtm
500162551Sdavidxu	tsp = NULL;
501127482Smtm	if (uap->timeout != NULL) {
502228221Spho		error = umtx_copyin_timeout(uap->timeout, &ts);
503127482Smtm		if (error != 0)
504127482Smtm			return (error);
505162551Sdavidxu		tsp = &ts;
506162551Sdavidxu	}
507162551Sdavidxu
508162551Sdavidxu	return (kern_thr_suspend(td, tsp));
509162551Sdavidxu}
510162551Sdavidxu
511162551Sdavidxuint
512162551Sdavidxukern_thr_suspend(struct thread *td, struct timespec *tsp)
513162551Sdavidxu{
514214091Sdavidxu	struct proc *p = td->td_proc;
515162551Sdavidxu	struct timeval tv;
516211733Sdavidxu	int error = 0;
517211733Sdavidxu	int timo = 0;
518162551Sdavidxu
519164876Sdavidxu	if (td->td_pflags & TDP_WAKEUP) {
520164876Sdavidxu		td->td_pflags &= ~TDP_WAKEUP;
521164876Sdavidxu		return (0);
522164876Sdavidxu	}
523164876Sdavidxu
524214091Sdavidxu	if (tsp != NULL) {
525211733Sdavidxu		if (tsp->tv_sec == 0 && tsp->tv_nsec == 0)
526211733Sdavidxu			error = EWOULDBLOCK;
527211733Sdavidxu		else {
528211733Sdavidxu			TIMESPEC_TO_TIMEVAL(&tv, tsp);
529211733Sdavidxu			timo = tvtohz(&tv);
530211733Sdavidxu		}
531211733Sdavidxu	}
532211733Sdavidxu
533214091Sdavidxu	PROC_LOCK(p);
534214091Sdavidxu	if (error == 0 && (td->td_flags & TDF_THRWAKEUP) == 0)
535214091Sdavidxu		error = msleep((void *)td, &p->p_mtx,
536214091Sdavidxu			 PCATCH, "lthr", timo);
537214091Sdavidxu
538138272Sdavidxu	if (td->td_flags & TDF_THRWAKEUP) {
539170307Sjeff		thread_lock(td);
540138272Sdavidxu		td->td_flags &= ~TDF_THRWAKEUP;
541170307Sjeff		thread_unlock(td);
542214091Sdavidxu		PROC_UNLOCK(p);
543138272Sdavidxu		return (0);
544138272Sdavidxu	}
545214091Sdavidxu	PROC_UNLOCK(p);
546138272Sdavidxu	if (error == EWOULDBLOCK)
547138272Sdavidxu		error = ETIMEDOUT;
548138272Sdavidxu	else if (error == ERESTART) {
549211733Sdavidxu		if (timo != 0)
550138272Sdavidxu			error = EINTR;
551138272Sdavidxu	}
552138272Sdavidxu	return (error);
553127482Smtm}
554127482Smtm
555127482Smtmint
556225617Skmacysys_thr_wake(struct thread *td, struct thr_wake_args *uap)
557131431Smarcel	/* long id */
558127482Smtm{
559151990Sdavidxu	struct proc *p;
560131431Smarcel	struct thread *ttd;
561127482Smtm
562164876Sdavidxu	if (uap->id == td->td_tid) {
563164876Sdavidxu		td->td_pflags |= TDP_WAKEUP;
564164876Sdavidxu		return (0);
565164876Sdavidxu	}
566164876Sdavidxu
567151990Sdavidxu	p = td->td_proc;
568213642Sdavidxu	ttd = tdfind((lwpid_t)uap->id, p->p_pid);
569213642Sdavidxu	if (ttd == NULL)
570127482Smtm		return (ESRCH);
571170307Sjeff	thread_lock(ttd);
572131431Smarcel	ttd->td_flags |= TDF_THRWAKEUP;
573170307Sjeff	thread_unlock(ttd);
574138272Sdavidxu	wakeup((void *)ttd);
575151990Sdavidxu	PROC_UNLOCK(p);
576127482Smtm	return (0);
577127482Smtm}
578155327Sdavidxu
579155327Sdavidxuint
580225617Skmacysys_thr_set_name(struct thread *td, struct thr_set_name_args *uap)
581155327Sdavidxu{
582213642Sdavidxu	struct proc *p;
583155327Sdavidxu	char name[MAXCOMLEN + 1];
584155327Sdavidxu	struct thread *ttd;
585155327Sdavidxu	int error;
586155327Sdavidxu
587155327Sdavidxu	error = 0;
588155327Sdavidxu	name[0] = '\0';
589155327Sdavidxu	if (uap->name != NULL) {
590310044Svangyzen		error = copyinstr(uap->name, name, sizeof(name), NULL);
591310044Svangyzen		if (error == ENAMETOOLONG) {
592310044Svangyzen			error = copyin(uap->name, name, sizeof(name) - 1);
593310044Svangyzen			name[sizeof(name) - 1] = '\0';
594310044Svangyzen		}
595155327Sdavidxu		if (error)
596155327Sdavidxu			return (error);
597155327Sdavidxu	}
598213642Sdavidxu	p = td->td_proc;
599213642Sdavidxu	ttd = tdfind((lwpid_t)uap->id, p->p_pid);
600213642Sdavidxu	if (ttd == NULL)
601213642Sdavidxu		return (ESRCH);
602213642Sdavidxu	strcpy(ttd->td_name, name);
603232700Sjhb#ifdef KTR
604232700Sjhb	sched_clear_tdname(ttd);
605232700Sjhb#endif
606155327Sdavidxu	PROC_UNLOCK(p);
607155327Sdavidxu	return (error);
608155327Sdavidxu}
609283373Sdchagin
610283373Sdchaginint
611283373Sdchaginkern_thr_alloc(struct proc *p, int pages, struct thread **ntd)
612283373Sdchagin{
613283373Sdchagin
614283373Sdchagin	/* Have race condition but it is cheap. */
615283373Sdchagin	if (p->p_numthreads >= max_threads_per_proc) {
616283373Sdchagin		++max_threads_hits;
617283373Sdchagin		return (EPROCLIM);
618283373Sdchagin	}
619283373Sdchagin
620283373Sdchagin	*ntd = thread_alloc(pages);
621283373Sdchagin	if (*ntd == NULL)
622283373Sdchagin		return (ENOMEM);
623283373Sdchagin
624283373Sdchagin	return (0);
625283373Sdchagin}
626