1 /*- 2 * Copyright (c) 1999 Peter Wemm <peter@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kthread.h> 33 #include <sys/lock.h> 34 #include <sys/mutex.h> 35 #include <sys/proc.h> 36 #include <sys/resourcevar.h> 37 #include <sys/signalvar.h> 38 #include <sys/sx.h> 39 #include <sys/unistd.h> 40 #include <sys/wait.h> 41 #include <sys/sched.h> 42 43 #include <machine/stdarg.h> 44 45 /* 46 * Start a kernel process. This is called after a fork() call in 47 * mi_startup() in the file kern/init_main.c. 48 * 49 * This function is used to start "internal" daemons and intended 50 * to be called from SYSINIT(). 51 */ 52 void 53 kproc_start(udata) 54 const void *udata; 55 { 56 const struct kproc_desc *kp = udata; 57 int error; 58 59 error = kthread_create((void (*)(void *))kp->func, NULL, 60 kp->global_procpp, 0, 0, "%s", kp->arg0); 61 if (error) 62 panic("kproc_start: %s: error %d", kp->arg0, error); 63 } 64 65 /* 66 * Create a kernel process/thread/whatever. It shares its address space 67 * with proc0 - ie: kernel only. 68 * 69 * func is the function to start. 70 * arg is the parameter to pass to function on first startup. 71 * newpp is the return value pointing to the thread's struct proc. 72 * flags are flags to fork1 (in unistd.h) 73 * fmt and following will be *printf'd into (*newpp)->p_comm (for ps, etc.). 74 */ 75 int 76 kthread_create(void (*func)(void *), void *arg, 77 struct proc **newpp, int flags, int pages, const char *fmt, ...) 78 { 79 int error; 80 va_list ap; 81 struct thread *td; 82 struct proc *p2; 83 84 if (!proc0.p_stats) 85 panic("kthread_create called too soon"); 86 87 error = fork1(&thread0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags, 88 pages, &p2); 89 if (error) 90 return error; 91 92 /* save a global descriptor, if desired */ 93 if (newpp != NULL) 94 *newpp = p2; 95 96 /* this is a non-swapped system process */ 97 PROC_LOCK(p2); 98 p2->p_flag |= P_SYSTEM | P_KTHREAD; 99 mtx_lock(&p2->p_sigacts->ps_mtx); 100 p2->p_sigacts->ps_flag |= PS_NOCLDWAIT; 101 mtx_unlock(&p2->p_sigacts->ps_mtx); 102 PROC_UNLOCK(p2); 103 104 /* set up arg0 for 'ps', et al */ 105 va_start(ap, fmt); 106 vsnprintf(p2->p_comm, sizeof(p2->p_comm), fmt, ap); 107 va_end(ap); 108 109 /* call the processes' main()... */ 110 td = FIRST_THREAD_IN_PROC(p2); 111 cpu_set_fork_handler(td, func, arg); 112 TD_SET_CAN_RUN(td); 113 114 /* Delay putting it on the run queue until now. */ 115 if (!(flags & RFSTOPPED)) { 116 mtx_lock_spin(&sched_lock); 117 sched_add(td, SRQ_BORING); 118 mtx_unlock_spin(&sched_lock); 119 } 120 121 return 0; 122 } 123 124 void 125 kthread_exit(int ecode) 126 { 127 struct thread *td; 128 struct proc *p; 129 130 td = curthread; 131 p = td->td_proc; 132 133 /* 134 * Reparent curthread from proc0 to init so that the zombie 135 * is harvested. 136 */ 137 sx_xlock(&proctree_lock); 138 PROC_LOCK(p); 139 proc_reparent(p, initproc); 140 PROC_UNLOCK(p); 141 sx_xunlock(&proctree_lock); 142 143 /* 144 * Wakeup anyone waiting for us to exit. 145 */ 146 wakeup(p); 147 148 /* Buh-bye! */ 149 exit1(td, W_EXITCODE(ecode, 0)); 150 } 151 152 /* 153 * Advise a kernel process to suspend (or resume) in its main loop. 154 * Participation is voluntary. 155 */ 156 int 157 kthread_suspend(struct proc *p, int timo) 158 { 159 /* 160 * Make sure this is indeed a system process and we can safely 161 * use the p_siglist field. 162 */ 163 PROC_LOCK(p); 164 if ((p->p_flag & P_KTHREAD) == 0) { 165 PROC_UNLOCK(p); 166 return (EINVAL); 167 } 168 SIGADDSET(p->p_siglist, SIGSTOP); 169 wakeup(p); 170 return msleep(&p->p_siglist, &p->p_mtx, PPAUSE | PDROP, "suspkt", timo); 171 } 172 173 int 174 kthread_resume(struct proc *p) 175 { 176 /* 177 * Make sure this is indeed a system process and we can safely 178 * use the p_siglist field. 179 */ 180 PROC_LOCK(p); 181 if ((p->p_flag & P_KTHREAD) == 0) { 182 PROC_UNLOCK(p); 183 return (EINVAL); 184 } 185 SIGDELSET(p->p_siglist, SIGSTOP); 186 PROC_UNLOCK(p); 187 wakeup(&p->p_siglist); 188 return (0); 189 } 190 191 void 192 kthread_suspend_check(struct proc *p) 193 { 194 PROC_LOCK(p); 195 while (SIGISMEMBER(p->p_siglist, SIGSTOP)) { 196 wakeup(&p->p_siglist); 197 msleep(&p->p_siglist, &p->p_mtx, PPAUSE, "ktsusp", 0); 198 } 199 PROC_UNLOCK(p); 200 } 201