The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_kthread.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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/cpuset.h>
   33 #include <sys/kthread.h>
   34 #include <sys/lock.h>
   35 #include <sys/mutex.h>
   36 #include <sys/proc.h>
   37 #include <sys/resourcevar.h>
   38 #include <sys/signalvar.h>
   39 #include <sys/sx.h>
   40 #include <sys/unistd.h>
   41 #include <sys/wait.h>
   42 #include <sys/sched.h>
   43 #include <vm/vm.h>
   44 #include <vm/vm_extern.h>
   45 
   46 #include <machine/stdarg.h>
   47 
   48 /*
   49  * Start a kernel process.  This is called after a fork() call in
   50  * mi_startup() in the file kern/init_main.c.
   51  *
   52  * This function is used to start "internal" daemons and intended
   53  * to be called from SYSINIT().
   54  */
   55 void
   56 kproc_start(udata)
   57         const void *udata;
   58 {
   59         const struct kproc_desc *kp = udata;
   60         int error;
   61 
   62         error = kproc_create((void (*)(void *))kp->func, NULL,
   63                     kp->global_procpp, 0, 0, "%s", kp->arg0);
   64         if (error)
   65                 panic("kproc_start: %s: error %d", kp->arg0, error);
   66 }
   67 
   68 /*
   69  * Create a kernel process/thread/whatever.  It shares its address space
   70  * with proc0 - ie: kernel only.
   71  *
   72  * func is the function to start.
   73  * arg is the parameter to pass to function on first startup.
   74  * newpp is the return value pointing to the thread's struct proc.
   75  * flags are flags to fork1 (in unistd.h)
   76  * fmt and following will be *printf'd into (*newpp)->p_comm (for ps, etc.).
   77  */
   78 int
   79 kproc_create(void (*func)(void *), void *arg,
   80     struct proc **newpp, int flags, int pages, const char *fmt, ...)
   81 {
   82         int error;
   83         va_list ap;
   84         struct thread *td;
   85         struct proc *p2;
   86 
   87         if (!proc0.p_stats)
   88                 panic("kproc_create called too soon");
   89 
   90         error = fork1(&thread0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags,
   91             pages, &p2);
   92         if (error)
   93                 return error;
   94 
   95         /* save a global descriptor, if desired */
   96         if (newpp != NULL)
   97                 *newpp = p2;
   98 
   99         /* this is a non-swapped system process */
  100         PROC_LOCK(p2);
  101         td = FIRST_THREAD_IN_PROC(p2);
  102         p2->p_flag |= P_SYSTEM | P_KTHREAD;
  103         td->td_pflags |= TDP_KTHREAD;
  104         mtx_lock(&p2->p_sigacts->ps_mtx);
  105         p2->p_sigacts->ps_flag |= PS_NOCLDWAIT;
  106         mtx_unlock(&p2->p_sigacts->ps_mtx);
  107         PROC_UNLOCK(p2);
  108 
  109         /* set up arg0 for 'ps', et al */
  110         va_start(ap, fmt);
  111         vsnprintf(p2->p_comm, sizeof(p2->p_comm), fmt, ap);
  112         va_end(ap);
  113         /* set up arg0 for 'ps', et al */
  114         va_start(ap, fmt);
  115         vsnprintf(td->td_name, sizeof(td->td_name), fmt, ap);
  116         va_end(ap);
  117 #ifdef KTR
  118         sched_clear_tdname(td);
  119 #endif
  120 
  121         /* call the processes' main()... */
  122         cpu_set_fork_handler(td, func, arg);
  123 
  124         /* Avoid inheriting affinity from a random parent. */
  125         cpuset_setthread(td->td_tid, cpuset_root);
  126         thread_lock(td);
  127         TD_SET_CAN_RUN(td);
  128         sched_prio(td, PVM);
  129         sched_user_prio(td, PUSER);
  130 
  131         /* Delay putting it on the run queue until now. */
  132         if (!(flags & RFSTOPPED))
  133                 sched_add(td, SRQ_BORING); 
  134         thread_unlock(td);
  135 
  136         return 0;
  137 }
  138 
  139 void
  140 kproc_exit(int ecode)
  141 {
  142         struct thread *td;
  143         struct proc *p;
  144 
  145         td = curthread;
  146         p = td->td_proc;
  147 
  148         /*
  149          * Reparent curthread from proc0 to init so that the zombie
  150          * is harvested.
  151          */
  152         sx_xlock(&proctree_lock);
  153         PROC_LOCK(p);
  154         proc_reparent(p, initproc);
  155         PROC_UNLOCK(p);
  156         sx_xunlock(&proctree_lock);
  157 
  158         /*
  159          * Wakeup anyone waiting for us to exit.
  160          */
  161         wakeup(p);
  162 
  163         /* Buh-bye! */
  164         exit1(td, W_EXITCODE(ecode, 0));
  165 }
  166 
  167 /*
  168  * Advise a kernel process to suspend (or resume) in its main loop.
  169  * Participation is voluntary.
  170  */
  171 int
  172 kproc_suspend(struct proc *p, int timo)
  173 {
  174         /*
  175          * Make sure this is indeed a system process and we can safely
  176          * use the p_siglist field.
  177          */
  178         PROC_LOCK(p);
  179         if ((p->p_flag & P_KTHREAD) == 0) {
  180                 PROC_UNLOCK(p);
  181                 return (EINVAL);
  182         }
  183         SIGADDSET(p->p_siglist, SIGSTOP);
  184         wakeup(p);
  185         return msleep(&p->p_siglist, &p->p_mtx, PPAUSE | PDROP, "suspkp", timo);
  186 }
  187 
  188 int
  189 kproc_resume(struct proc *p)
  190 {
  191         /*
  192          * Make sure this is indeed a system process and we can safely
  193          * use the p_siglist field.
  194          */
  195         PROC_LOCK(p);
  196         if ((p->p_flag & P_KTHREAD) == 0) {
  197                 PROC_UNLOCK(p);
  198                 return (EINVAL);
  199         }
  200         SIGDELSET(p->p_siglist, SIGSTOP);
  201         PROC_UNLOCK(p);
  202         wakeup(&p->p_siglist);
  203         return (0);
  204 }
  205 
  206 void
  207 kproc_suspend_check(struct proc *p)
  208 {
  209         PROC_LOCK(p);
  210         while (SIGISMEMBER(p->p_siglist, SIGSTOP)) {
  211                 wakeup(&p->p_siglist);
  212                 msleep(&p->p_siglist, &p->p_mtx, PPAUSE, "kpsusp", 0);
  213         }
  214         PROC_UNLOCK(p);
  215 }
  216 
  217 
  218 /*
  219  * Start a kernel thread.  
  220  *
  221  * This function is used to start "internal" daemons and intended
  222  * to be called from SYSINIT().
  223  */
  224 
  225 void
  226 kthread_start(udata)
  227         const void *udata;
  228 {
  229         const struct kthread_desc       *kp = udata;
  230         int error;
  231 
  232         error = kthread_add((void (*)(void *))kp->func, NULL,
  233                     NULL, kp->global_threadpp, 0, 0, "%s", kp->arg0);
  234         if (error)
  235                 panic("kthread_start: %s: error %d", kp->arg0, error);
  236 }
  237 
  238 /*
  239  * Create a kernel thread.  It shares its address space
  240  * with proc0 - ie: kernel only.
  241  *
  242  * func is the function to start.
  243  * arg is the parameter to pass to function on first startup.
  244  * newtdp is the return value pointing to the thread's struct thread.
  245  *  ** XXX fix this --> flags are flags to fork1 (in unistd.h) 
  246  * fmt and following will be *printf'd into (*newtd)->td_name (for ps, etc.).
  247  */
  248 int
  249 kthread_add(void (*func)(void *), void *arg, struct proc *p,
  250     struct thread **newtdp, int flags, int pages, const char *fmt, ...)
  251 {
  252         va_list ap;
  253         struct thread *newtd, *oldtd;
  254 
  255         if (!proc0.p_stats)
  256                 panic("kthread_add called too soon");
  257 
  258         /* If no process supplied, put it on proc0 */
  259         if (p == NULL)
  260                 p = &proc0;
  261 
  262         /* Initialize our new td  */
  263         newtd = thread_alloc(pages);
  264         if (newtd == NULL)
  265                 return (ENOMEM);
  266 
  267         PROC_LOCK(p);
  268         oldtd = FIRST_THREAD_IN_PROC(p);
  269 
  270         bzero(&newtd->td_startzero,
  271             __rangeof(struct thread, td_startzero, td_endzero));
  272         bzero(&newtd->td_rux, sizeof(newtd->td_rux));
  273         newtd->td_map_def_user = NULL;
  274         newtd->td_dbg_forked = 0;
  275 /* XXX check if we should zero. */
  276         bcopy(&oldtd->td_startcopy, &newtd->td_startcopy,
  277             __rangeof(struct thread, td_startcopy, td_endcopy));
  278 
  279         /* set up arg0 for 'ps', et al */
  280         va_start(ap, fmt);
  281         vsnprintf(newtd->td_name, sizeof(newtd->td_name), fmt, ap);
  282         va_end(ap);
  283 
  284         newtd->td_proc = p;  /* needed for cpu_set_upcall */
  285 
  286         /* XXX optimise this probably? */
  287         /* On x86 (and probably the others too) it is way too full of junk */
  288         /* Needs a better name */
  289         cpu_set_upcall(newtd, oldtd);
  290         /* put the designated function(arg) as the resume context */
  291         cpu_set_fork_handler(newtd, func, arg);
  292 
  293         newtd->td_pflags |= TDP_KTHREAD;
  294         newtd->td_ucred = crhold(p->p_ucred);
  295 
  296         /* this code almost the same as create_thread() in kern_thr.c */
  297         p->p_flag |= P_HADTHREADS;
  298         newtd->td_sigmask = oldtd->td_sigmask; /* XXX dubious */
  299         thread_link(newtd, p);
  300         thread_lock(oldtd);
  301         /* let the scheduler know about these things. */
  302         sched_fork_thread(oldtd, newtd);
  303         TD_SET_CAN_RUN(newtd);
  304         thread_unlock(oldtd);
  305         PROC_UNLOCK(p);
  306 
  307 
  308         /* Avoid inheriting affinity from a random parent. */
  309         cpuset_setthread(newtd->td_tid, cpuset_root);
  310 
  311         /* Delay putting it on the run queue until now. */
  312         if (!(flags & RFSTOPPED)) {
  313                 thread_lock(newtd);
  314                 sched_add(newtd, SRQ_BORING); 
  315                 thread_unlock(newtd);
  316         }
  317         if (newtdp)
  318                 *newtdp = newtd;
  319         return 0;
  320 }
  321 
  322 void
  323 kthread_exit(void)
  324 {
  325         struct proc *p;
  326 
  327         /* A module may be waiting for us to exit. */
  328         wakeup(curthread);
  329 
  330         /*
  331          * We could rely on thread_exit to call exit1() but
  332          * there is extra work that needs to be done
  333          */
  334         if (curthread->td_proc->p_numthreads == 1)
  335                 kproc_exit(0);  /* never returns */
  336 
  337         p = curthread->td_proc;
  338         PROC_LOCK(p);
  339         PROC_SLOCK(p);
  340         thread_exit();
  341 }
  342 
  343 /*
  344  * Advise a kernel process to suspend (or resume) in its main loop.
  345  * Participation is voluntary.
  346  */
  347 int
  348 kthread_suspend(struct thread *td, int timo)
  349 {
  350         if ((td->td_pflags & TDP_KTHREAD) == 0) {
  351                 return (EINVAL);
  352         }
  353         thread_lock(td);
  354         td->td_flags |= TDF_KTH_SUSP;
  355         thread_unlock(td);
  356         /*
  357          * If it's stopped for some other reason,
  358          * kick it to notice our request 
  359          * or we'll end up timing out
  360          */
  361         wakeup(td); /* traditional  place for kernel threads to sleep on */ /* XXX ?? */
  362         return (tsleep(&td->td_flags, PPAUSE | PDROP, "suspkt", timo));
  363 }
  364 
  365 /*
  366  * let the kthread it can keep going again.
  367  */
  368 int
  369 kthread_resume(struct thread *td)
  370 {
  371         if ((td->td_pflags & TDP_KTHREAD) == 0) {
  372                 return (EINVAL);
  373         }
  374         thread_lock(td);
  375         td->td_flags &= ~TDF_KTH_SUSP;
  376         thread_unlock(td);
  377         wakeup(&td->td_name);
  378         return (0);
  379 }
  380 
  381 /*
  382  * Used by the thread to poll as to whether it should yield/sleep
  383  * and notify the caller that is has happened.
  384  */
  385 void
  386 kthread_suspend_check(struct thread *td)
  387 {
  388         while (td->td_flags & TDF_KTH_SUSP) {
  389                 /*
  390                  * let the caller know we got the message then sleep
  391                  */
  392                 wakeup(&td->td_flags);
  393                 tsleep(&td->td_name, PPAUSE, "ktsusp", 0);
  394         }
  395 }
  396 
  397 int
  398 kproc_kthread_add(void (*func)(void *), void *arg,
  399             struct proc **procptr, struct thread **tdptr,
  400             int flags, int pages, const char *procname, const char *fmt, ...) 
  401 {
  402         int error;
  403         va_list ap;
  404         char buf[100];
  405         struct thread *td;
  406 
  407         if (*procptr == 0) {
  408                 error = kproc_create(func, arg,
  409                         procptr, flags, pages, "%s", procname);
  410                 if (error)
  411                         return (error);
  412                 td = FIRST_THREAD_IN_PROC(*procptr);
  413                 if (tdptr)
  414                         *tdptr = td;
  415                 va_start(ap, fmt);
  416                 vsnprintf(td->td_name, sizeof(td->td_name), fmt, ap);
  417                 va_end(ap);
  418 #ifdef KTR
  419                 sched_clear_tdname(td);
  420 #endif
  421                 return (0); 
  422         }
  423         va_start(ap, fmt);
  424         vsnprintf(buf, sizeof(buf), fmt, ap);
  425         va_end(ap);
  426         error = kthread_add(func, arg, *procptr,
  427                     tdptr, flags, pages, "%s", buf);
  428         return (error);
  429 }

Cache object: df3f8b2c71fc44ea3eac9366cf60d18a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.