1 /* $NetBSD: kern_kthread.c,v 1.26 2009/01/30 04:09:35 agc Exp $ */
4 * Copyright (c) 1998, 1999, 2007, 2009 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center, and by Andrew Doran.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: kern_kthread.c,v 1.26 2009/01/30 04:09:35 agc Exp $");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/kthread.h>
41 #include <sys/sched.h>
44 #include <uvm/uvm_extern.h>
47 * note that stdarg.h and the ansi style va_start macro is used for both
48 * ansi and traditional c complers.
49 * XXX: this requires that stdarg.h define: va_alist and va_dcl
51 #include <machine/stdarg.h>
54 * Fork a kernel thread. Any process can request this to be done.
57 kthread_create(pri_t pri
, int flag
, struct cpu_info
*ci
,
58 void (*func
)(void *), void *arg
,
59 lwp_t
**lp
, const char *fmt
, ...)
67 uaddr
= uvm_uarea_alloc();
71 if ((flag
& KTHREAD_TS
) != 0) {
76 error
= lwp_create(&lwp0
, &proc0
, uaddr
, LWP_DETACHED
, NULL
,
77 0, func
, arg
, &l
, lc
);
79 uvm_uarea_free(uaddr
);
83 l
->l_name
= kmem_alloc(MAXCOMLEN
, KM_SLEEP
);
84 if (l
->l_name
== NULL
) {
89 vsnprintf(l
->l_name
, MAXCOMLEN
, fmt
, ap
);
96 if ((flag
& KTHREAD_INTR
) != 0) {
97 KASSERT((flag
& KTHREAD_MPSAFE
) != 0);
100 if (pri
== PRI_NONE
) {
101 if ((flag
& KTHREAD_TS
) != 0) {
102 /* Maximum user priority level. */
105 /* Minimum kernel priority level. */
109 mutex_enter(proc0
.p_lock
);
113 if (ci
!= l
->l_cpu
) {
114 lwp_unlock_to(l
, ci
->ci_schedstate
.spc_mutex
);
117 l
->l_pflag
|= LP_BOUND
;
120 if ((flag
& KTHREAD_INTR
) != 0)
121 l
->l_pflag
|= LP_INTR
;
122 if ((flag
& KTHREAD_MPSAFE
) == 0)
123 l
->l_pflag
&= ~LP_MPSAFE
;
126 * Set the new LWP running, unless the caller has requested
129 if ((flag
& KTHREAD_IDLE
) == 0) {
131 sched_enqueue(l
, false);
134 lwp_unlock_to(l
, ci
->ci_schedstate
.spc_lwplock
);
137 * The LWP is not created suspended or stopped and cannot be set
138 * into those states later, so must be considered runnable.
141 mutex_exit(proc0
.p_lock
);
151 * Cause a kernel thread to exit. Assumes the exiting thread is the
155 kthread_exit(int ecode
)
160 /* We can't do much with the exit code, so just report it. */
162 if ((name
= l
->l_name
) == NULL
)
164 printf("WARNING: kthread `%s' (%d) exits with status %d\n",
165 name
, l
->l_lid
, ecode
);
172 * XXX Fool the compiler. Making exit1() __noreturn__ is a can
173 * XXX of worms right now.
180 * Destroy an inactive kthread. The kthread must be in the LSIDL state.
183 kthread_destroy(lwp_t
*l
)
186 KASSERT((l
->l_flag
& LW_SYSTEM
) != 0);
187 KASSERT(l
->l_stat
== LSIDL
);