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