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