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