1*11f8c2f9Spooka /* $NetBSD: threads.c,v 1.12 2010/09/01 19:37:59 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*11f8c2f9Spooka __KERNEL_RCSID(0, "$NetBSD: threads.c,v 1.12 2010/09/01 19:37:59 pooka Exp $"); 33c03306bcSpooka 34c03306bcSpooka #include <sys/param.h> 359970bb9eSpooka #include <sys/atomic.h> 36c03306bcSpooka #include <sys/kmem.h> 37c03306bcSpooka #include <sys/kthread.h> 38c91a5143Spooka #include <sys/malloc.h> 39c03306bcSpooka #include <sys/systm.h> 40c03306bcSpooka 41c03306bcSpooka #include <machine/stdarg.h> 42c03306bcSpooka 43c03306bcSpooka #include <rump/rumpuser.h> 44c03306bcSpooka 45c03306bcSpooka #include "rump_private.h" 46c03306bcSpooka 47c03306bcSpooka struct kthdesc { 48c03306bcSpooka void (*f)(void *); 49c03306bcSpooka void *arg; 50c03306bcSpooka struct lwp *mylwp; 51c03306bcSpooka }; 52c03306bcSpooka 53c03306bcSpooka static void * 54c03306bcSpooka threadbouncer(void *arg) 55c03306bcSpooka { 56c03306bcSpooka struct kthdesc *k = arg; 571029997fSpooka struct lwp *l = k->mylwp; 58c03306bcSpooka void (*f)(void *); 59c03306bcSpooka void *thrarg; 60c03306bcSpooka 61c03306bcSpooka f = k->f; 62c03306bcSpooka thrarg = k->arg; 631029997fSpooka 6419cde6b5Spooka /* schedule ourselves */ 651029997fSpooka rumpuser_set_curlwp(l); 66c03306bcSpooka rump_schedule(); 67c03306bcSpooka 68c91a5143Spooka /* free dance struct */ 69c91a5143Spooka free(k, M_TEMP); 70c91a5143Spooka 71c03306bcSpooka if ((curlwp->l_pflag & LP_MPSAFE) == 0) 72c03306bcSpooka KERNEL_LOCK(1, NULL); 73c03306bcSpooka 74c03306bcSpooka f(thrarg); 75c03306bcSpooka 76c03306bcSpooka panic("unreachable, should kthread_exit()"); 77c03306bcSpooka } 78c03306bcSpooka 79c03306bcSpooka int 80c03306bcSpooka kthread_create(pri_t pri, int flags, struct cpu_info *ci, 81c03306bcSpooka void (*func)(void *), void *arg, lwp_t **newlp, const char *fmt, ...) 82c03306bcSpooka { 83c03306bcSpooka char thrstore[MAXCOMLEN]; 84c03306bcSpooka const char *thrname = NULL; 85c03306bcSpooka va_list ap; 86c03306bcSpooka struct kthdesc *k; 87c03306bcSpooka struct lwp *l; 88c03306bcSpooka int rv; 89c03306bcSpooka 90c03306bcSpooka thrstore[0] = '\0'; 91c03306bcSpooka if (fmt) { 92c03306bcSpooka va_start(ap, fmt); 93c03306bcSpooka vsnprintf(thrstore, sizeof(thrstore), fmt, ap); 94c03306bcSpooka va_end(ap); 95c03306bcSpooka thrname = thrstore; 96c03306bcSpooka } 97c03306bcSpooka 98c03306bcSpooka /* 99c03306bcSpooka * We don't want a module unload thread. 100c03306bcSpooka * (XXX: yes, this is a kludge too, and the kernel should 101c03306bcSpooka * have a more flexible method for configuring which threads 102c03306bcSpooka * we want). 103c03306bcSpooka */ 104c03306bcSpooka if (strcmp(thrstore, "modunload") == 0) { 105c03306bcSpooka return 0; 106c03306bcSpooka } 107c03306bcSpooka 108c03306bcSpooka if (!rump_threads) { 109c03306bcSpooka /* fake them */ 110c03306bcSpooka if (strcmp(thrstore, "vrele") == 0) { 111c03306bcSpooka printf("rump warning: threads not enabled, not starting" 112c03306bcSpooka " vrele thread\n"); 113c03306bcSpooka return 0; 114c03306bcSpooka } else if (strcmp(thrstore, "cachegc") == 0) { 115c03306bcSpooka printf("rump warning: threads not enabled, not starting" 116c03306bcSpooka " namecache g/c thread\n"); 117c03306bcSpooka return 0; 118c03306bcSpooka } else if (strcmp(thrstore, "nfssilly") == 0) { 119c03306bcSpooka printf("rump warning: threads not enabled, not enabling" 120c03306bcSpooka " nfs silly rename\n"); 121c03306bcSpooka return 0; 122c03306bcSpooka } else if (strcmp(thrstore, "unpgc") == 0) { 123c03306bcSpooka printf("rump warning: threads not enabled, not enabling" 124c03306bcSpooka " UNP garbage collection\n"); 125c03306bcSpooka return 0; 126580ff1a8Spooka } else if (strncmp(thrstore, "pmf", sizeof("pmf")-1) == 0) { 127580ff1a8Spooka printf("rump warning: threads not enabled, not enabling" 128580ff1a8Spooka " pmf thread\n"); 129580ff1a8Spooka return 0; 13053ddf73fSpooka } else if (strncmp(thrstore, "xcall", sizeof("xcall")-1) == 0) { 13153ddf73fSpooka printf("rump warning: threads not enabled, CPU xcall" 13253ddf73fSpooka " not functional\n"); 13353ddf73fSpooka return 0; 134c03306bcSpooka } else 135c03306bcSpooka panic("threads not available, setenv RUMP_THREADS 1"); 136c03306bcSpooka } 137c03306bcSpooka KASSERT(fmt != NULL); 138c03306bcSpooka 139c91a5143Spooka k = malloc(sizeof(*k), M_TEMP, M_WAITOK); 140c03306bcSpooka k->f = func; 141c03306bcSpooka k->arg = arg; 142*11f8c2f9Spooka k->mylwp = l = rump__lwproc_allockernlwp(); 143d11274ecSpooka l->l_flag |= LW_SYSTEM; 144c03306bcSpooka if (flags & KTHREAD_MPSAFE) 145c03306bcSpooka l->l_pflag |= LP_MPSAFE; 1461029997fSpooka if (flags & KTHREAD_INTR) 1471029997fSpooka l->l_pflag |= LP_INTR; 14862e84772Spooka if (ci) { 14962e84772Spooka l->l_pflag |= LP_BOUND; 150d11274ecSpooka l->l_target_cpu = ci; 15162e84772Spooka } 1522f3605b7Spooka if (thrname) { 1532f3605b7Spooka l->l_name = kmem_alloc(MAXCOMLEN, KM_SLEEP); 1542f3605b7Spooka strlcpy(l->l_name, thrname, MAXCOMLEN); 1552f3605b7Spooka } 1562f3605b7Spooka 1579970bb9eSpooka rv = rumpuser_thread_create(threadbouncer, k, thrname, 1589970bb9eSpooka (flags & KTHREAD_JOINABLE) == KTHREAD_JOINABLE, &l->l_ctxlink); 159c03306bcSpooka if (rv) 160c03306bcSpooka return rv; 161c03306bcSpooka 1629970bb9eSpooka if (newlp) { 163c03306bcSpooka *newlp = l; 1649970bb9eSpooka } else { 1659970bb9eSpooka KASSERT((flags & KTHREAD_JOINABLE) == 0); 1669970bb9eSpooka } 1679970bb9eSpooka 168c03306bcSpooka return 0; 169c03306bcSpooka } 170c03306bcSpooka 171c03306bcSpooka void 172c03306bcSpooka kthread_exit(int ecode) 173c03306bcSpooka { 174c03306bcSpooka 175c03306bcSpooka if ((curlwp->l_pflag & LP_MPSAFE) == 0) 176630dc3f6Spooka KERNEL_UNLOCK_LAST(NULL); 177*11f8c2f9Spooka rump_lwproc_releaselwp(); 1789970bb9eSpooka /* unschedule includes membar */ 179c03306bcSpooka rump_unschedule(); 180c03306bcSpooka rumpuser_thread_exit(); 181c03306bcSpooka } 1829970bb9eSpooka 1839970bb9eSpooka int 1849970bb9eSpooka kthread_join(struct lwp *l) 1859970bb9eSpooka { 1869970bb9eSpooka int rv; 1879970bb9eSpooka 1889970bb9eSpooka KASSERT(l->l_ctxlink != NULL); 1899970bb9eSpooka rv = rumpuser_thread_join(l->l_ctxlink); 1909970bb9eSpooka membar_consumer(); 1919970bb9eSpooka 1929970bb9eSpooka return rv; 1939970bb9eSpooka } 194