19454b2d8SWarner Losh /*- 29c8b8baaSPeter Wemm * Copyright (c) 1999 Peter Wemm <peter@FreeBSD.org> 39c8b8baaSPeter Wemm * All rights reserved. 49c8b8baaSPeter Wemm * 59c8b8baaSPeter Wemm * Redistribution and use in source and binary forms, with or without 69c8b8baaSPeter Wemm * modification, are permitted provided that the following conditions 79c8b8baaSPeter Wemm * are met: 89c8b8baaSPeter Wemm * 1. Redistributions of source code must retain the above copyright 99c8b8baaSPeter Wemm * notice, this list of conditions and the following disclaimer. 109c8b8baaSPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 119c8b8baaSPeter Wemm * notice, this list of conditions and the following disclaimer in the 129c8b8baaSPeter Wemm * documentation and/or other materials provided with the distribution. 139c8b8baaSPeter Wemm * 149c8b8baaSPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 159c8b8baaSPeter Wemm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 169c8b8baaSPeter Wemm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 179c8b8baaSPeter Wemm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 189c8b8baaSPeter Wemm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 199c8b8baaSPeter Wemm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 209c8b8baaSPeter Wemm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 219c8b8baaSPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 229c8b8baaSPeter Wemm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 239c8b8baaSPeter Wemm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 249c8b8baaSPeter Wemm * SUCH DAMAGE. 259c8b8baaSPeter Wemm */ 269c8b8baaSPeter Wemm 27677b542eSDavid E. O'Brien #include <sys/cdefs.h> 28677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 29677b542eSDavid E. O'Brien 309c8b8baaSPeter Wemm #include <sys/param.h> 319c8b8baaSPeter Wemm #include <sys/systm.h> 329c8b8baaSPeter Wemm #include <sys/kthread.h> 3398f03f90SJake Burkholder #include <sys/lock.h> 341005a129SJohn Baldwin #include <sys/mutex.h> 351005a129SJohn Baldwin #include <sys/proc.h> 3631008641SWarner Losh #include <sys/resourcevar.h> 375e950839SLuoqi Chen #include <sys/signalvar.h> 381005a129SJohn Baldwin #include <sys/sx.h> 399c8b8baaSPeter Wemm #include <sys/unistd.h> 409c8b8baaSPeter Wemm #include <sys/wait.h> 41f0393f06SJeff Roberson #include <sys/sched.h> 429c8b8baaSPeter Wemm 439c8b8baaSPeter Wemm #include <machine/stdarg.h> 449c8b8baaSPeter Wemm 459c8b8baaSPeter Wemm /* 469c8b8baaSPeter Wemm * Start a kernel process. This is called after a fork() call in 479c8b8baaSPeter Wemm * mi_startup() in the file kern/init_main.c. 489c8b8baaSPeter Wemm * 499c8b8baaSPeter Wemm * This function is used to start "internal" daemons and intended 509c8b8baaSPeter Wemm * to be called from SYSINIT(). 519c8b8baaSPeter Wemm */ 529c8b8baaSPeter Wemm void 539c8b8baaSPeter Wemm kproc_start(udata) 549c8b8baaSPeter Wemm const void *udata; 559c8b8baaSPeter Wemm { 569c8b8baaSPeter Wemm const struct kproc_desc *kp = udata; 579c8b8baaSPeter Wemm int error; 589c8b8baaSPeter Wemm 599c8b8baaSPeter Wemm error = kthread_create((void (*)(void *))kp->func, NULL, 60316ec49aSScott Long kp->global_procpp, 0, 0, "%s", kp->arg0); 619c8b8baaSPeter Wemm if (error) 629c8b8baaSPeter Wemm panic("kproc_start: %s: error %d", kp->arg0, error); 639c8b8baaSPeter Wemm } 649c8b8baaSPeter Wemm 659c8b8baaSPeter Wemm /* 660384fff8SJason Evans * Create a kernel process/thread/whatever. It shares its address space 679c8b8baaSPeter Wemm * with proc0 - ie: kernel only. 680384fff8SJason Evans * 690384fff8SJason Evans * func is the function to start. 700384fff8SJason Evans * arg is the parameter to pass to function on first startup. 710384fff8SJason Evans * newpp is the return value pointing to the thread's struct proc. 720384fff8SJason Evans * flags are flags to fork1 (in unistd.h) 730384fff8SJason Evans * fmt and following will be *printf'd into (*newpp)->p_comm (for ps, etc.). 749c8b8baaSPeter Wemm */ 759c8b8baaSPeter Wemm int 769c8b8baaSPeter Wemm kthread_create(void (*func)(void *), void *arg, 77316ec49aSScott Long struct proc **newpp, int flags, int pages, const char *fmt, ...) 789c8b8baaSPeter Wemm { 799c8b8baaSPeter Wemm int error; 809c8b8baaSPeter Wemm va_list ap; 8171fad9fdSJulian Elischer struct thread *td; 829c8b8baaSPeter Wemm struct proc *p2; 839c8b8baaSPeter Wemm 8487ccef7bSDag-Erling Smørgrav if (!proc0.p_stats) 850384fff8SJason Evans panic("kthread_create called too soon"); 860384fff8SJason Evans 872b8a08afSPeter Wemm error = fork1(&thread0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags, 88316ec49aSScott Long pages, &p2); 899c8b8baaSPeter Wemm if (error) 909c8b8baaSPeter Wemm return error; 919c8b8baaSPeter Wemm 929c8b8baaSPeter Wemm /* save a global descriptor, if desired */ 939c8b8baaSPeter Wemm if (newpp != NULL) 949c8b8baaSPeter Wemm *newpp = p2; 959c8b8baaSPeter Wemm 969c8b8baaSPeter Wemm /* this is a non-swapped system process */ 97f1dea27dSJohn Baldwin PROC_LOCK(p2); 98f1dea27dSJohn Baldwin p2->p_flag |= P_SYSTEM | P_KTHREAD; 9990af4afaSJohn Baldwin mtx_lock(&p2->p_sigacts->ps_mtx); 10090af4afaSJohn Baldwin p2->p_sigacts->ps_flag |= PS_NOCLDWAIT; 10190af4afaSJohn Baldwin mtx_unlock(&p2->p_sigacts->ps_mtx); 102f1dea27dSJohn Baldwin PROC_UNLOCK(p2); 1039c8b8baaSPeter Wemm 1049c8b8baaSPeter Wemm /* set up arg0 for 'ps', et al */ 1059c8b8baaSPeter Wemm va_start(ap, fmt); 1069c8b8baaSPeter Wemm vsnprintf(p2->p_comm, sizeof(p2->p_comm), fmt, ap); 1079c8b8baaSPeter Wemm va_end(ap); 1089c8b8baaSPeter Wemm 1099c8b8baaSPeter Wemm /* call the processes' main()... */ 11071fad9fdSJulian Elischer td = FIRST_THREAD_IN_PROC(p2); 11171fad9fdSJulian Elischer cpu_set_fork_handler(td, func, arg); 11271fad9fdSJulian Elischer TD_SET_CAN_RUN(td); 1139c8b8baaSPeter Wemm 114960d3c68SJohn Baldwin /* Delay putting it on the run queue until now. */ 115f1dea27dSJohn Baldwin if (!(flags & RFSTOPPED)) { 1160bfc4d14SJohn Baldwin mtx_lock_spin(&sched_lock); 117f0393f06SJeff Roberson sched_add(td, SRQ_BORING); 1189ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 1190bfc4d14SJohn Baldwin } 120960d3c68SJohn Baldwin 1219c8b8baaSPeter Wemm return 0; 1229c8b8baaSPeter Wemm } 1239c8b8baaSPeter Wemm 1249c8b8baaSPeter Wemm void 1259c8b8baaSPeter Wemm kthread_exit(int ecode) 1269c8b8baaSPeter Wemm { 127658c434dSPeter Wemm struct thread *td; 128658c434dSPeter Wemm struct proc *p; 12998f03f90SJake Burkholder 130658c434dSPeter Wemm td = curthread; 131658c434dSPeter Wemm p = td->td_proc; 132934ba9b2SJohn Baldwin 133934ba9b2SJohn Baldwin /* 134934ba9b2SJohn Baldwin * Reparent curthread from proc0 to init so that the zombie 135934ba9b2SJohn Baldwin * is harvested. 136934ba9b2SJohn Baldwin */ 1371005a129SJohn Baldwin sx_xlock(&proctree_lock); 1385b1927bcSMatthew Dillon PROC_LOCK(p); 1395b1927bcSMatthew Dillon proc_reparent(p, initproc); 1405b1927bcSMatthew Dillon PROC_UNLOCK(p); 1411005a129SJohn Baldwin sx_xunlock(&proctree_lock); 142934ba9b2SJohn Baldwin 143934ba9b2SJohn Baldwin /* 144934ba9b2SJohn Baldwin * Wakeup anyone waiting for us to exit. 145934ba9b2SJohn Baldwin */ 146934ba9b2SJohn Baldwin wakeup(p); 147934ba9b2SJohn Baldwin 148934ba9b2SJohn Baldwin /* Buh-bye! */ 149658c434dSPeter Wemm exit1(td, W_EXITCODE(ecode, 0)); 1509c8b8baaSPeter Wemm } 1519c8b8baaSPeter Wemm 1525e950839SLuoqi Chen /* 1535e950839SLuoqi Chen * Advise a kernel process to suspend (or resume) in its main loop. 1545e950839SLuoqi Chen * Participation is voluntary. 1555e950839SLuoqi Chen */ 1565e950839SLuoqi Chen int 157ffc831daSJohn Baldwin kthread_suspend(struct proc *p, int timo) 1585e950839SLuoqi Chen { 1595e950839SLuoqi Chen /* 1605e950839SLuoqi Chen * Make sure this is indeed a system process and we can safely 1611d9c5696SJuli Mallett * use the p_siglist field. 1625e950839SLuoqi Chen */ 1636451855fSJohn Baldwin PROC_LOCK(p); 1646451855fSJohn Baldwin if ((p->p_flag & P_KTHREAD) == 0) { 1656451855fSJohn Baldwin PROC_UNLOCK(p); 1665e950839SLuoqi Chen return (EINVAL); 1676451855fSJohn Baldwin } 1681d9c5696SJuli Mallett SIGADDSET(p->p_siglist, SIGSTOP); 1698f0d41d3SPeter Wemm wakeup(p); 1701d9c5696SJuli Mallett return msleep(&p->p_siglist, &p->p_mtx, PPAUSE | PDROP, "suspkt", timo); 1715e950839SLuoqi Chen } 1725e950839SLuoqi Chen 1735e950839SLuoqi Chen int 174ffc831daSJohn Baldwin kthread_resume(struct proc *p) 1755e950839SLuoqi Chen { 1765e950839SLuoqi Chen /* 1775e950839SLuoqi Chen * Make sure this is indeed a system process and we can safely 1785e950839SLuoqi Chen * use the p_siglist field. 1795e950839SLuoqi Chen */ 1806451855fSJohn Baldwin PROC_LOCK(p); 1816451855fSJohn Baldwin if ((p->p_flag & P_KTHREAD) == 0) { 1826451855fSJohn Baldwin PROC_UNLOCK(p); 1835e950839SLuoqi Chen return (EINVAL); 1846451855fSJohn Baldwin } 1851d9c5696SJuli Mallett SIGDELSET(p->p_siglist, SIGSTOP); 1866451855fSJohn Baldwin PROC_UNLOCK(p); 1871d9c5696SJuli Mallett wakeup(&p->p_siglist); 1885e950839SLuoqi Chen return (0); 1895e950839SLuoqi Chen } 1905e950839SLuoqi Chen 1915e950839SLuoqi Chen void 192ffc831daSJohn Baldwin kthread_suspend_check(struct proc *p) 1935e950839SLuoqi Chen { 1946451855fSJohn Baldwin PROC_LOCK(p); 1951d9c5696SJuli Mallett while (SIGISMEMBER(p->p_siglist, SIGSTOP)) { 1961d9c5696SJuli Mallett wakeup(&p->p_siglist); 1971d9c5696SJuli Mallett msleep(&p->p_siglist, &p->p_mtx, PPAUSE, "ktsusp", 0); 1985e950839SLuoqi Chen } 1996451855fSJohn Baldwin PROC_UNLOCK(p); 2005e950839SLuoqi Chen } 201