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/proc.h> 329c8b8baaSPeter Wemm #include <sys/kthread.h> 3398f03f90SJake Burkholder #include <sys/lock.h> 3431008641SWarner Losh #include <sys/resourcevar.h> 355e950839SLuoqi Chen #include <sys/signalvar.h> 369c8b8baaSPeter Wemm #include <sys/unistd.h> 379c8b8baaSPeter Wemm #include <sys/wait.h> 389c8b8baaSPeter Wemm 399c8b8baaSPeter Wemm #include <machine/stdarg.h> 409c8b8baaSPeter Wemm 419c8b8baaSPeter Wemm /* 429c8b8baaSPeter Wemm * Start a kernel process. This is called after a fork() call in 439c8b8baaSPeter Wemm * mi_startup() in the file kern/init_main.c. 449c8b8baaSPeter Wemm * 459c8b8baaSPeter Wemm * This function is used to start "internal" daemons and intended 469c8b8baaSPeter Wemm * to be called from SYSINIT(). 479c8b8baaSPeter Wemm */ 489c8b8baaSPeter Wemm void 499c8b8baaSPeter Wemm kproc_start(udata) 509c8b8baaSPeter Wemm const void *udata; 519c8b8baaSPeter Wemm { 529c8b8baaSPeter Wemm const struct kproc_desc *kp = udata; 539c8b8baaSPeter Wemm int error; 549c8b8baaSPeter Wemm 559c8b8baaSPeter Wemm error = kthread_create((void (*)(void *))kp->func, NULL, 560384fff8SJason Evans kp->global_procpp, 0, kp->arg0); 579c8b8baaSPeter Wemm if (error) 589c8b8baaSPeter Wemm panic("kproc_start: %s: error %d", kp->arg0, error); 599c8b8baaSPeter Wemm } 609c8b8baaSPeter Wemm 619c8b8baaSPeter Wemm /* 620384fff8SJason Evans * Create a kernel process/thread/whatever. It shares its address space 639c8b8baaSPeter Wemm * with proc0 - ie: kernel only. 640384fff8SJason Evans * 650384fff8SJason Evans * func is the function to start. 660384fff8SJason Evans * arg is the parameter to pass to function on first startup. 670384fff8SJason Evans * newpp is the return value pointing to the thread's struct proc. 680384fff8SJason Evans * flags are flags to fork1 (in unistd.h) 690384fff8SJason Evans * fmt and following will be *printf'd into (*newpp)->p_comm (for ps, etc.). 709c8b8baaSPeter Wemm */ 719c8b8baaSPeter Wemm int 729c8b8baaSPeter Wemm kthread_create(void (*func)(void *), void *arg, 730384fff8SJason Evans struct proc **newpp, int flags, const char *fmt, ...) 749c8b8baaSPeter Wemm { 759c8b8baaSPeter Wemm int error; 769c8b8baaSPeter Wemm va_list ap; 779c8b8baaSPeter Wemm struct proc *p2; 789c8b8baaSPeter Wemm 790384fff8SJason Evans if (!proc0.p_stats /* || proc0.p_stats->p_start.tv_sec == 0 */) 800384fff8SJason Evans panic("kthread_create called too soon"); 810384fff8SJason Evans 82960d3c68SJohn Baldwin error = fork1(&proc0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags, &p2); 839c8b8baaSPeter Wemm if (error) 849c8b8baaSPeter Wemm return error; 859c8b8baaSPeter Wemm 869c8b8baaSPeter Wemm /* save a global descriptor, if desired */ 879c8b8baaSPeter Wemm if (newpp != NULL) 889c8b8baaSPeter Wemm *newpp = p2; 899c8b8baaSPeter Wemm 909c8b8baaSPeter Wemm /* this is a non-swapped system process */ 91645682fdSLuoqi Chen p2->p_flag |= P_INMEM | P_SYSTEM; 92645682fdSLuoqi Chen p2->p_procsig->ps_flag |= PS_NOCLDWAIT; 939c8b8baaSPeter Wemm PHOLD(p2); 949c8b8baaSPeter Wemm 959c8b8baaSPeter Wemm /* set up arg0 for 'ps', et al */ 969c8b8baaSPeter Wemm va_start(ap, fmt); 979c8b8baaSPeter Wemm vsnprintf(p2->p_comm, sizeof(p2->p_comm), fmt, ap); 989c8b8baaSPeter Wemm va_end(ap); 999c8b8baaSPeter Wemm 1009c8b8baaSPeter Wemm /* call the processes' main()... */ 1019c8b8baaSPeter Wemm cpu_set_fork_handler(p2, func, arg); 1029c8b8baaSPeter Wemm 103960d3c68SJohn Baldwin /* Delay putting it on the run queue until now. */ 104960d3c68SJohn Baldwin if (!(flags & RFSTOPPED)) { 105960d3c68SJohn Baldwin mtx_enter(&sched_lock, MTX_SPIN); 106960d3c68SJohn Baldwin p2->p_stat = SRUN; 107960d3c68SJohn Baldwin setrunqueue(p2); 108960d3c68SJohn Baldwin mtx_exit(&sched_lock, MTX_SPIN); 109960d3c68SJohn Baldwin } 110960d3c68SJohn Baldwin 1119c8b8baaSPeter Wemm return 0; 1129c8b8baaSPeter Wemm } 1139c8b8baaSPeter Wemm 1149c8b8baaSPeter Wemm void 1159c8b8baaSPeter Wemm kthread_exit(int ecode) 1169c8b8baaSPeter Wemm { 11798f03f90SJake Burkholder 11898f03f90SJake Burkholder PROCTREE_LOCK(PT_EXCLUSIVE); 119d8f83167SJohn Baldwin proc_reparent(curproc, initproc); 12098f03f90SJake Burkholder PROCTREE_LOCK(PT_RELEASE); 1219c8b8baaSPeter Wemm exit1(curproc, W_EXITCODE(ecode, 0)); 1229c8b8baaSPeter Wemm } 1239c8b8baaSPeter Wemm 1245e950839SLuoqi Chen /* 1255e950839SLuoqi Chen * Advise a kernel process to suspend (or resume) in its main loop. 1265e950839SLuoqi Chen * Participation is voluntary. 1275e950839SLuoqi Chen */ 1285e950839SLuoqi Chen int 129ffc831daSJohn Baldwin kthread_suspend(struct proc *p, int timo) 1305e950839SLuoqi Chen { 1315e950839SLuoqi Chen /* 1325e950839SLuoqi Chen * Make sure this is indeed a system process and we can safely 1335e950839SLuoqi Chen * use the p_siglist field. 1345e950839SLuoqi Chen */ 1355e950839SLuoqi Chen if ((p->p_flag & P_SYSTEM) == 0) 1365e950839SLuoqi Chen return (EINVAL); 1375e950839SLuoqi Chen SIGADDSET(p->p_siglist, SIGSTOP); 138ffc831daSJohn Baldwin return tsleep((caddr_t)&p->p_siglist, PPAUSE, "suspkt", timo); 1395e950839SLuoqi Chen } 1405e950839SLuoqi Chen 1415e950839SLuoqi Chen int 142ffc831daSJohn Baldwin kthread_resume(struct proc *p) 1435e950839SLuoqi Chen { 1445e950839SLuoqi Chen /* 1455e950839SLuoqi Chen * Make sure this is indeed a system process and we can safely 1465e950839SLuoqi Chen * use the p_siglist field. 1475e950839SLuoqi Chen */ 1485e950839SLuoqi Chen if ((p->p_flag & P_SYSTEM) == 0) 1495e950839SLuoqi Chen return (EINVAL); 1505e950839SLuoqi Chen SIGDELSET(p->p_siglist, SIGSTOP); 1515e950839SLuoqi Chen wakeup((caddr_t)&p->p_siglist); 1525e950839SLuoqi Chen return (0); 1535e950839SLuoqi Chen } 1545e950839SLuoqi Chen 1555e950839SLuoqi Chen void 156ffc831daSJohn Baldwin kthread_suspend_check(struct proc *p) 1575e950839SLuoqi Chen { 1585e950839SLuoqi Chen while (SIGISMEMBER(p->p_siglist, SIGSTOP)) { 1595e950839SLuoqi Chen wakeup((caddr_t)&p->p_siglist); 160ffc831daSJohn Baldwin tsleep((caddr_t)&p->p_siglist, PPAUSE, "ktsusp", 0); 1615e950839SLuoqi Chen } 1625e950839SLuoqi Chen } 163