kern_kthread.c (172836) | kern_kthread.c (173004) |
---|---|
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 --- 11 unchanged lines hidden (view full) --- 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> | 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 --- 11 unchanged lines hidden (view full) --- 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: head/sys/kern/kern_kthread.c 172836 2007-10-20 23:23:23Z julian $"); | 28__FBSDID("$FreeBSD: head/sys/kern/kern_kthread.c 173004 2007-10-26 08:00:41Z julian $"); |
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> | 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#include <vm/vm.h> 43#include <vm/vm_extern.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 --- 40 unchanged lines hidden (view full) --- 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); | 44 45#include <machine/stdarg.h> 46 47/* 48 * Start a kernel process. This is called after a fork() call in 49 * mi_startup() in the file kern/init_main.c. 50 * 51 * This function is used to start "internal" daemons and intended --- 40 unchanged lines hidden (view full) --- 92 return error; 93 94 /* save a global descriptor, if desired */ 95 if (newpp != NULL) 96 *newpp = p2; 97 98 /* this is a non-swapped system process */ 99 PROC_LOCK(p2); |
100 td = FIRST_THREAD_IN_PROC(p2); |
|
98 p2->p_flag |= P_SYSTEM | P_KTHREAD; | 101 p2->p_flag |= P_SYSTEM | P_KTHREAD; |
102 td->td_pflags |= TDP_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); | 103 mtx_lock(&p2->p_sigacts->ps_mtx); 104 p2->p_sigacts->ps_flag |= PS_NOCLDWAIT; 105 mtx_unlock(&p2->p_sigacts->ps_mtx); 106 PROC_UNLOCK(p2); 107 108 /* set up arg0 for 'ps', et al */ 109 va_start(ap, fmt); 110 vsnprintf(p2->p_comm, sizeof(p2->p_comm), fmt, ap); 111 va_end(ap); |
112 /* set up arg0 for 'ps', et al */ 113 va_start(ap, fmt); 114 vsnprintf(td->td_name, sizeof(td->td_name), fmt, ap); 115 va_end(ap); |
|
108 109 /* call the processes' main()... */ | 116 117 /* 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 thread_lock(td); 117 sched_add(td, SRQ_BORING); 118 thread_unlock(td); --- 43 unchanged lines hidden (view full) --- 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); | 118 cpu_set_fork_handler(td, func, arg); 119 TD_SET_CAN_RUN(td); 120 121 /* Delay putting it on the run queue until now. */ 122 if (!(flags & RFSTOPPED)) { 123 thread_lock(td); 124 sched_add(td, SRQ_BORING); 125 thread_unlock(td); --- 43 unchanged lines hidden (view full) --- 169 */ 170 PROC_LOCK(p); 171 if ((p->p_flag & P_KTHREAD) == 0) { 172 PROC_UNLOCK(p); 173 return (EINVAL); 174 } 175 SIGADDSET(p->p_siglist, SIGSTOP); 176 wakeup(p); |
170 return msleep(&p->p_siglist, &p->p_mtx, PPAUSE | PDROP, "suspkt", timo); | 177 return msleep(&p->p_siglist, &p->p_mtx, PPAUSE | PDROP, "suspkp", timo); |
171} 172 173int 174kproc_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. --- 10 unchanged lines hidden (view full) --- 189} 190 191void 192kproc_suspend_check(struct proc *p) 193{ 194 PROC_LOCK(p); 195 while (SIGISMEMBER(p->p_siglist, SIGSTOP)) { 196 wakeup(&p->p_siglist); | 178} 179 180int 181kproc_resume(struct proc *p) 182{ 183 /* 184 * Make sure this is indeed a system process and we can safely 185 * use the p_siglist field. --- 10 unchanged lines hidden (view full) --- 196} 197 198void 199kproc_suspend_check(struct proc *p) 200{ 201 PROC_LOCK(p); 202 while (SIGISMEMBER(p->p_siglist, SIGSTOP)) { 203 wakeup(&p->p_siglist); |
197 msleep(&p->p_siglist, &p->p_mtx, PPAUSE, "ktsusp", 0); | 204 msleep(&p->p_siglist, &p->p_mtx, PPAUSE, "kpsusp", 0); |
198 } 199 PROC_UNLOCK(p); 200} | 205 } 206 PROC_UNLOCK(p); 207} |
208 209 210/* 211 * Start a kernel thread. 212 * 213 * This function is used to start "internal" daemons and intended 214 * to be called from SYSINIT(). 215 */ 216 217void 218kthread_start(udata) 219 const void *udata; 220{ 221 const struct kthread_desc *kp = udata; 222 int error; 223 224 error = kthread_add((void (*)(void *))kp->func, NULL, 225 NULL, kp->global_threadpp, 0, 0, "%s", kp->arg0); 226 if (error) 227 panic("kthread_start: %s: error %d", kp->arg0, error); 228} 229 230/* 231 * Create a kernel thread. It shares its address space 232 * with proc0 - ie: kernel only. 233 * 234 * func is the function to start. 235 * arg is the parameter to pass to function on first startup. 236 * newtdp is the return value pointing to the thread's struct thread. 237 * ** XXX fix this --> flags are flags to fork1 (in unistd.h) 238 * ** XXX are any used? 239 * fmt and following will be *printf'd into (*newtd)->td_name (for ps, etc.). 240 */ 241int 242kthread_add(void (*func)(void *), void *arg, struct proc *p, 243 struct thread **newtdp, int flags, int pages, const char *fmt, ...) 244{ 245 va_list ap; 246 struct thread *newtd, *oldtd; 247 int error; 248 249 if (!proc0.p_stats) 250 panic("kthread_add called too soon"); 251 252 error = 0; 253 if (p == NULL) { 254 p = &proc0; 255 oldtd = &thread0; 256 } else { 257 oldtd = FIRST_THREAD_IN_PROC(p); 258 } 259 260 /* Initialize our td */ 261 newtd = thread_alloc(); 262 if (newtd == NULL) 263 return (ENOMEM); 264 265 bzero(&newtd->td_startzero, 266 __rangeof(struct thread, td_startzero, td_endzero)); 267/* XXX check if we should zero. */ 268 bcopy(&oldtd->td_startcopy, &newtd->td_startcopy, 269 __rangeof(struct thread, td_startcopy, td_endcopy)); 270 271 /* set up arg0 for 'ps', et al */ 272 va_start(ap, fmt); 273 vsnprintf(newtd->td_name, sizeof(newtd->td_name), fmt, ap); 274 va_end(ap); 275 276 newtd->td_proc = p; /* needed for cpu_set_upcall */ 277 278 /* XXX optimise this probably? */ 279 /* On x86 (and probably the others too) it is way too full of junk */ 280 /* Needs a better name */ 281 cpu_set_upcall(newtd, oldtd); 282 /* put the designated function(arg) as the resume context */ 283 cpu_set_fork_handler(newtd, func, arg); 284 285 newtd->td_pflags |= TDP_KTHREAD; 286 newtd->td_ucred = crhold(p->p_ucred); 287 /* Allocate and switch to an alternate kstack if specified. */ 288 if (pages != 0) 289 vm_thread_new_altkstack(newtd, pages); 290 291 /* this code almost the same as create_thread() in kern_thr.c */ 292 PROC_LOCK(p); 293 p->p_flag |= P_HADTHREADS; 294 newtd->td_sigmask = oldtd->td_sigmask; /* XXX dubious */ 295 PROC_SLOCK(p); 296 thread_link(newtd, p); 297 thread_lock(oldtd); 298 /* let the scheduler know about these things. */ 299 sched_fork_thread(oldtd, newtd); 300 TD_SET_CAN_RUN(newtd); 301 thread_unlock(oldtd); 302 PROC_SUNLOCK(p); 303 PROC_UNLOCK(p); 304 305 306 /* Delay putting it on the run queue until now. */ 307 if (!(flags & RFSTOPPED)) { 308 thread_lock(newtd); 309 sched_add(newtd, SRQ_BORING); 310 thread_unlock(newtd); 311 } 312 if (newtdp) 313 *newtdp = newtd; 314 return 0; 315} 316 317void 318kthread_exit(int ecode) 319{ 320 thread_exit(); 321} 322 323/* 324 * Advise a kernel process to suspend (or resume) in its main loop. 325 * Participation is voluntary. 326 */ 327int 328kthread_suspend(struct thread *td, int timo) 329{ 330 if ((td->td_pflags & TDP_KTHREAD) == 0) { 331 return (EINVAL); 332 } 333 thread_lock(td); 334 td->td_flags |= TDF_KTH_SUSP; 335 thread_unlock(td); 336 /* 337 * If it's stopped for some other reason, 338 * kick it to notice our request 339 * or we'll end up timing out 340 */ 341 wakeup(td); /* traditional place for kernel threads to sleep on */ /* XXX ?? */ 342 return (tsleep(&td->td_flags, PPAUSE | PDROP, "suspkt", timo)); 343} 344 345/* 346 * let the kthread it can keep going again. 347 */ 348int 349kthread_resume(struct thread *td) 350{ 351 if ((td->td_pflags & TDP_KTHREAD) == 0) { 352 return (EINVAL); 353 } 354 thread_lock(td); 355 td->td_flags &= ~TDF_KTH_SUSP; 356 thread_unlock(td); 357 wakeup(&td->td_name); 358 return (0); 359} 360 361/* 362 * Used by the thread to poll as to whether it should yield/sleep 363 * and notify the caller that is has happened. 364 */ 365void 366kthread_suspend_check(struct thread *td) 367{ 368 while (td->td_flags & TDF_KTH_SUSP) { 369 /* 370 * let the caller know we got the message then sleep 371 */ 372 wakeup(&td->td_flags); 373 tsleep(&td->td_name, PPAUSE, "ktsusp", 0); 374 } 375} 376 377int 378kproc_kthread_add(void (*func)(void *), void *arg, 379 struct proc **procptr, struct thread **tdptr, 380 int flags, int pages, char * procname, const char *fmt, ...) 381{ 382 int error; 383 va_list ap; 384 char buf[100]; 385 struct thread *td; 386 387 if (*procptr == 0) { 388 error = kproc_create(func, arg, 389 procptr, flags, pages, "%s", procname); 390 if (error) 391 return (error); 392 td = FIRST_THREAD_IN_PROC(*procptr); 393 *tdptr = td; 394 va_start(ap, fmt); 395 vsnprintf(td->td_name, sizeof(td->td_name), fmt, ap); 396 va_end(ap); 397 return (0); 398 } 399 va_start(ap, fmt); 400 vsnprintf(buf, sizeof(buf), fmt, ap); 401 va_end(ap); 402 error = kthread_add(func, arg, *procptr, 403 tdptr, flags, pages, "%s", buf); 404 return (error); 405} |
|