threads.c revision 1.8.2.2 1 1.8.2.2 yamt /* $NetBSD: threads.c,v 1.8.2.2 2010/03/11 15:04:38 yamt Exp $ */
2 1.8.2.2 yamt
3 1.8.2.2 yamt /*
4 1.8.2.2 yamt * Copyright (c) 2007-2009 Antti Kantee. All Rights Reserved.
5 1.8.2.2 yamt *
6 1.8.2.2 yamt * Development of this software was supported by
7 1.8.2.2 yamt * The Finnish Cultural Foundation.
8 1.8.2.2 yamt *
9 1.8.2.2 yamt * Redistribution and use in source and binary forms, with or without
10 1.8.2.2 yamt * modification, are permitted provided that the following conditions
11 1.8.2.2 yamt * are met:
12 1.8.2.2 yamt * 1. Redistributions of source code must retain the above copyright
13 1.8.2.2 yamt * notice, this list of conditions and the following disclaimer.
14 1.8.2.2 yamt * 2. Redistributions in binary form must reproduce the above copyright
15 1.8.2.2 yamt * notice, this list of conditions and the following disclaimer in the
16 1.8.2.2 yamt * documentation and/or other materials provided with the distribution.
17 1.8.2.2 yamt *
18 1.8.2.2 yamt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19 1.8.2.2 yamt * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 1.8.2.2 yamt * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 1.8.2.2 yamt * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 1.8.2.2 yamt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 1.8.2.2 yamt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 1.8.2.2 yamt * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 1.8.2.2 yamt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 1.8.2.2 yamt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 1.8.2.2 yamt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 1.8.2.2 yamt * SUCH DAMAGE.
29 1.8.2.2 yamt */
30 1.8.2.2 yamt
31 1.8.2.2 yamt #include <sys/cdefs.h>
32 1.8.2.2 yamt __KERNEL_RCSID(0, "$NetBSD: threads.c,v 1.8.2.2 2010/03/11 15:04:38 yamt Exp $");
33 1.8.2.2 yamt
34 1.8.2.2 yamt #include <sys/param.h>
35 1.8.2.2 yamt #include <sys/kmem.h>
36 1.8.2.2 yamt #include <sys/kthread.h>
37 1.8.2.2 yamt #include <sys/systm.h>
38 1.8.2.2 yamt
39 1.8.2.2 yamt #include <machine/stdarg.h>
40 1.8.2.2 yamt
41 1.8.2.2 yamt #include <rump/rumpuser.h>
42 1.8.2.2 yamt
43 1.8.2.2 yamt #include "rump_private.h"
44 1.8.2.2 yamt
45 1.8.2.2 yamt struct kthdesc {
46 1.8.2.2 yamt void (*f)(void *);
47 1.8.2.2 yamt void *arg;
48 1.8.2.2 yamt struct lwp *mylwp;
49 1.8.2.2 yamt };
50 1.8.2.2 yamt
51 1.8.2.2 yamt static void *
52 1.8.2.2 yamt threadbouncer(void *arg)
53 1.8.2.2 yamt {
54 1.8.2.2 yamt struct kthdesc *k = arg;
55 1.8.2.2 yamt struct lwp *l = k->mylwp;
56 1.8.2.2 yamt void (*f)(void *);
57 1.8.2.2 yamt void *thrarg;
58 1.8.2.2 yamt
59 1.8.2.2 yamt f = k->f;
60 1.8.2.2 yamt thrarg = k->arg;
61 1.8.2.2 yamt rumpuser_free(k);
62 1.8.2.2 yamt
63 1.8.2.2 yamt /* schedule ourselves */
64 1.8.2.2 yamt rumpuser_set_curlwp(l);
65 1.8.2.2 yamt rump_schedule();
66 1.8.2.2 yamt
67 1.8.2.2 yamt if ((curlwp->l_pflag & LP_MPSAFE) == 0)
68 1.8.2.2 yamt KERNEL_LOCK(1, NULL);
69 1.8.2.2 yamt
70 1.8.2.2 yamt f(thrarg);
71 1.8.2.2 yamt
72 1.8.2.2 yamt panic("unreachable, should kthread_exit()");
73 1.8.2.2 yamt }
74 1.8.2.2 yamt
75 1.8.2.2 yamt int
76 1.8.2.2 yamt kthread_create(pri_t pri, int flags, struct cpu_info *ci,
77 1.8.2.2 yamt void (*func)(void *), void *arg, lwp_t **newlp, const char *fmt, ...)
78 1.8.2.2 yamt {
79 1.8.2.2 yamt char thrstore[MAXCOMLEN];
80 1.8.2.2 yamt const char *thrname = NULL;
81 1.8.2.2 yamt va_list ap;
82 1.8.2.2 yamt struct kthdesc *k;
83 1.8.2.2 yamt struct lwp *l;
84 1.8.2.2 yamt int rv;
85 1.8.2.2 yamt
86 1.8.2.2 yamt thrstore[0] = '\0';
87 1.8.2.2 yamt if (fmt) {
88 1.8.2.2 yamt va_start(ap, fmt);
89 1.8.2.2 yamt vsnprintf(thrstore, sizeof(thrstore), fmt, ap);
90 1.8.2.2 yamt va_end(ap);
91 1.8.2.2 yamt thrname = thrstore;
92 1.8.2.2 yamt }
93 1.8.2.2 yamt
94 1.8.2.2 yamt /*
95 1.8.2.2 yamt * We don't want a module unload thread.
96 1.8.2.2 yamt * (XXX: yes, this is a kludge too, and the kernel should
97 1.8.2.2 yamt * have a more flexible method for configuring which threads
98 1.8.2.2 yamt * we want).
99 1.8.2.2 yamt */
100 1.8.2.2 yamt if (strcmp(thrstore, "modunload") == 0) {
101 1.8.2.2 yamt return 0;
102 1.8.2.2 yamt }
103 1.8.2.2 yamt
104 1.8.2.2 yamt if (!rump_threads) {
105 1.8.2.2 yamt /* fake them */
106 1.8.2.2 yamt if (strcmp(thrstore, "vrele") == 0) {
107 1.8.2.2 yamt printf("rump warning: threads not enabled, not starting"
108 1.8.2.2 yamt " vrele thread\n");
109 1.8.2.2 yamt return 0;
110 1.8.2.2 yamt } else if (strcmp(thrstore, "cachegc") == 0) {
111 1.8.2.2 yamt printf("rump warning: threads not enabled, not starting"
112 1.8.2.2 yamt " namecache g/c thread\n");
113 1.8.2.2 yamt return 0;
114 1.8.2.2 yamt } else if (strcmp(thrstore, "nfssilly") == 0) {
115 1.8.2.2 yamt printf("rump warning: threads not enabled, not enabling"
116 1.8.2.2 yamt " nfs silly rename\n");
117 1.8.2.2 yamt return 0;
118 1.8.2.2 yamt } else if (strcmp(thrstore, "unpgc") == 0) {
119 1.8.2.2 yamt printf("rump warning: threads not enabled, not enabling"
120 1.8.2.2 yamt " UNP garbage collection\n");
121 1.8.2.2 yamt return 0;
122 1.8.2.2 yamt } else if (strncmp(thrstore, "pmf", sizeof("pmf")-1) == 0) {
123 1.8.2.2 yamt printf("rump warning: threads not enabled, not enabling"
124 1.8.2.2 yamt " pmf thread\n");
125 1.8.2.2 yamt return 0;
126 1.8.2.2 yamt } else if (strncmp(thrstore, "xcall", sizeof("xcall")-1) == 0) {
127 1.8.2.2 yamt printf("rump warning: threads not enabled, CPU xcall"
128 1.8.2.2 yamt " not functional\n");
129 1.8.2.2 yamt return 0;
130 1.8.2.2 yamt } else
131 1.8.2.2 yamt panic("threads not available, setenv RUMP_THREADS 1");
132 1.8.2.2 yamt }
133 1.8.2.2 yamt KASSERT(fmt != NULL);
134 1.8.2.2 yamt
135 1.8.2.2 yamt k = rumpuser_malloc(sizeof(struct kthdesc), 0);
136 1.8.2.2 yamt k->f = func;
137 1.8.2.2 yamt k->arg = arg;
138 1.8.2.2 yamt k->mylwp = l = rump_lwp_alloc(0, rump_nextlid());
139 1.8.2.2 yamt if (flags & KTHREAD_MPSAFE)
140 1.8.2.2 yamt l->l_pflag |= LP_MPSAFE;
141 1.8.2.2 yamt if (flags & KTHREAD_INTR)
142 1.8.2.2 yamt l->l_pflag |= LP_INTR;
143 1.8.2.2 yamt if (ci) {
144 1.8.2.2 yamt l->l_pflag |= LP_BOUND;
145 1.8.2.2 yamt l->l_cpu = ci;
146 1.8.2.2 yamt }
147 1.8.2.2 yamt if (thrname) {
148 1.8.2.2 yamt l->l_name = kmem_alloc(MAXCOMLEN, KM_SLEEP);
149 1.8.2.2 yamt strlcpy(l->l_name, thrname, MAXCOMLEN);
150 1.8.2.2 yamt }
151 1.8.2.2 yamt
152 1.8.2.2 yamt rv = rumpuser_thread_create(threadbouncer, k, thrname);
153 1.8.2.2 yamt if (rv)
154 1.8.2.2 yamt return rv;
155 1.8.2.2 yamt
156 1.8.2.2 yamt if (newlp)
157 1.8.2.2 yamt *newlp = l;
158 1.8.2.2 yamt return 0;
159 1.8.2.2 yamt }
160 1.8.2.2 yamt
161 1.8.2.2 yamt void
162 1.8.2.2 yamt kthread_exit(int ecode)
163 1.8.2.2 yamt {
164 1.8.2.2 yamt
165 1.8.2.2 yamt if ((curlwp->l_pflag & LP_MPSAFE) == 0)
166 1.8.2.2 yamt KERNEL_UNLOCK_LAST(NULL);
167 1.8.2.2 yamt rump_lwp_release(curlwp);
168 1.8.2.2 yamt rump_unschedule();
169 1.8.2.2 yamt rumpuser_thread_exit();
170 1.8.2.2 yamt }
171