1*eda14cbcSMatt Macy /* 2*eda14cbcSMatt Macy * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. 3*eda14cbcSMatt Macy * Copyright (C) 2007 The Regents of the University of California. 4*eda14cbcSMatt Macy * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). 5*eda14cbcSMatt Macy * Written by Brian Behlendorf <behlendorf1@llnl.gov>. 6*eda14cbcSMatt Macy * UCRL-CODE-235197 7*eda14cbcSMatt Macy * 8*eda14cbcSMatt Macy * This file is part of the SPL, Solaris Porting Layer. 9*eda14cbcSMatt Macy * For details, see <http://zfsonlinux.org/>. 10*eda14cbcSMatt Macy * 11*eda14cbcSMatt Macy * The SPL is free software; you can redistribute it and/or modify it 12*eda14cbcSMatt Macy * under the terms of the GNU General Public License as published by the 13*eda14cbcSMatt Macy * Free Software Foundation; either version 2 of the License, or (at your 14*eda14cbcSMatt Macy * option) any later version. 15*eda14cbcSMatt Macy * 16*eda14cbcSMatt Macy * The SPL is distributed in the hope that it will be useful, but WITHOUT 17*eda14cbcSMatt Macy * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 18*eda14cbcSMatt Macy * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 19*eda14cbcSMatt Macy * for more details. 20*eda14cbcSMatt Macy * 21*eda14cbcSMatt Macy * You should have received a copy of the GNU General Public License along 22*eda14cbcSMatt Macy * with the SPL. If not, see <http://www.gnu.org/licenses/>. 23*eda14cbcSMatt Macy * 24*eda14cbcSMatt Macy * Solaris Porting Layer (SPL) Thread Implementation. 25*eda14cbcSMatt Macy */ 26*eda14cbcSMatt Macy 27*eda14cbcSMatt Macy #include <sys/thread.h> 28*eda14cbcSMatt Macy #include <sys/kmem.h> 29*eda14cbcSMatt Macy #include <sys/tsd.h> 30*eda14cbcSMatt Macy 31*eda14cbcSMatt Macy /* 32*eda14cbcSMatt Macy * Thread interfaces 33*eda14cbcSMatt Macy */ 34*eda14cbcSMatt Macy typedef struct thread_priv_s { 35*eda14cbcSMatt Macy unsigned long tp_magic; /* Magic */ 36*eda14cbcSMatt Macy int tp_name_size; /* Name size */ 37*eda14cbcSMatt Macy char *tp_name; /* Name (without _thread suffix) */ 38*eda14cbcSMatt Macy void (*tp_func)(void *); /* Registered function */ 39*eda14cbcSMatt Macy void *tp_args; /* Args to be passed to function */ 40*eda14cbcSMatt Macy size_t tp_len; /* Len to be passed to function */ 41*eda14cbcSMatt Macy int tp_state; /* State to start thread at */ 42*eda14cbcSMatt Macy pri_t tp_pri; /* Priority to start threat at */ 43*eda14cbcSMatt Macy } thread_priv_t; 44*eda14cbcSMatt Macy 45*eda14cbcSMatt Macy static int 46*eda14cbcSMatt Macy thread_generic_wrapper(void *arg) 47*eda14cbcSMatt Macy { 48*eda14cbcSMatt Macy thread_priv_t *tp = (thread_priv_t *)arg; 49*eda14cbcSMatt Macy void (*func)(void *); 50*eda14cbcSMatt Macy void *args; 51*eda14cbcSMatt Macy 52*eda14cbcSMatt Macy ASSERT(tp->tp_magic == TP_MAGIC); 53*eda14cbcSMatt Macy func = tp->tp_func; 54*eda14cbcSMatt Macy args = tp->tp_args; 55*eda14cbcSMatt Macy set_current_state(tp->tp_state); 56*eda14cbcSMatt Macy set_user_nice((kthread_t *)current, PRIO_TO_NICE(tp->tp_pri)); 57*eda14cbcSMatt Macy kmem_free(tp->tp_name, tp->tp_name_size); 58*eda14cbcSMatt Macy kmem_free(tp, sizeof (thread_priv_t)); 59*eda14cbcSMatt Macy 60*eda14cbcSMatt Macy if (func) 61*eda14cbcSMatt Macy func(args); 62*eda14cbcSMatt Macy 63*eda14cbcSMatt Macy return (0); 64*eda14cbcSMatt Macy } 65*eda14cbcSMatt Macy 66*eda14cbcSMatt Macy void 67*eda14cbcSMatt Macy __thread_exit(void) 68*eda14cbcSMatt Macy { 69*eda14cbcSMatt Macy tsd_exit(); 70*eda14cbcSMatt Macy complete_and_exit(NULL, 0); 71*eda14cbcSMatt Macy /* Unreachable */ 72*eda14cbcSMatt Macy } 73*eda14cbcSMatt Macy EXPORT_SYMBOL(__thread_exit); 74*eda14cbcSMatt Macy 75*eda14cbcSMatt Macy /* 76*eda14cbcSMatt Macy * thread_create() may block forever if it cannot create a thread or 77*eda14cbcSMatt Macy * allocate memory. This is preferable to returning a NULL which Solaris 78*eda14cbcSMatt Macy * style callers likely never check for... since it can't fail. 79*eda14cbcSMatt Macy */ 80*eda14cbcSMatt Macy kthread_t * 81*eda14cbcSMatt Macy __thread_create(caddr_t stk, size_t stksize, thread_func_t func, 82*eda14cbcSMatt Macy const char *name, void *args, size_t len, proc_t *pp, int state, pri_t pri) 83*eda14cbcSMatt Macy { 84*eda14cbcSMatt Macy thread_priv_t *tp; 85*eda14cbcSMatt Macy struct task_struct *tsk; 86*eda14cbcSMatt Macy char *p; 87*eda14cbcSMatt Macy 88*eda14cbcSMatt Macy /* Option pp is simply ignored */ 89*eda14cbcSMatt Macy /* Variable stack size unsupported */ 90*eda14cbcSMatt Macy ASSERT(stk == NULL); 91*eda14cbcSMatt Macy 92*eda14cbcSMatt Macy tp = kmem_alloc(sizeof (thread_priv_t), KM_PUSHPAGE); 93*eda14cbcSMatt Macy if (tp == NULL) 94*eda14cbcSMatt Macy return (NULL); 95*eda14cbcSMatt Macy 96*eda14cbcSMatt Macy tp->tp_magic = TP_MAGIC; 97*eda14cbcSMatt Macy tp->tp_name_size = strlen(name) + 1; 98*eda14cbcSMatt Macy 99*eda14cbcSMatt Macy tp->tp_name = kmem_alloc(tp->tp_name_size, KM_PUSHPAGE); 100*eda14cbcSMatt Macy if (tp->tp_name == NULL) { 101*eda14cbcSMatt Macy kmem_free(tp, sizeof (thread_priv_t)); 102*eda14cbcSMatt Macy return (NULL); 103*eda14cbcSMatt Macy } 104*eda14cbcSMatt Macy 105*eda14cbcSMatt Macy strncpy(tp->tp_name, name, tp->tp_name_size); 106*eda14cbcSMatt Macy 107*eda14cbcSMatt Macy /* 108*eda14cbcSMatt Macy * Strip trailing "_thread" from passed name which will be the func 109*eda14cbcSMatt Macy * name since the exposed API has no parameter for passing a name. 110*eda14cbcSMatt Macy */ 111*eda14cbcSMatt Macy p = strstr(tp->tp_name, "_thread"); 112*eda14cbcSMatt Macy if (p) 113*eda14cbcSMatt Macy p[0] = '\0'; 114*eda14cbcSMatt Macy 115*eda14cbcSMatt Macy tp->tp_func = func; 116*eda14cbcSMatt Macy tp->tp_args = args; 117*eda14cbcSMatt Macy tp->tp_len = len; 118*eda14cbcSMatt Macy tp->tp_state = state; 119*eda14cbcSMatt Macy tp->tp_pri = pri; 120*eda14cbcSMatt Macy 121*eda14cbcSMatt Macy tsk = spl_kthread_create(thread_generic_wrapper, (void *)tp, 122*eda14cbcSMatt Macy "%s", tp->tp_name); 123*eda14cbcSMatt Macy if (IS_ERR(tsk)) 124*eda14cbcSMatt Macy return (NULL); 125*eda14cbcSMatt Macy 126*eda14cbcSMatt Macy wake_up_process(tsk); 127*eda14cbcSMatt Macy return ((kthread_t *)tsk); 128*eda14cbcSMatt Macy } 129*eda14cbcSMatt Macy EXPORT_SYMBOL(__thread_create); 130*eda14cbcSMatt Macy 131*eda14cbcSMatt Macy /* 132*eda14cbcSMatt Macy * spl_kthread_create - Wrapper providing pre-3.13 semantics for 133*eda14cbcSMatt Macy * kthread_create() in which it is not killable and less likely 134*eda14cbcSMatt Macy * to return -ENOMEM. 135*eda14cbcSMatt Macy */ 136*eda14cbcSMatt Macy struct task_struct * 137*eda14cbcSMatt Macy spl_kthread_create(int (*func)(void *), void *data, const char namefmt[], ...) 138*eda14cbcSMatt Macy { 139*eda14cbcSMatt Macy struct task_struct *tsk; 140*eda14cbcSMatt Macy va_list args; 141*eda14cbcSMatt Macy char name[TASK_COMM_LEN]; 142*eda14cbcSMatt Macy 143*eda14cbcSMatt Macy va_start(args, namefmt); 144*eda14cbcSMatt Macy vsnprintf(name, sizeof (name), namefmt, args); 145*eda14cbcSMatt Macy va_end(args); 146*eda14cbcSMatt Macy do { 147*eda14cbcSMatt Macy tsk = kthread_create(func, data, "%s", name); 148*eda14cbcSMatt Macy if (IS_ERR(tsk)) { 149*eda14cbcSMatt Macy if (signal_pending(current)) { 150*eda14cbcSMatt Macy clear_thread_flag(TIF_SIGPENDING); 151*eda14cbcSMatt Macy continue; 152*eda14cbcSMatt Macy } 153*eda14cbcSMatt Macy if (PTR_ERR(tsk) == -ENOMEM) 154*eda14cbcSMatt Macy continue; 155*eda14cbcSMatt Macy return (NULL); 156*eda14cbcSMatt Macy } else { 157*eda14cbcSMatt Macy return (tsk); 158*eda14cbcSMatt Macy } 159*eda14cbcSMatt Macy } while (1); 160*eda14cbcSMatt Macy } 161*eda14cbcSMatt Macy EXPORT_SYMBOL(spl_kthread_create); 162