1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. 3eda14cbcSMatt Macy * Copyright (C) 2007 The Regents of the University of California. 4eda14cbcSMatt Macy * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). 5eda14cbcSMatt Macy * Written by Brian Behlendorf <behlendorf1@llnl.gov>. 6eda14cbcSMatt Macy * UCRL-CODE-235197 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * This file is part of the SPL, Solaris Porting Layer. 9eda14cbcSMatt Macy * 10eda14cbcSMatt Macy * The SPL is free software; you can redistribute it and/or modify it 11eda14cbcSMatt Macy * under the terms of the GNU General Public License as published by the 12eda14cbcSMatt Macy * Free Software Foundation; either version 2 of the License, or (at your 13eda14cbcSMatt Macy * option) any later version. 14eda14cbcSMatt Macy * 15eda14cbcSMatt Macy * The SPL is distributed in the hope that it will be useful, but WITHOUT 16eda14cbcSMatt Macy * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17eda14cbcSMatt Macy * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18eda14cbcSMatt Macy * for more details. 19eda14cbcSMatt Macy * 20eda14cbcSMatt Macy * You should have received a copy of the GNU General Public License along 21eda14cbcSMatt Macy * with the SPL. If not, see <http://www.gnu.org/licenses/>. 22eda14cbcSMatt Macy * 23eda14cbcSMatt Macy * Solaris Porting Layer (SPL) Thread Implementation. 24eda14cbcSMatt Macy */ 25eda14cbcSMatt Macy 26eda14cbcSMatt Macy #include <sys/thread.h> 27eda14cbcSMatt Macy #include <sys/kmem.h> 28eda14cbcSMatt Macy #include <sys/tsd.h> 29eda14cbcSMatt Macy 30eda14cbcSMatt Macy /* 31eda14cbcSMatt Macy * Thread interfaces 32eda14cbcSMatt Macy */ 33eda14cbcSMatt Macy typedef struct thread_priv_s { 34eda14cbcSMatt Macy unsigned long tp_magic; /* Magic */ 35eda14cbcSMatt Macy int tp_name_size; /* Name size */ 36eda14cbcSMatt Macy char *tp_name; /* Name (without _thread suffix) */ 37eda14cbcSMatt Macy void (*tp_func)(void *); /* Registered function */ 38eda14cbcSMatt Macy void *tp_args; /* Args to be passed to function */ 39eda14cbcSMatt Macy size_t tp_len; /* Len to be passed to function */ 40eda14cbcSMatt Macy int tp_state; /* State to start thread at */ 41eda14cbcSMatt Macy pri_t tp_pri; /* Priority to start threat at */ 42eda14cbcSMatt Macy } thread_priv_t; 43eda14cbcSMatt Macy 44eda14cbcSMatt Macy static int 45eda14cbcSMatt Macy thread_generic_wrapper(void *arg) 46eda14cbcSMatt Macy { 47eda14cbcSMatt Macy thread_priv_t *tp = (thread_priv_t *)arg; 48eda14cbcSMatt Macy void (*func)(void *); 49eda14cbcSMatt Macy void *args; 50eda14cbcSMatt Macy 51eda14cbcSMatt Macy ASSERT(tp->tp_magic == TP_MAGIC); 52eda14cbcSMatt Macy func = tp->tp_func; 53eda14cbcSMatt Macy args = tp->tp_args; 54eda14cbcSMatt Macy set_current_state(tp->tp_state); 55eda14cbcSMatt Macy set_user_nice((kthread_t *)current, PRIO_TO_NICE(tp->tp_pri)); 56eda14cbcSMatt Macy kmem_free(tp->tp_name, tp->tp_name_size); 57eda14cbcSMatt Macy kmem_free(tp, sizeof (thread_priv_t)); 58eda14cbcSMatt Macy 59eda14cbcSMatt Macy if (func) 60eda14cbcSMatt Macy func(args); 61eda14cbcSMatt Macy 62eda14cbcSMatt Macy return (0); 63eda14cbcSMatt Macy } 64eda14cbcSMatt Macy 65eda14cbcSMatt Macy /* 66eda14cbcSMatt Macy * thread_create() may block forever if it cannot create a thread or 67eda14cbcSMatt Macy * allocate memory. This is preferable to returning a NULL which Solaris 68eda14cbcSMatt Macy * style callers likely never check for... since it can't fail. 69eda14cbcSMatt Macy */ 70eda14cbcSMatt Macy kthread_t * 71eda14cbcSMatt Macy __thread_create(caddr_t stk, size_t stksize, thread_func_t func, 72eda14cbcSMatt Macy const char *name, void *args, size_t len, proc_t *pp, int state, pri_t pri) 73eda14cbcSMatt Macy { 74eda14cbcSMatt Macy thread_priv_t *tp; 75eda14cbcSMatt Macy struct task_struct *tsk; 76eda14cbcSMatt Macy char *p; 77eda14cbcSMatt Macy 78eda14cbcSMatt Macy /* Option pp is simply ignored */ 79eda14cbcSMatt Macy /* Variable stack size unsupported */ 80eda14cbcSMatt Macy ASSERT(stk == NULL); 81eda14cbcSMatt Macy 82eda14cbcSMatt Macy tp = kmem_alloc(sizeof (thread_priv_t), KM_PUSHPAGE); 83eda14cbcSMatt Macy if (tp == NULL) 84eda14cbcSMatt Macy return (NULL); 85eda14cbcSMatt Macy 86eda14cbcSMatt Macy tp->tp_magic = TP_MAGIC; 87eda14cbcSMatt Macy tp->tp_name_size = strlen(name) + 1; 88eda14cbcSMatt Macy 89eda14cbcSMatt Macy tp->tp_name = kmem_alloc(tp->tp_name_size, KM_PUSHPAGE); 90eda14cbcSMatt Macy if (tp->tp_name == NULL) { 91eda14cbcSMatt Macy kmem_free(tp, sizeof (thread_priv_t)); 92eda14cbcSMatt Macy return (NULL); 93eda14cbcSMatt Macy } 94eda14cbcSMatt Macy 95be181ee2SMartin Matuska strlcpy(tp->tp_name, name, tp->tp_name_size); 96eda14cbcSMatt Macy 97eda14cbcSMatt Macy /* 98eda14cbcSMatt Macy * Strip trailing "_thread" from passed name which will be the func 99eda14cbcSMatt Macy * name since the exposed API has no parameter for passing a name. 100eda14cbcSMatt Macy */ 101eda14cbcSMatt Macy p = strstr(tp->tp_name, "_thread"); 102eda14cbcSMatt Macy if (p) 103eda14cbcSMatt Macy p[0] = '\0'; 104eda14cbcSMatt Macy 105eda14cbcSMatt Macy tp->tp_func = func; 106eda14cbcSMatt Macy tp->tp_args = args; 107eda14cbcSMatt Macy tp->tp_len = len; 108eda14cbcSMatt Macy tp->tp_state = state; 109eda14cbcSMatt Macy tp->tp_pri = pri; 110eda14cbcSMatt Macy 111eda14cbcSMatt Macy tsk = spl_kthread_create(thread_generic_wrapper, (void *)tp, 112eda14cbcSMatt Macy "%s", tp->tp_name); 113eda14cbcSMatt Macy if (IS_ERR(tsk)) 114eda14cbcSMatt Macy return (NULL); 115eda14cbcSMatt Macy 116eda14cbcSMatt Macy wake_up_process(tsk); 117eda14cbcSMatt Macy return ((kthread_t *)tsk); 118eda14cbcSMatt Macy } 119eda14cbcSMatt Macy EXPORT_SYMBOL(__thread_create); 120eda14cbcSMatt Macy 121eda14cbcSMatt Macy /* 122eda14cbcSMatt Macy * spl_kthread_create - Wrapper providing pre-3.13 semantics for 123eda14cbcSMatt Macy * kthread_create() in which it is not killable and less likely 124eda14cbcSMatt Macy * to return -ENOMEM. 125eda14cbcSMatt Macy */ 126eda14cbcSMatt Macy struct task_struct * 127eda14cbcSMatt Macy spl_kthread_create(int (*func)(void *), void *data, const char namefmt[], ...) 128eda14cbcSMatt Macy { 129eda14cbcSMatt Macy struct task_struct *tsk; 130eda14cbcSMatt Macy va_list args; 131eda14cbcSMatt Macy char name[TASK_COMM_LEN]; 132eda14cbcSMatt Macy 133eda14cbcSMatt Macy va_start(args, namefmt); 134eda14cbcSMatt Macy vsnprintf(name, sizeof (name), namefmt, args); 135eda14cbcSMatt Macy va_end(args); 136eda14cbcSMatt Macy do { 137eda14cbcSMatt Macy tsk = kthread_create(func, data, "%s", name); 138eda14cbcSMatt Macy if (IS_ERR(tsk)) { 139eda14cbcSMatt Macy if (signal_pending(current)) { 140eda14cbcSMatt Macy clear_thread_flag(TIF_SIGPENDING); 141eda14cbcSMatt Macy continue; 142eda14cbcSMatt Macy } 143eda14cbcSMatt Macy if (PTR_ERR(tsk) == -ENOMEM) 144eda14cbcSMatt Macy continue; 145eda14cbcSMatt Macy return (NULL); 146eda14cbcSMatt Macy } else { 147eda14cbcSMatt Macy return (tsk); 148eda14cbcSMatt Macy } 149eda14cbcSMatt Macy } while (1); 150eda14cbcSMatt Macy } 151eda14cbcSMatt Macy EXPORT_SYMBOL(spl_kthread_create); 15216038816SMartin Matuska 15316038816SMartin Matuska /* 15416038816SMartin Matuska * The "why" argument indicates the allowable side-effects of the call: 15516038816SMartin Matuska * 15616038816SMartin Matuska * FORREAL: Extract the next pending signal from p_sig into p_cursig; 15716038816SMartin Matuska * stop the process if a stop has been requested or if a traced signal 15816038816SMartin Matuska * is pending. 15916038816SMartin Matuska * 16016038816SMartin Matuska * JUSTLOOKING: Don't stop the process, just indicate whether or not 16116038816SMartin Matuska * a signal might be pending (FORREAL is needed to tell for sure). 16216038816SMartin Matuska */ 16316038816SMartin Matuska int 16416038816SMartin Matuska issig(int why) 16516038816SMartin Matuska { 16616038816SMartin Matuska ASSERT(why == FORREAL || why == JUSTLOOKING); 16716038816SMartin Matuska 16816038816SMartin Matuska if (!signal_pending(current)) 16916038816SMartin Matuska return (0); 17016038816SMartin Matuska 17116038816SMartin Matuska if (why != FORREAL) 17216038816SMartin Matuska return (1); 17316038816SMartin Matuska 17416038816SMartin Matuska struct task_struct *task = current; 17516038816SMartin Matuska spl_kernel_siginfo_t __info; 17616038816SMartin Matuska sigset_t set; 17716038816SMartin Matuska siginitsetinv(&set, 1ULL << (SIGSTOP - 1) | 1ULL << (SIGTSTP - 1)); 17816038816SMartin Matuska sigorsets(&set, &task->blocked, &set); 17916038816SMartin Matuska 18016038816SMartin Matuska spin_lock_irq(&task->sighand->siglock); 181c03c5b1cSMartin Matuska #ifdef HAVE_DEQUEUE_SIGNAL_4ARG 182c03c5b1cSMartin Matuska enum pid_type __type; 183*15f0b8c3SMartin Matuska if (dequeue_signal(task, &set, &__info, &__type) != 0) { 184c03c5b1cSMartin Matuska #else 185*15f0b8c3SMartin Matuska if (dequeue_signal(task, &set, &__info) != 0) { 186c03c5b1cSMartin Matuska #endif 18716038816SMartin Matuska #ifdef HAVE_SIGNAL_STOP 18816038816SMartin Matuska spin_unlock_irq(&task->sighand->siglock); 18916038816SMartin Matuska kernel_signal_stop(); 19016038816SMartin Matuska #else 19116038816SMartin Matuska if (current->jobctl & JOBCTL_STOP_DEQUEUED) 19216038816SMartin Matuska spl_set_special_state(TASK_STOPPED); 19316038816SMartin Matuska 19416038816SMartin Matuska spin_unlock_irq(¤t->sighand->siglock); 19516038816SMartin Matuska 19616038816SMartin Matuska schedule(); 19716038816SMartin Matuska #endif 19816038816SMartin Matuska return (0); 19916038816SMartin Matuska } 20016038816SMartin Matuska 20116038816SMartin Matuska spin_unlock_irq(&task->sighand->siglock); 20216038816SMartin Matuska 20316038816SMartin Matuska return (1); 20416038816SMartin Matuska } 20516038816SMartin Matuska 20616038816SMartin Matuska EXPORT_SYMBOL(issig); 207