root/kern/kern_kthread.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. kthread_create
  2. kthread_exit
  3. kthread_create_deferred
  4. kthread_run_deferred_queue

    1 /*      $OpenBSD: kern_kthread.c,v 1.27 2007/03/15 10:22:30 art Exp $   */
    2 /*      $NetBSD: kern_kthread.c,v 1.3 1998/12/22 21:21:36 kleink Exp $  */
    3 
    4 /*-
    5  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
   10  * NASA Ames Research Center.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by the NetBSD
   23  *      Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/kernel.h>
   44 #include <sys/kthread.h>
   45 #include <sys/proc.h>
   46 #include <sys/wait.h>
   47 #include <sys/malloc.h>
   48 #include <sys/queue.h>
   49 
   50 #include <machine/cpu.h>
   51 
   52 /*
   53  * note that stdarg.h and the ansi style va_start macro is used for both
   54  * ansi and traditional c compilers.
   55  * XXX: this requires that stdarg.h define: va_alist and va_dcl
   56  */
   57 #include <sys/stdarg.h>
   58 
   59 int     kthread_create_now;
   60 
   61 /*
   62  * Fork a kernel thread.  Any process can request this to be done.
   63  * The VM space and limits, etc. will be shared with proc0.
   64  */
   65 int
   66 kthread_create(void (*func)(void *), void *arg,
   67     struct proc **newpp, const char *fmt, ...)
   68 {
   69         struct proc *p2;
   70         int error;
   71         va_list ap;
   72 
   73         /*
   74          * First, create the new process.  Share the memory, file
   75          * descriptors and don't leave the exit status around for the
   76          * parent to wait for.
   77          */
   78         error = fork1(&proc0, 0, FORK_SHAREVM |FORK_NOZOMBIE |FORK_SIGHAND,
   79             NULL, 0, func, arg, NULL, &p2);
   80         if (error)
   81                 return (error);
   82 
   83         /*
   84          * Mark it as a system process.
   85          */
   86         atomic_setbits_int(&p2->p_flag, P_SYSTEM);
   87 
   88         /* Name it as specified. */
   89         va_start(ap, fmt);
   90         vsnprintf(p2->p_comm, sizeof p2->p_comm, fmt, ap);
   91         va_end(ap);
   92 
   93         /* All done! */
   94         if (newpp != NULL)
   95                 *newpp = p2;
   96         return (0);
   97 }
   98 
   99 /*
  100  * Cause a kernel thread to exit.  Assumes the exiting thread is the
  101  * current context.
  102  */
  103 void
  104 kthread_exit(int ecode)
  105 {
  106 
  107         /*
  108          * XXX What do we do with the exit code?  Should we even bother
  109          * XXX with it?  The parent (proc0) isn't going to do much with
  110          * XXX it.
  111          */
  112         if (ecode != 0)
  113                 printf("WARNING: thread `%s' (%d) exits with status %d\n",
  114                     curproc->p_comm, curproc->p_pid, ecode);
  115 
  116         exit1(curproc, W_EXITCODE(ecode, 0), EXIT_NORMAL);
  117 
  118         /*
  119          * XXX Fool the compiler.  Making exit1() __dead is a can
  120          * XXX of worms right now.
  121          */
  122         for (;;);
  123 }
  124 
  125 struct kthread_q {
  126         SIMPLEQ_ENTRY(kthread_q) kq_q;
  127         void (*kq_func)(void *);
  128         void *kq_arg;
  129 };
  130 
  131 SIMPLEQ_HEAD(, kthread_q) kthread_q = SIMPLEQ_HEAD_INITIALIZER(kthread_q);
  132 
  133 /*
  134  * Defer the creation of a kernel thread.  Once the standard kernel threads
  135  * and processes have been created, this queue will be run to callback to
  136  * the caller to create threads for e.g. file systems and device drivers.
  137  */
  138 void
  139 kthread_create_deferred(void (*func)(void *), void *arg)
  140 {
  141         struct kthread_q *kq;
  142 
  143         if (kthread_create_now) {
  144                 (*func)(arg);
  145                 return;
  146         }
  147 
  148         kq = malloc(sizeof *kq, M_TEMP, M_NOWAIT);
  149         if (kq == NULL)
  150                 panic("unable to allocate kthread_q");
  151         bzero(kq, sizeof *kq);
  152 
  153         kq->kq_func = func;
  154         kq->kq_arg = arg;
  155 
  156         SIMPLEQ_INSERT_TAIL(&kthread_q, kq, kq_q);
  157 }
  158 
  159 void
  160 kthread_run_deferred_queue(void)
  161 {
  162         struct kthread_q *kq;
  163 
  164         /* No longer need to defer kthread creation. */
  165         kthread_create_now = 1;
  166 
  167         while ((kq = SIMPLEQ_FIRST(&kthread_q)) != NULL) {
  168                 SIMPLEQ_REMOVE_HEAD(&kthread_q, kq_q);
  169                 (*kq->kq_func)(kq->kq_arg);
  170                 free(kq, M_TEMP);
  171         }
  172 }

/* [<][>][^][v][top][bottom][index][help] */