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/10/sys/kern/kern_thr.c 337258 2018-08-03 14:45:53Z 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 58112899Sjeff#include <machine/frame.h> 59112899Sjeff 60171859Sdavidxu#include <security/audit/audit.h> 61171859Sdavidxu 62227309Sedstatic SYSCTL_NODE(_kern, OID_AUTO, threads, CTLFLAG_RW, 0, 63227309Sed "thread allocation"); 64218972Skib 65218972Skibstatic int max_threads_per_proc = 1500; 66218972SkibSYSCTL_INT(_kern_threads, OID_AUTO, max_threads_per_proc, CTLFLAG_RW, 67228449Seadler &max_threads_per_proc, 0, "Limit on threads per proc"); 68218972Skib 69218972Skibstatic int max_threads_hits; 70218972SkibSYSCTL_INT(_kern_threads, OID_AUTO, max_threads_hits, CTLFLAG_RD, 71228449Seadler &max_threads_hits, 0, "kern.threads.max_threads_per_proc hit count"); 72218972Skib 73205014Snwhitehorn#ifdef COMPAT_FREEBSD32 74162551Sdavidxu 75162551Sdavidxustatic inline int 76162551Sdavidxusuword_lwpid(void *addr, lwpid_t lwpid) 77162551Sdavidxu{ 78162551Sdavidxu int error; 79162551Sdavidxu 80185169Skib if (SV_CURPROC_FLAG(SV_LP64)) 81162551Sdavidxu error = suword(addr, lwpid); 82162551Sdavidxu else 83162551Sdavidxu error = suword32(addr, lwpid); 84162551Sdavidxu return (error); 85162551Sdavidxu} 86162551Sdavidxu 87162551Sdavidxu#else 88162551Sdavidxu#define suword_lwpid suword 89162551Sdavidxu#endif 90162551Sdavidxu 91112899Sjeff/* 92112899Sjeff * System call interface. 93112899Sjeff */ 94286843Sed 95286843Sedstruct thr_create_initthr_args { 96286843Sed ucontext_t ctx; 97286843Sed long *tid; 98286843Sed}; 99286843Sed 100286843Sedstatic int 101286843Sedthr_create_initthr(struct thread *td, void *thunk) 102286843Sed{ 103286843Sed struct thr_create_initthr_args *args; 104286843Sed 105286843Sed /* Copy out the child tid. */ 106286843Sed args = thunk; 107286843Sed if (args->tid != NULL && suword_lwpid(args->tid, td->td_tid)) 108286843Sed return (EFAULT); 109286843Sed 110286843Sed return (set_mcontext(td, &args->ctx.uc_mcontext)); 111286843Sed} 112286843Sed 113112899Sjeffint 114225617Skmacysys_thr_create(struct thread *td, struct thr_create_args *uap) 115131431Smarcel /* ucontext_t *ctx, long *id, int flags */ 116112899Sjeff{ 117286843Sed struct thr_create_initthr_args args; 118112899Sjeff int error; 119145434Sdavidxu 120286843Sed if ((error = copyin(uap->ctx, &args.ctx, sizeof(args.ctx)))) 121145434Sdavidxu return (error); 122286843Sed args.tid = uap->id; 123286843Sed return (thread_create(td, NULL, thr_create_initthr, &args)); 124145434Sdavidxu} 125145434Sdavidxu 126145434Sdavidxuint 127225617Skmacysys_thr_new(struct thread *td, struct thr_new_args *uap) 128145434Sdavidxu /* struct thr_param * */ 129145434Sdavidxu{ 130145434Sdavidxu struct thr_param param; 131145434Sdavidxu int error; 132145434Sdavidxu 133162551Sdavidxu if (uap->param_size < 0 || uap->param_size > sizeof(param)) 134145434Sdavidxu return (EINVAL); 135162497Sdavidxu bzero(¶m, sizeof(param)); 136162551Sdavidxu if ((error = copyin(uap->param, ¶m, uap->param_size))) 137145434Sdavidxu return (error); 138162551Sdavidxu return (kern_thr_new(td, ¶m)); 139162551Sdavidxu} 140162551Sdavidxu 141286843Sedstatic int 142286843Sedthr_new_initthr(struct thread *td, void *thunk) 143286843Sed{ 144286843Sed stack_t stack; 145286843Sed struct thr_param *param; 146286843Sed 147286843Sed /* 148286843Sed * Here we copy out tid to two places, one for child and one 149286843Sed * for parent, because pthread can create a detached thread, 150286843Sed * if parent wants to safely access child tid, it has to provide 151286843Sed * its storage, because child thread may exit quickly and 152286843Sed * memory is freed before parent thread can access it. 153286843Sed */ 154286843Sed param = thunk; 155286843Sed if ((param->child_tid != NULL && 156286843Sed suword_lwpid(param->child_tid, td->td_tid)) || 157286843Sed (param->parent_tid != NULL && 158286843Sed suword_lwpid(param->parent_tid, td->td_tid))) 159286843Sed return (EFAULT); 160286843Sed 161286843Sed /* Set up our machine context. */ 162286843Sed stack.ss_sp = param->stack_base; 163286843Sed stack.ss_size = param->stack_size; 164286843Sed /* Set upcall address to user thread entry function. */ 165286843Sed cpu_set_upcall_kse(td, param->start_func, param->arg, &stack); 166286843Sed /* Setup user TLS address and TLS pointer register. */ 167286843Sed return (cpu_set_user_tls(td, param->tls_base)); 168286843Sed} 169286843Sed 170162551Sdavidxuint 171162551Sdavidxukern_thr_new(struct thread *td, struct thr_param *param) 172162551Sdavidxu{ 173162551Sdavidxu struct rtprio rtp, *rtpp; 174162551Sdavidxu int error; 175162551Sdavidxu 176162497Sdavidxu rtpp = NULL; 177162551Sdavidxu if (param->rtp != 0) { 178162551Sdavidxu error = copyin(param->rtp, &rtp, sizeof(struct rtprio)); 179183846Srdivacky if (error) 180183846Srdivacky return (error); 181162497Sdavidxu rtpp = &rtp; 182160254Sdavidxu } 183286843Sed return (thread_create(td, rtpp, thr_new_initthr, param)); 184145434Sdavidxu} 185145434Sdavidxu 186286843Sedint 187286843Sedthread_create(struct thread *td, struct rtprio *rtp, 188286843Sed int (*initialize_thread)(struct thread *, void *), void *thunk) 189145434Sdavidxu{ 190145434Sdavidxu struct thread *newtd; 191134791Sjulian struct proc *p; 192160252Sdavidxu int error; 193112899Sjeff 194134791Sjulian p = td->td_proc; 195112899Sjeff 196162497Sdavidxu if (rtp != NULL) { 197162497Sdavidxu switch(rtp->type) { 198162497Sdavidxu case RTP_PRIO_REALTIME: 199162497Sdavidxu case RTP_PRIO_FIFO: 200160259Sdavidxu /* Only root can set scheduler policy */ 201164033Srwatson if (priv_check(td, PRIV_SCHED_SETPOLICY) != 0) 202160254Sdavidxu return (EPERM); 203162497Sdavidxu if (rtp->prio > RTP_PRIO_MAX) 204160254Sdavidxu return (EINVAL); 205160259Sdavidxu break; 206162497Sdavidxu case RTP_PRIO_NORMAL: 207162497Sdavidxu rtp->prio = 0; 208160259Sdavidxu break; 209160259Sdavidxu default: 210160259Sdavidxu return (EINVAL); 211160254Sdavidxu } 212160254Sdavidxu } 213160254Sdavidxu 214223825Strasz#ifdef RACCT 215220222Strasz PROC_LOCK(td->td_proc); 216220222Strasz error = racct_add(p, RACCT_NTHR, 1); 217220222Strasz PROC_UNLOCK(td->td_proc); 218220222Strasz if (error != 0) 219220222Strasz return (EPROCLIM); 220223825Strasz#endif 221220222Strasz 222164936Sjulian /* Initialize our td */ 223293481Sdchagin error = kern_thr_alloc(p, 0, &newtd); 224293481Sdchagin if (error) 225220222Strasz goto fail; 226145434Sdavidxu 227228360Spho cpu_set_upcall(newtd, td); 228228360Spho 229134791Sjulian bzero(&newtd->td_startzero, 230137946Sdas __rangeof(struct thread, td_startzero, td_endzero)); 231284199Skib newtd->td_su = NULL; 232304905Skib newtd->td_sleeptimo = 0; 233134791Sjulian bcopy(&td->td_startcopy, &newtd->td_startcopy, 234137946Sdas __rangeof(struct thread, td_startcopy, td_endcopy)); 235134791Sjulian newtd->td_proc = td->td_proc; 236134791Sjulian newtd->td_ucred = crhold(td->td_ucred); 237289780Sjhb newtd->td_dbg_sc_code = td->td_dbg_sc_code; 238289780Sjhb newtd->td_dbg_sc_narg = td->td_dbg_sc_narg; 239112899Sjeff 240286843Sed error = initialize_thread(newtd, thunk); 241286843Sed if (error != 0) { 242286843Sed thread_free(newtd); 243286843Sed crfree(td->td_ucred); 244286843Sed goto fail; 245131431Smarcel } 246112899Sjeff 247160252Sdavidxu PROC_LOCK(td->td_proc); 248145434Sdavidxu td->td_proc->p_flag |= P_HADTHREADS; 249163709Sjb thread_link(newtd, p); 250173625Sjulian bcopy(p->p_comm, newtd->td_name, sizeof(newtd->td_name)); 251170307Sjeff thread_lock(td); 252134791Sjulian /* let the scheduler know about these things. */ 253134791Sjulian sched_fork_thread(td, newtd); 254170307Sjeff thread_unlock(td); 255177471Sjeff if (P_SHOULDSTOP(p)) 256177471Sjeff newtd->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK; 257304188Sjhb if (p->p_ptevents & PTRACE_LWP) 258304017Sjhb newtd->td_dbgflags |= TDB_BORN; 259170307Sjeff PROC_UNLOCK(p); 260213642Sdavidxu 261213642Sdavidxu tidhash_add(newtd); 262213642Sdavidxu 263170307Sjeff thread_lock(newtd); 264162497Sdavidxu if (rtp != NULL) { 265163709Sjb if (!(td->td_pri_class == PRI_TIMESHARE && 266163709Sjb rtp->type == RTP_PRIO_NORMAL)) { 267163709Sjb rtp_to_pri(rtp, newtd); 268163709Sjb sched_prio(newtd, newtd->td_user_pri); 269163709Sjb } /* ignore timesharing class */ 270163709Sjb } 271134791Sjulian TD_SET_CAN_RUN(newtd); 272177514Sdavidxu sched_add(newtd, SRQ_BORING); 273170307Sjeff thread_unlock(newtd); 274112899Sjeff 275189074Sed return (0); 276220222Strasz 277220222Straszfail: 278223825Strasz#ifdef RACCT 279284665Strasz if (racct_enable) { 280284665Strasz PROC_LOCK(p); 281284665Strasz racct_sub(p, RACCT_NTHR, 1); 282284665Strasz PROC_UNLOCK(p); 283284665Strasz } 284223825Strasz#endif 285220222Strasz return (error); 286112899Sjeff} 287112899Sjeff 288112899Sjeffint 289225617Skmacysys_thr_self(struct thread *td, struct thr_self_args *uap) 290131431Smarcel /* long *id */ 291112899Sjeff{ 292112899Sjeff int error; 293112899Sjeff 294162551Sdavidxu error = suword_lwpid(uap->id, (unsigned)td->td_tid); 295162551Sdavidxu if (error == -1) 296162551Sdavidxu return (EFAULT); 297112899Sjeff return (0); 298112899Sjeff} 299112899Sjeff 300112899Sjeffint 301225617Skmacysys_thr_exit(struct thread *td, struct thr_exit_args *uap) 302136192Smtm /* long *state */ 303112899Sjeff{ 304112899Sjeff 305136192Smtm /* Signal userland that it can free the stack. */ 306151692Sdavidxu if ((void *)uap->state != NULL) { 307162551Sdavidxu suword_lwpid(uap->state, 1); 308178648Sdavidxu kern_umtx_wake(td, uap->state, INT_MAX, 0); 309151692Sdavidxu } 310136192Smtm 311293480Sdchagin return (kern_thr_exit(td)); 312293480Sdchagin} 313293480Sdchagin 314293480Sdchaginint 315293480Sdchaginkern_thr_exit(struct thread *td) 316293480Sdchagin{ 317293480Sdchagin struct proc *p; 318293480Sdchagin 319293480Sdchagin p = td->td_proc; 320293480Sdchagin 321304017Sjhb /* 322304017Sjhb * If all of the threads in a process call this routine to 323304017Sjhb * exit (e.g. all threads call pthread_exit()), exactly one 324304017Sjhb * thread should return to the caller to terminate the process 325304017Sjhb * instead of the thread. 326304017Sjhb * 327304017Sjhb * Checking p_numthreads alone is not sufficient since threads 328304017Sjhb * might be committed to terminating while the PROC_LOCK is 329304017Sjhb * dropped in either ptracestop() or while removing this thread 330304017Sjhb * from the tidhash. Instead, the p_pendingexits field holds 331304017Sjhb * the count of threads in either of those states and a thread 332304017Sjhb * is considered the "last" thread if all of the other threads 333304017Sjhb * in a process are already terminating. 334304017Sjhb */ 335112899Sjeff PROC_LOCK(p); 336304017Sjhb if (p->p_numthreads == p->p_pendingexits + 1) { 337304017Sjhb /* 338304017Sjhb * Ignore attempts to shut down last thread in the 339304017Sjhb * proc. This will actually call _exit(2) in the 340304017Sjhb * usermode trampoline when it returns. 341304017Sjhb */ 342304017Sjhb PROC_UNLOCK(p); 343304017Sjhb return (0); 344134791Sjulian } 345274339Skib 346304017Sjhb p->p_pendingexits++; 347304017Sjhb td->td_dbgflags |= TDB_EXIT; 348304188Sjhb if (p->p_ptevents & PTRACE_LWP) 349315949Sbadger ptracestop(td, SIGTRAP, NULL); 350304017Sjhb PROC_UNLOCK(p); 351304017Sjhb tidhash_remove(td); 352304017Sjhb PROC_LOCK(p); 353304017Sjhb p->p_pendingexits--; 354304017Sjhb 355274339Skib /* 356304017Sjhb * The check above should prevent all other threads from this 357304017Sjhb * process from exiting while the PROC_LOCK is dropped, so 358304017Sjhb * there must be at least one other thread other than the 359304017Sjhb * current thread. 360274339Skib */ 361304017Sjhb KASSERT(p->p_numthreads > 1, ("too few threads")); 362304017Sjhb racct_sub(p, RACCT_NTHR, 1); 363304017Sjhb tdsigcleanup(td); 364304017Sjhb umtx_thread_exit(td); 365337258Sasomers 366337258Sasomers#ifdef AUDIT 367337258Sasomers AUDIT_SYSCALL_EXIT(0, td); 368337258Sasomers#endif 369337258Sasomers 370304017Sjhb PROC_SLOCK(p); 371304017Sjhb thread_stopped(p); 372304017Sjhb thread_exit(); 373304017Sjhb /* NOTREACHED */ 374112899Sjeff} 375112899Sjeff 376112899Sjeffint 377225617Skmacysys_thr_kill(struct thread *td, struct thr_kill_args *uap) 378131431Smarcel /* long id, int sig */ 379112899Sjeff{ 380204519Sbruno ksiginfo_t ksi; 381112899Sjeff struct thread *ttd; 382112899Sjeff struct proc *p; 383112899Sjeff int error; 384112899Sjeff 385112899Sjeff p = td->td_proc; 386204519Sbruno ksiginfo_init(&ksi); 387204519Sbruno ksi.ksi_signo = uap->sig; 388211732Sdavidxu ksi.ksi_code = SI_LWP; 389204519Sbruno ksi.ksi_pid = p->p_pid; 390204519Sbruno ksi.ksi_uid = td->td_ucred->cr_ruid; 391154093Sdavidxu if (uap->id == -1) { 392154093Sdavidxu if (uap->sig != 0 && !_SIG_VALID(uap->sig)) { 393154093Sdavidxu error = EINVAL; 394154093Sdavidxu } else { 395154093Sdavidxu error = ESRCH; 396213642Sdavidxu PROC_LOCK(p); 397154093Sdavidxu FOREACH_THREAD_IN_PROC(p, ttd) { 398154093Sdavidxu if (ttd != td) { 399154093Sdavidxu error = 0; 400154093Sdavidxu if (uap->sig == 0) 401154093Sdavidxu break; 402209592Sjhb tdksignal(ttd, uap->sig, &ksi); 403154093Sdavidxu } 404154093Sdavidxu } 405213642Sdavidxu PROC_UNLOCK(p); 406154093Sdavidxu } 407154093Sdavidxu } else { 408213642Sdavidxu error = 0; 409213642Sdavidxu ttd = tdfind((lwpid_t)uap->id, p->p_pid); 410154093Sdavidxu if (ttd == NULL) 411213642Sdavidxu return (ESRCH); 412213642Sdavidxu if (uap->sig == 0) 413154093Sdavidxu ; 414154093Sdavidxu else if (!_SIG_VALID(uap->sig)) 415154093Sdavidxu error = EINVAL; 416213642Sdavidxu else 417209592Sjhb tdksignal(ttd, uap->sig, &ksi); 418213642Sdavidxu PROC_UNLOCK(ttd->td_proc); 419112899Sjeff } 420112899Sjeff return (error); 421112899Sjeff} 422127482Smtm 423127482Smtmint 424225617Skmacysys_thr_kill2(struct thread *td, struct thr_kill2_args *uap) 425171859Sdavidxu /* pid_t pid, long id, int sig */ 426171859Sdavidxu{ 427204519Sbruno ksiginfo_t ksi; 428171859Sdavidxu struct thread *ttd; 429171859Sdavidxu struct proc *p; 430171859Sdavidxu int error; 431171859Sdavidxu 432195104Srwatson AUDIT_ARG_SIGNUM(uap->sig); 433171859Sdavidxu 434213642Sdavidxu ksiginfo_init(&ksi); 435213642Sdavidxu ksi.ksi_signo = uap->sig; 436213642Sdavidxu ksi.ksi_code = SI_LWP; 437213642Sdavidxu ksi.ksi_pid = td->td_proc->p_pid; 438213642Sdavidxu ksi.ksi_uid = td->td_ucred->cr_ruid; 439213642Sdavidxu if (uap->id == -1) { 440213642Sdavidxu if ((p = pfind(uap->pid)) == NULL) 441213642Sdavidxu return (ESRCH); 442213642Sdavidxu AUDIT_ARG_PROCESS(p); 443213642Sdavidxu error = p_cansignal(td, p, uap->sig); 444213642Sdavidxu if (error) { 445213642Sdavidxu PROC_UNLOCK(p); 446213642Sdavidxu return (error); 447213642Sdavidxu } 448213642Sdavidxu if (uap->sig != 0 && !_SIG_VALID(uap->sig)) { 449213642Sdavidxu error = EINVAL; 450213642Sdavidxu } else { 451213642Sdavidxu error = ESRCH; 452213642Sdavidxu FOREACH_THREAD_IN_PROC(p, ttd) { 453213642Sdavidxu if (ttd != td) { 454213642Sdavidxu error = 0; 455213642Sdavidxu if (uap->sig == 0) 456213642Sdavidxu break; 457213642Sdavidxu tdksignal(ttd, uap->sig, &ksi); 458171859Sdavidxu } 459171859Sdavidxu } 460171859Sdavidxu } 461213642Sdavidxu PROC_UNLOCK(p); 462213642Sdavidxu } else { 463213642Sdavidxu ttd = tdfind((lwpid_t)uap->id, uap->pid); 464213642Sdavidxu if (ttd == NULL) 465213642Sdavidxu return (ESRCH); 466213642Sdavidxu p = ttd->td_proc; 467213642Sdavidxu AUDIT_ARG_PROCESS(p); 468213642Sdavidxu error = p_cansignal(td, p, uap->sig); 469213642Sdavidxu if (uap->sig == 0) 470213642Sdavidxu ; 471213642Sdavidxu else if (!_SIG_VALID(uap->sig)) 472213642Sdavidxu error = EINVAL; 473213642Sdavidxu else 474213642Sdavidxu tdksignal(ttd, uap->sig, &ksi); 475213642Sdavidxu PROC_UNLOCK(p); 476171859Sdavidxu } 477171859Sdavidxu return (error); 478171859Sdavidxu} 479171859Sdavidxu 480171859Sdavidxuint 481225617Skmacysys_thr_suspend(struct thread *td, struct thr_suspend_args *uap) 482127482Smtm /* const struct timespec *timeout */ 483127482Smtm{ 484162551Sdavidxu struct timespec ts, *tsp; 485127482Smtm int error; 486127482Smtm 487162551Sdavidxu tsp = NULL; 488127482Smtm if (uap->timeout != NULL) { 489228221Spho error = umtx_copyin_timeout(uap->timeout, &ts); 490127482Smtm if (error != 0) 491127482Smtm return (error); 492162551Sdavidxu tsp = &ts; 493162551Sdavidxu } 494162551Sdavidxu 495162551Sdavidxu return (kern_thr_suspend(td, tsp)); 496162551Sdavidxu} 497162551Sdavidxu 498162551Sdavidxuint 499162551Sdavidxukern_thr_suspend(struct thread *td, struct timespec *tsp) 500162551Sdavidxu{ 501214091Sdavidxu struct proc *p = td->td_proc; 502162551Sdavidxu struct timeval tv; 503211733Sdavidxu int error = 0; 504211733Sdavidxu int timo = 0; 505162551Sdavidxu 506164876Sdavidxu if (td->td_pflags & TDP_WAKEUP) { 507164876Sdavidxu td->td_pflags &= ~TDP_WAKEUP; 508164876Sdavidxu return (0); 509164876Sdavidxu } 510164876Sdavidxu 511214091Sdavidxu if (tsp != NULL) { 512211733Sdavidxu if (tsp->tv_sec == 0 && tsp->tv_nsec == 0) 513211733Sdavidxu error = EWOULDBLOCK; 514211733Sdavidxu else { 515211733Sdavidxu TIMESPEC_TO_TIMEVAL(&tv, tsp); 516211733Sdavidxu timo = tvtohz(&tv); 517211733Sdavidxu } 518211733Sdavidxu } 519211733Sdavidxu 520214091Sdavidxu PROC_LOCK(p); 521214091Sdavidxu if (error == 0 && (td->td_flags & TDF_THRWAKEUP) == 0) 522214091Sdavidxu error = msleep((void *)td, &p->p_mtx, 523214091Sdavidxu PCATCH, "lthr", timo); 524214091Sdavidxu 525138272Sdavidxu if (td->td_flags & TDF_THRWAKEUP) { 526170307Sjeff thread_lock(td); 527138272Sdavidxu td->td_flags &= ~TDF_THRWAKEUP; 528170307Sjeff thread_unlock(td); 529214091Sdavidxu PROC_UNLOCK(p); 530138272Sdavidxu return (0); 531138272Sdavidxu } 532214091Sdavidxu PROC_UNLOCK(p); 533138272Sdavidxu if (error == EWOULDBLOCK) 534138272Sdavidxu error = ETIMEDOUT; 535138272Sdavidxu else if (error == ERESTART) { 536211733Sdavidxu if (timo != 0) 537138272Sdavidxu error = EINTR; 538138272Sdavidxu } 539138272Sdavidxu return (error); 540127482Smtm} 541127482Smtm 542127482Smtmint 543225617Skmacysys_thr_wake(struct thread *td, struct thr_wake_args *uap) 544131431Smarcel /* long id */ 545127482Smtm{ 546151990Sdavidxu struct proc *p; 547131431Smarcel struct thread *ttd; 548127482Smtm 549164876Sdavidxu if (uap->id == td->td_tid) { 550164876Sdavidxu td->td_pflags |= TDP_WAKEUP; 551164876Sdavidxu return (0); 552164876Sdavidxu } 553164876Sdavidxu 554151990Sdavidxu p = td->td_proc; 555213642Sdavidxu ttd = tdfind((lwpid_t)uap->id, p->p_pid); 556213642Sdavidxu if (ttd == NULL) 557127482Smtm return (ESRCH); 558170307Sjeff thread_lock(ttd); 559131431Smarcel ttd->td_flags |= TDF_THRWAKEUP; 560170307Sjeff thread_unlock(ttd); 561138272Sdavidxu wakeup((void *)ttd); 562151990Sdavidxu PROC_UNLOCK(p); 563127482Smtm return (0); 564127482Smtm} 565155327Sdavidxu 566155327Sdavidxuint 567225617Skmacysys_thr_set_name(struct thread *td, struct thr_set_name_args *uap) 568155327Sdavidxu{ 569213642Sdavidxu struct proc *p; 570155327Sdavidxu char name[MAXCOMLEN + 1]; 571155327Sdavidxu struct thread *ttd; 572155327Sdavidxu int error; 573155327Sdavidxu 574155327Sdavidxu error = 0; 575155327Sdavidxu name[0] = '\0'; 576155327Sdavidxu if (uap->name != NULL) { 577310099Svangyzen error = copyinstr(uap->name, name, sizeof(name), NULL); 578310099Svangyzen if (error == ENAMETOOLONG) { 579310099Svangyzen error = copyin(uap->name, name, sizeof(name) - 1); 580310099Svangyzen name[sizeof(name) - 1] = '\0'; 581310099Svangyzen } 582155327Sdavidxu if (error) 583155327Sdavidxu return (error); 584155327Sdavidxu } 585213642Sdavidxu p = td->td_proc; 586213642Sdavidxu ttd = tdfind((lwpid_t)uap->id, p->p_pid); 587213642Sdavidxu if (ttd == NULL) 588213642Sdavidxu return (ESRCH); 589213642Sdavidxu strcpy(ttd->td_name, name); 590232700Sjhb#ifdef KTR 591232700Sjhb sched_clear_tdname(ttd); 592232700Sjhb#endif 593155327Sdavidxu PROC_UNLOCK(p); 594155327Sdavidxu return (error); 595155327Sdavidxu} 596293481Sdchagin 597293481Sdchaginint 598293481Sdchaginkern_thr_alloc(struct proc *p, int pages, struct thread **ntd) 599293481Sdchagin{ 600293481Sdchagin 601293481Sdchagin /* Have race condition but it is cheap. */ 602293481Sdchagin if (p->p_numthreads >= max_threads_per_proc) { 603293481Sdchagin ++max_threads_hits; 604293481Sdchagin return (EPROCLIM); 605293481Sdchagin } 606293481Sdchagin 607293481Sdchagin *ntd = thread_alloc(pages); 608293481Sdchagin if (*ntd == NULL) 609293481Sdchagin return (ENOMEM); 610293481Sdchagin 611293481Sdchagin return (0); 612293481Sdchagin} 613