Annotation of src/sys/kern/kern_kthread.c, Revision 1.35
1.35 ! joerg 1: /* $NetBSD: kern_kthread.c,v 1.34 2011/05/24 18:18:22 joerg Exp $ */
1.1 thorpej 2:
3: /*-
1.25 ad 4: * Copyright (c) 1998, 1999, 2007, 2009 The NetBSD Foundation, Inc.
1.1 thorpej 5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
1.17 ad 9: * NASA Ames Research Center, and by Andrew Doran.
1.1 thorpej 10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
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.
19: *
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.
31: */
1.12 lukem 32:
33: #include <sys/cdefs.h>
1.35 ! joerg 34: __KERNEL_RCSID(0, "$NetBSD: kern_kthread.c,v 1.34 2011/05/24 18:18:22 joerg Exp $");
1.1 thorpej 35:
36: #include <sys/param.h>
37: #include <sys/systm.h>
38: #include <sys/kernel.h>
39: #include <sys/kthread.h>
1.33 rmind 40: #include <sys/mutex.h>
1.17 ad 41: #include <sys/sched.h>
42: #include <sys/kmem.h>
43:
44: #include <uvm/uvm_extern.h>
1.33 rmind 45:
46: static lwp_t * kthread_jtarget;
47: static kmutex_t kthread_lock;
48: static kcondvar_t kthread_cv;
49:
50: void
51: kthread_sysinit(void)
52: {
1.1 thorpej 53:
1.33 rmind 54: mutex_init(&kthread_lock, MUTEX_DEFAULT, IPL_NONE);
55: cv_init(&kthread_cv, "kthrwait");
56: kthread_jtarget = NULL;
57: }
1.1 thorpej 58:
59: /*
1.33 rmind 60: * kthread_create: create a kernel thread, that is, system-only LWP.
1.1 thorpej 61: */
62: int
1.17 ad 63: kthread_create(pri_t pri, int flag, struct cpu_info *ci,
1.33 rmind 64: void (*func)(void *), void *arg, lwp_t **lp, const char *fmt, ...)
1.1 thorpej 65: {
1.17 ad 66: lwp_t *l;
67: vaddr_t uaddr;
1.33 rmind 68: int error, lc;
1.1 thorpej 69: va_list ap;
70:
1.33 rmind 71: KASSERT((flag & KTHREAD_INTR) == 0 || (flag & KTHREAD_MPSAFE) != 0);
1.31 matt 72:
73: uaddr = uvm_uarea_system_alloc();
1.27 rmind 74: if (uaddr == 0) {
1.17 ad 75: return ENOMEM;
1.27 rmind 76: }
1.26 agc 77: if ((flag & KTHREAD_TS) != 0) {
1.25 ad 78: lc = SCHED_OTHER;
79: } else {
80: lc = SCHED_RR;
81: }
1.28 haad 82:
1.33 rmind 83: error = lwp_create(&lwp0, &proc0, uaddr, LWP_DETACHED, NULL,
1.25 ad 84: 0, func, arg, &l, lc);
1.17 ad 85: if (error) {
1.31 matt 86: uvm_uarea_system_free(uaddr);
1.17 ad 87: return error;
88: }
89: if (fmt != NULL) {
90: l->l_name = kmem_alloc(MAXCOMLEN, KM_SLEEP);
91: if (l->l_name == NULL) {
1.28 haad 92: kthread_destroy(l);
1.17 ad 93: return ENOMEM;
94: }
95: va_start(ap, fmt);
96: vsnprintf(l->l_name, MAXCOMLEN, fmt, ap);
97: va_end(ap);
98: }
99:
100: /*
101: * Set parameters.
102: */
103: if (pri == PRI_NONE) {
1.26 agc 104: if ((flag & KTHREAD_TS) != 0) {
1.25 ad 105: /* Maximum user priority level. */
106: pri = MAXPRI_USER;
107: } else {
108: /* Minimum kernel priority level. */
109: pri = PRI_KTHREAD;
110: }
1.17 ad 111: }
1.23 ad 112: mutex_enter(proc0.p_lock);
1.19 ad 113: lwp_lock(l);
1.17 ad 114: l->l_priority = pri;
115: if (ci != NULL) {
116: if (ci != l->l_cpu) {
117: lwp_unlock_to(l, ci->ci_schedstate.spc_mutex);
118: lwp_lock(l);
119: }
1.22 ad 120: l->l_pflag |= LP_BOUND;
1.17 ad 121: l->l_cpu = ci;
122: }
1.33 rmind 123:
124: if ((flag & KTHREAD_JOINABLE) != 0) {
125: KASSERT(lp != NULL);
126: l->l_pflag |= LP_JOINABLE;
127: }
128: if ((flag & KTHREAD_INTR) != 0) {
1.19 ad 129: l->l_pflag |= LP_INTR;
1.33 rmind 130: }
131: if ((flag & KTHREAD_MPSAFE) == 0) {
1.20 ad 132: l->l_pflag &= ~LP_MPSAFE;
1.33 rmind 133: }
1.17 ad 134:
135: /*
136: * Set the new LWP running, unless the caller has requested
137: * otherwise.
138: */
139: if ((flag & KTHREAD_IDLE) == 0) {
140: l->l_stat = LSRUN;
141: sched_enqueue(l, false);
1.19 ad 142: lwp_unlock(l);
143: } else
1.21 ad 144: lwp_unlock_to(l, ci->ci_schedstate.spc_lwplock);
1.23 ad 145: mutex_exit(proc0.p_lock);
1.1 thorpej 146:
147: /* All done! */
1.33 rmind 148: if (lp != NULL) {
1.17 ad 149: *lp = l;
1.33 rmind 150: }
151: return 0;
1.1 thorpej 152: }
153:
154: /*
155: * Cause a kernel thread to exit. Assumes the exiting thread is the
156: * current context.
157: */
158: void
1.11 thorpej 159: kthread_exit(int ecode)
1.1 thorpej 160: {
1.18 ad 161: const char *name;
1.17 ad 162: lwp_t *l = curlwp;
1.1 thorpej 163:
1.17 ad 164: /* We can't do much with the exit code, so just report it. */
1.18 ad 165: if (ecode != 0) {
166: if ((name = l->l_name) == NULL)
167: name = "unnamed";
1.17 ad 168: printf("WARNING: kthread `%s' (%d) exits with status %d\n",
1.18 ad 169: name, l->l_lid, ecode);
170: }
1.1 thorpej 171:
1.33 rmind 172: /* Barrier for joining. */
173: if (l->l_pflag & LP_JOINABLE) {
174: mutex_enter(&kthread_lock);
175: while (kthread_jtarget != l) {
176: cv_wait(&kthread_cv, &kthread_lock);
177: }
178: kthread_jtarget = NULL;
179: cv_broadcast(&kthread_cv);
180: mutex_exit(&kthread_lock);
181: }
182:
1.17 ad 183: /* And exit.. */
184: lwp_exit(l);
1.34 joerg 185: panic("kthread_exit");
1.2 thorpej 186: }
187:
188: /*
1.17 ad 189: * Destroy an inactive kthread. The kthread must be in the LSIDL state.
1.2 thorpej 190: */
191: void
1.17 ad 192: kthread_destroy(lwp_t *l)
1.2 thorpej 193: {
1.33 rmind 194:
1.17 ad 195: KASSERT((l->l_flag & LW_SYSTEM) != 0);
196: KASSERT(l->l_stat == LSIDL);
1.2 thorpej 197:
1.17 ad 198: lwp_exit(l);
1.1 thorpej 199: }
1.28 haad 200:
201: /*
202: * Wait for a kthread to exit, as pthread_join().
203: */
204: int
205: kthread_join(lwp_t *l)
206: {
207:
208: KASSERT((l->l_flag & LW_SYSTEM) != 0);
209:
1.33 rmind 210: /*
211: * - Wait if some other thread has occupied the target.
212: * - Speicfy our kthread as a target and notify it.
213: * - Wait for the target kthread to notify us.
214: */
215: mutex_enter(&kthread_lock);
216: while (kthread_jtarget) {
217: cv_wait(&kthread_cv, &kthread_lock);
218: }
219: kthread_jtarget = l;
220: cv_broadcast(&kthread_cv);
221: while (kthread_jtarget == l) {
222: cv_wait(&kthread_cv, &kthread_lock);
223: }
224: mutex_exit(&kthread_lock);
225:
226: return 0;
1.28 haad 227: }
CVSweb <webmaster@jp.NetBSD.org>