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(¶m, sizeof(param)); 138162551Sdavidxu if ((error = copyin(uap->param, ¶m, uap->param_size))) 139145434Sdavidxu return (error); 140162551Sdavidxu return (kern_thr_new(td, ¶m)); 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