kern_kthread.c revision 104306
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1999 Peter Wemm <peter@FreeBSD.org> 31549Srgrimes * All rights reserved. 41549Srgrimes * 59507Sdg * Redistribution and use in source and binary forms, with or without 69507Sdg * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 141541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2158705Scharnier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241541Srgrimes * SUCH DAMAGE. 251541Srgrimes * 261541Srgrimes * $FreeBSD: head/sys/kern/kern_kthread.c 104306 2002-10-01 17:15:53Z jmallett $ 271541Srgrimes */ 281541Srgrimes 291541Srgrimes#include <sys/param.h> 301541Srgrimes#include <sys/systm.h> 311541Srgrimes#include <sys/kthread.h> 321541Srgrimes#include <sys/lock.h> 331541Srgrimes#include <sys/mutex.h> 341541Srgrimes#include <sys/proc.h> 351541Srgrimes#include <sys/resourcevar.h> 361541Srgrimes#include <sys/signalvar.h> 371541Srgrimes#include <sys/sx.h> 381541Srgrimes#include <sys/unistd.h> 391541Srgrimes#include <sys/wait.h> 401549Srgrimes 411541Srgrimes#include <machine/stdarg.h> 421541Srgrimes 431541Srgrimes/* 441541Srgrimes * Start a kernel process. This is called after a fork() call in 451541Srgrimes * mi_startup() in the file kern/init_main.c. 461541Srgrimes * 471549Srgrimes * This function is used to start "internal" daemons and intended 481549Srgrimes * to be called from SYSINIT(). 499507Sdg */ 507695Sdgvoid 511549Srgrimeskproc_start(udata) 521549Srgrimes const void *udata; 53116226Sobrien{ 54116226Sobrien const struct kproc_desc *kp = udata; 55116226Sobrien int error; 561541Srgrimes 571541Srgrimes error = kthread_create((void (*)(void *))kp->func, NULL, 581541Srgrimes kp->global_procpp, 0, "%s", kp->arg0); 591541Srgrimes if (error) 601541Srgrimes panic("kproc_start: %s: error %d", kp->arg0, error); 6160041Sphk} 629507Sdg 6312662Sdg/* 6451340Sdillon * Create a kernel process/thread/whatever. It shares its address space 651541Srgrimes * with proc0 - ie: kernel only. 661541Srgrimes * 6712662Sdg * func is the function to start. 681541Srgrimes * arg is the parameter to pass to function on first startup. 699507Sdg * newpp is the return value pointing to the thread's struct proc. 7031853Sdyson * flags are flags to fork1 (in unistd.h) 711541Srgrimes * fmt and following will be *printf'd into (*newpp)->p_comm (for ps, etc.). 7212662Sdg */ 731541Srgrimesint 7492727Salfredkthread_create(void (*func)(void *), void *arg, 7592727Salfred struct proc **newpp, int flags, const char *fmt, ...) 7692727Salfred{ 7792727Salfred int error; 7892727Salfred va_list ap; 7992727Salfred struct thread *td; 8092727Salfred struct proc *p2; 8192727Salfred 8292727Salfred if (!proc0.p_stats /* || proc0.p_stats->p_start.tv_sec == 0 */) 8392727Salfred panic("kthread_create called too soon"); 8411943Sbde 851541Srgrimes error = fork1(&thread0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags, 86118466Sphk &p2); 87118466Sphk if (error) 88118466Sphk return error; 89118466Sphk 90118466Sphk /* save a global descriptor, if desired */ 91118466Sphk if (newpp != NULL) 921541Srgrimes *newpp = p2; 931541Srgrimes 9479127Sjhb /* this is a non-swapped system process */ 9510556Sdyson PROC_LOCK(p2); 96104094Sphk p2->p_flag |= P_SYSTEM | P_KTHREAD; 9779127Sjhb p2->p_procsig->ps_flag |= PS_NOCLDWAIT; 9879127Sjhb _PHOLD(p2); 9942957Sdillon PROC_UNLOCK(p2); 10079127Sjhb 10179127Sjhb /* set up arg0 for 'ps', et al */ 10279127Sjhb va_start(ap, fmt); 1031541Srgrimes vsnprintf(p2->p_comm, sizeof(p2->p_comm), fmt, ap); 1041541Srgrimes va_end(ap); 1051541Srgrimes 10698604Salc /* call the processes' main()... */ 10798604Salc td = FIRST_THREAD_IN_PROC(p2); 1081541Srgrimes cpu_set_fork_handler(td, func, arg); 1099507Sdg TD_SET_CAN_RUN(td); 11040286Sdg 11128751Sbde /* Delay putting it on the run queue until now. */ 1121541Srgrimes mtx_lock_spin(&sched_lock); 1139456Sdg p2->p_sflag |= PS_INMEM; 1141541Srgrimes if (!(flags & RFSTOPPED)) { 1151541Srgrimes setrunqueue(td); 1161541Srgrimes } 1171541Srgrimes mtx_unlock_spin(&sched_lock); 1181541Srgrimes 1191541Srgrimes return 0; 1201827Sdg} 1211541Srgrimes 1229411Sdgvoid 1239411Sdgkthread_exit(int ecode) 124103923Sjeff{ 125103923Sjeff struct thread *td; 12698604Salc struct proc *p; 1271541Srgrimes 1289411Sdg td = curthread; 1299411Sdg p = td->td_proc; 1301541Srgrimes sx_xlock(&proctree_lock); 131101308Sjeff PROC_LOCK(p); 132101308Sjeff proc_reparent(p, initproc); 133101308Sjeff PROC_UNLOCK(p); 134101308Sjeff sx_xunlock(&proctree_lock); 1359411Sdg exit1(td, W_EXITCODE(ecode, 0)); 136101308Sjeff} 137101308Sjeff 1389411Sdg/* 1399411Sdg * Advise a kernel process to suspend (or resume) in its main loop. 1409411Sdg * Participation is voluntary. 1419411Sdg */ 1429411Sdgint 143114074Salckthread_suspend(struct proc *p, int timo) 144114074Salc{ 145114074Salc /* 146114074Salc * Make sure this is indeed a system process and we can safely 147114074Salc * use the p_siglist field. 1489507Sdg */ 1495455Sdg PROC_LOCK(p); 15032071Sdyson if ((p->p_flag & P_KTHREAD) == 0) { 15132071Sdyson PROC_UNLOCK(p); 15232071Sdyson return (EINVAL); 1539507Sdg } 1541541Srgrimes SIGADDSET(p->p_siglist, SIGSTOP); 1551541Srgrimes wakeup(p); 1561541Srgrimes return msleep(&p->p_siglist, &p->p_mtx, PPAUSE | PDROP, "suspkt", timo); 15740286Sdg} 1581827Sdg 15940286Sdgint 1601549Srgrimeskthread_resume(struct proc *p) 1619507Sdg{ 1629507Sdg /* 1631541Srgrimes * Make sure this is indeed a system process and we can safely 16432286Sdyson * use the p_siglist field. 165114074Salc */ 1661541Srgrimes PROC_LOCK(p); 167101308Sjeff if ((p->p_flag & P_KTHREAD) == 0) { 16898604Salc PROC_UNLOCK(p); 169101308Sjeff return (EINVAL); 170101308Sjeff } 171101308Sjeff SIGDELSET(p->p_siglist, SIGSTOP); 1729411Sdg PROC_UNLOCK(p); 1739411Sdg wakeup(&p->p_siglist); 174101308Sjeff return (0); 17598604Salc} 1769507Sdg 1771541Srgrimesvoid 1781541Srgrimeskthread_suspend_check(struct proc *p) 179114774Salc{ 180114774Salc PROC_LOCK(p); 181114774Salc while (SIGISMEMBER(p->p_siglist, SIGSTOP)) { 18212820Sphk wakeup(&p->p_siglist); 1839507Sdg msleep(&p->p_siglist, &p->p_mtx, PPAUSE, "ktsusp", 0); 1849507Sdg } 1851541Srgrimes PROC_UNLOCK(p); 18679242Sdillon} 1871541Srgrimes