19c8b8baaSPeter Wemm /* 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 * $FreeBSD$ 279c8b8baaSPeter Wemm */ 289c8b8baaSPeter Wemm 299c8b8baaSPeter Wemm #include <sys/param.h> 309c8b8baaSPeter Wemm #include <sys/systm.h> 319c8b8baaSPeter Wemm #include <sys/kthread.h> 3298f03f90SJake Burkholder #include <sys/lock.h> 331005a129SJohn Baldwin #include <sys/mutex.h> 341005a129SJohn Baldwin #include <sys/proc.h> 3531008641SWarner Losh #include <sys/resourcevar.h> 365e950839SLuoqi Chen #include <sys/signalvar.h> 371005a129SJohn Baldwin #include <sys/sx.h> 389c8b8baaSPeter Wemm #include <sys/unistd.h> 399c8b8baaSPeter Wemm #include <sys/wait.h> 409c8b8baaSPeter Wemm 419c8b8baaSPeter Wemm #include <machine/stdarg.h> 429c8b8baaSPeter Wemm 439c8b8baaSPeter Wemm /* 449c8b8baaSPeter Wemm * Start a kernel process. This is called after a fork() call in 459c8b8baaSPeter Wemm * mi_startup() in the file kern/init_main.c. 469c8b8baaSPeter Wemm * 479c8b8baaSPeter Wemm * This function is used to start "internal" daemons and intended 489c8b8baaSPeter Wemm * to be called from SYSINIT(). 499c8b8baaSPeter Wemm */ 509c8b8baaSPeter Wemm void 519c8b8baaSPeter Wemm kproc_start(udata) 529c8b8baaSPeter Wemm const void *udata; 539c8b8baaSPeter Wemm { 549c8b8baaSPeter Wemm const struct kproc_desc *kp = udata; 559c8b8baaSPeter Wemm int error; 569c8b8baaSPeter Wemm 579c8b8baaSPeter Wemm error = kthread_create((void (*)(void *))kp->func, NULL, 582d075e99SKris Kennaway kp->global_procpp, 0, "%s", kp->arg0); 599c8b8baaSPeter Wemm if (error) 609c8b8baaSPeter Wemm panic("kproc_start: %s: error %d", kp->arg0, error); 619c8b8baaSPeter Wemm } 629c8b8baaSPeter Wemm 639c8b8baaSPeter Wemm /* 640384fff8SJason Evans * Create a kernel process/thread/whatever. It shares its address space 659c8b8baaSPeter Wemm * with proc0 - ie: kernel only. 660384fff8SJason Evans * 670384fff8SJason Evans * func is the function to start. 680384fff8SJason Evans * arg is the parameter to pass to function on first startup. 690384fff8SJason Evans * newpp is the return value pointing to the thread's struct proc. 700384fff8SJason Evans * flags are flags to fork1 (in unistd.h) 710384fff8SJason Evans * fmt and following will be *printf'd into (*newpp)->p_comm (for ps, etc.). 729c8b8baaSPeter Wemm */ 739c8b8baaSPeter Wemm int 749c8b8baaSPeter Wemm kthread_create(void (*func)(void *), void *arg, 750384fff8SJason Evans struct proc **newpp, int flags, const char *fmt, ...) 769c8b8baaSPeter Wemm { 779c8b8baaSPeter Wemm int error; 789c8b8baaSPeter Wemm va_list ap; 799c8b8baaSPeter Wemm struct proc *p2; 809c8b8baaSPeter Wemm 810384fff8SJason Evans if (!proc0.p_stats /* || proc0.p_stats->p_start.tv_sec == 0 */) 820384fff8SJason Evans panic("kthread_create called too soon"); 830384fff8SJason Evans 84b40ce416SJulian Elischer error = fork1(thread0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags, &p2); 859c8b8baaSPeter Wemm if (error) 869c8b8baaSPeter Wemm return error; 879c8b8baaSPeter Wemm 889c8b8baaSPeter Wemm /* save a global descriptor, if desired */ 899c8b8baaSPeter Wemm if (newpp != NULL) 909c8b8baaSPeter Wemm *newpp = p2; 919c8b8baaSPeter Wemm 929c8b8baaSPeter Wemm /* this is a non-swapped system process */ 93f1dea27dSJohn Baldwin PROC_LOCK(p2); 94f1dea27dSJohn Baldwin p2->p_flag |= P_SYSTEM | P_KTHREAD; 95645682fdSLuoqi Chen p2->p_procsig->ps_flag |= PS_NOCLDWAIT; 966451855fSJohn Baldwin _PHOLD(p2); 97f1dea27dSJohn Baldwin PROC_UNLOCK(p2); 989c8b8baaSPeter Wemm 999c8b8baaSPeter Wemm /* set up arg0 for 'ps', et al */ 1009c8b8baaSPeter Wemm va_start(ap, fmt); 1019c8b8baaSPeter Wemm vsnprintf(p2->p_comm, sizeof(p2->p_comm), fmt, ap); 1029c8b8baaSPeter Wemm va_end(ap); 1039c8b8baaSPeter Wemm 1049c8b8baaSPeter Wemm /* call the processes' main()... */ 105b40ce416SJulian Elischer cpu_set_fork_handler(&p2->p_thread, func, arg); /* XXXKSE */ 1069c8b8baaSPeter Wemm 107960d3c68SJohn Baldwin /* Delay putting it on the run queue until now. */ 1089ed346baSBosko Milekic mtx_lock_spin(&sched_lock); 109f1dea27dSJohn Baldwin p2->p_sflag |= PS_INMEM; 110f1dea27dSJohn Baldwin if (!(flags & RFSTOPPED)) { 111960d3c68SJohn Baldwin p2->p_stat = SRUN; 112b40ce416SJulian Elischer setrunqueue(&p2->p_thread); /* XXXKSE */ 113960d3c68SJohn Baldwin } 1149ed346baSBosko Milekic mtx_unlock_spin(&sched_lock); 115960d3c68SJohn Baldwin 1169c8b8baaSPeter Wemm return 0; 1179c8b8baaSPeter Wemm } 1189c8b8baaSPeter Wemm 1199c8b8baaSPeter Wemm void 1209c8b8baaSPeter Wemm kthread_exit(int ecode) 1219c8b8baaSPeter Wemm { 122658c434dSPeter Wemm struct thread *td; 123658c434dSPeter Wemm struct proc *p; 12498f03f90SJake Burkholder 125658c434dSPeter Wemm td = curthread; 126658c434dSPeter Wemm p = td->td_proc; 1271005a129SJohn Baldwin sx_xlock(&proctree_lock); 1285b1927bcSMatthew Dillon PROC_LOCK(p); 1295b1927bcSMatthew Dillon proc_reparent(p, initproc); 1305b1927bcSMatthew Dillon PROC_UNLOCK(p); 1311005a129SJohn Baldwin sx_xunlock(&proctree_lock); 132658c434dSPeter Wemm exit1(td, W_EXITCODE(ecode, 0)); 1339c8b8baaSPeter Wemm } 1349c8b8baaSPeter Wemm 1355e950839SLuoqi Chen /* 1365e950839SLuoqi Chen * Advise a kernel process to suspend (or resume) in its main loop. 1375e950839SLuoqi Chen * Participation is voluntary. 1385e950839SLuoqi Chen */ 1395e950839SLuoqi Chen int 140ffc831daSJohn Baldwin kthread_suspend(struct proc *p, int timo) 1415e950839SLuoqi Chen { 1425e950839SLuoqi Chen /* 1435e950839SLuoqi Chen * Make sure this is indeed a system process and we can safely 1445e950839SLuoqi Chen * use the p_siglist field. 1455e950839SLuoqi Chen */ 1466451855fSJohn Baldwin PROC_LOCK(p); 1476451855fSJohn Baldwin if ((p->p_flag & P_KTHREAD) == 0) { 1486451855fSJohn Baldwin PROC_UNLOCK(p); 1495e950839SLuoqi Chen return (EINVAL); 1506451855fSJohn Baldwin } 1515e950839SLuoqi Chen SIGADDSET(p->p_siglist, SIGSTOP); 1526451855fSJohn Baldwin return msleep(&p->p_siglist, &p->p_mtx, PPAUSE | PDROP, "suspkt", timo); 1535e950839SLuoqi Chen } 1545e950839SLuoqi Chen 1555e950839SLuoqi Chen int 156ffc831daSJohn Baldwin kthread_resume(struct proc *p) 1575e950839SLuoqi Chen { 1585e950839SLuoqi Chen /* 1595e950839SLuoqi Chen * Make sure this is indeed a system process and we can safely 1605e950839SLuoqi Chen * use the p_siglist field. 1615e950839SLuoqi Chen */ 1626451855fSJohn Baldwin PROC_LOCK(p); 1636451855fSJohn Baldwin if ((p->p_flag & P_KTHREAD) == 0) { 1646451855fSJohn Baldwin PROC_UNLOCK(p); 1655e950839SLuoqi Chen return (EINVAL); 1666451855fSJohn Baldwin } 1675e950839SLuoqi Chen SIGDELSET(p->p_siglist, SIGSTOP); 1686451855fSJohn Baldwin PROC_UNLOCK(p); 1696451855fSJohn Baldwin wakeup(&p->p_siglist); 1705e950839SLuoqi Chen return (0); 1715e950839SLuoqi Chen } 1725e950839SLuoqi Chen 1735e950839SLuoqi Chen void 174ffc831daSJohn Baldwin kthread_suspend_check(struct proc *p) 1755e950839SLuoqi Chen { 1766451855fSJohn Baldwin PROC_LOCK(p); 1775e950839SLuoqi Chen while (SIGISMEMBER(p->p_siglist, SIGSTOP)) { 1786451855fSJohn Baldwin wakeup(&p->p_siglist); 1796451855fSJohn Baldwin msleep(&p->p_siglist, &p->p_mtx, PPAUSE, "ktsusp", 0); 1805e950839SLuoqi Chen } 1816451855fSJohn Baldwin PROC_UNLOCK(p); 1825e950839SLuoqi Chen } 183