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> 29fd45b686SMartin Matuska #include <sys/string.h> 30eda14cbcSMatt Macy 31eda14cbcSMatt Macy /* 32eda14cbcSMatt Macy * Thread interfaces 33eda14cbcSMatt Macy */ 34eda14cbcSMatt Macy typedef struct thread_priv_s { 35eda14cbcSMatt Macy unsigned long tp_magic; /* Magic */ 36eda14cbcSMatt Macy int tp_name_size; /* Name size */ 37eda14cbcSMatt Macy char *tp_name; /* Name (without _thread suffix) */ 38eda14cbcSMatt Macy void (*tp_func)(void *); /* Registered function */ 39eda14cbcSMatt Macy void *tp_args; /* Args to be passed to function */ 40eda14cbcSMatt Macy size_t tp_len; /* Len to be passed to function */ 41eda14cbcSMatt Macy int tp_state; /* State to start thread at */ 42eda14cbcSMatt Macy pri_t tp_pri; /* Priority to start threat at */ 43eda14cbcSMatt Macy } thread_priv_t; 44eda14cbcSMatt Macy 45eda14cbcSMatt Macy static int 46eda14cbcSMatt Macy thread_generic_wrapper(void *arg) 47eda14cbcSMatt Macy { 48eda14cbcSMatt Macy thread_priv_t *tp = (thread_priv_t *)arg; 49eda14cbcSMatt Macy void (*func)(void *); 50eda14cbcSMatt Macy void *args; 51eda14cbcSMatt Macy 52eda14cbcSMatt Macy ASSERT(tp->tp_magic == TP_MAGIC); 53eda14cbcSMatt Macy func = tp->tp_func; 54eda14cbcSMatt Macy args = tp->tp_args; 55eda14cbcSMatt Macy set_current_state(tp->tp_state); 56eda14cbcSMatt Macy set_user_nice((kthread_t *)current, PRIO_TO_NICE(tp->tp_pri)); 57eda14cbcSMatt Macy kmem_free(tp->tp_name, tp->tp_name_size); 58eda14cbcSMatt Macy kmem_free(tp, sizeof (thread_priv_t)); 59eda14cbcSMatt Macy 60eda14cbcSMatt Macy if (func) 61eda14cbcSMatt Macy func(args); 62eda14cbcSMatt Macy 63eda14cbcSMatt Macy return (0); 64eda14cbcSMatt Macy } 65eda14cbcSMatt Macy 66eda14cbcSMatt Macy /* 67eda14cbcSMatt Macy * thread_create() may block forever if it cannot create a thread or 68eda14cbcSMatt Macy * allocate memory. This is preferable to returning a NULL which Solaris 69eda14cbcSMatt Macy * style callers likely never check for... since it can't fail. 70eda14cbcSMatt Macy */ 71eda14cbcSMatt Macy kthread_t * 72eda14cbcSMatt Macy __thread_create(caddr_t stk, size_t stksize, thread_func_t func, 73eda14cbcSMatt Macy const char *name, void *args, size_t len, proc_t *pp, int state, pri_t pri) 74eda14cbcSMatt Macy { 75eda14cbcSMatt Macy thread_priv_t *tp; 76eda14cbcSMatt Macy struct task_struct *tsk; 77eda14cbcSMatt Macy char *p; 78eda14cbcSMatt Macy 79eda14cbcSMatt Macy /* Option pp is simply ignored */ 80eda14cbcSMatt Macy /* Variable stack size unsupported */ 81eda14cbcSMatt Macy ASSERT(stk == NULL); 82eda14cbcSMatt Macy 83eda14cbcSMatt Macy tp = kmem_alloc(sizeof (thread_priv_t), KM_PUSHPAGE); 84eda14cbcSMatt Macy if (tp == NULL) 85eda14cbcSMatt Macy return (NULL); 86eda14cbcSMatt Macy 87eda14cbcSMatt Macy tp->tp_magic = TP_MAGIC; 88eda14cbcSMatt Macy tp->tp_name_size = strlen(name) + 1; 89eda14cbcSMatt Macy 90eda14cbcSMatt Macy tp->tp_name = kmem_alloc(tp->tp_name_size, KM_PUSHPAGE); 91eda14cbcSMatt Macy if (tp->tp_name == NULL) { 92eda14cbcSMatt Macy kmem_free(tp, sizeof (thread_priv_t)); 93eda14cbcSMatt Macy return (NULL); 94eda14cbcSMatt Macy } 95eda14cbcSMatt Macy 96be181ee2SMartin Matuska strlcpy(tp->tp_name, name, tp->tp_name_size); 97eda14cbcSMatt Macy 98eda14cbcSMatt Macy /* 99eda14cbcSMatt Macy * Strip trailing "_thread" from passed name which will be the func 100eda14cbcSMatt Macy * name since the exposed API has no parameter for passing a name. 101eda14cbcSMatt Macy */ 102eda14cbcSMatt Macy p = strstr(tp->tp_name, "_thread"); 103eda14cbcSMatt Macy if (p) 104eda14cbcSMatt Macy p[0] = '\0'; 105eda14cbcSMatt Macy 106eda14cbcSMatt Macy tp->tp_func = func; 107eda14cbcSMatt Macy tp->tp_args = args; 108eda14cbcSMatt Macy tp->tp_len = len; 109eda14cbcSMatt Macy tp->tp_state = state; 110eda14cbcSMatt Macy tp->tp_pri = pri; 111eda14cbcSMatt Macy 112eda14cbcSMatt Macy tsk = spl_kthread_create(thread_generic_wrapper, (void *)tp, 113eda14cbcSMatt Macy "%s", tp->tp_name); 114eda14cbcSMatt Macy if (IS_ERR(tsk)) 115eda14cbcSMatt Macy return (NULL); 116eda14cbcSMatt Macy 117eda14cbcSMatt Macy wake_up_process(tsk); 118eda14cbcSMatt Macy return ((kthread_t *)tsk); 119eda14cbcSMatt Macy } 120eda14cbcSMatt Macy EXPORT_SYMBOL(__thread_create); 121eda14cbcSMatt Macy 122eda14cbcSMatt Macy /* 123eda14cbcSMatt Macy * spl_kthread_create - Wrapper providing pre-3.13 semantics for 124eda14cbcSMatt Macy * kthread_create() in which it is not killable and less likely 125eda14cbcSMatt Macy * to return -ENOMEM. 126eda14cbcSMatt Macy */ 127eda14cbcSMatt Macy struct task_struct * 128eda14cbcSMatt Macy spl_kthread_create(int (*func)(void *), void *data, const char namefmt[], ...) 129eda14cbcSMatt Macy { 130eda14cbcSMatt Macy struct task_struct *tsk; 131eda14cbcSMatt Macy va_list args; 132eda14cbcSMatt Macy char name[TASK_COMM_LEN]; 133eda14cbcSMatt Macy 134eda14cbcSMatt Macy va_start(args, namefmt); 135eda14cbcSMatt Macy vsnprintf(name, sizeof (name), namefmt, args); 136eda14cbcSMatt Macy va_end(args); 137eda14cbcSMatt Macy do { 138eda14cbcSMatt Macy tsk = kthread_create(func, data, "%s", name); 139eda14cbcSMatt Macy if (IS_ERR(tsk)) { 140eda14cbcSMatt Macy if (signal_pending(current)) { 141eda14cbcSMatt Macy clear_thread_flag(TIF_SIGPENDING); 142eda14cbcSMatt Macy continue; 143eda14cbcSMatt Macy } 144eda14cbcSMatt Macy if (PTR_ERR(tsk) == -ENOMEM) 145eda14cbcSMatt Macy continue; 146eda14cbcSMatt Macy return (NULL); 147eda14cbcSMatt Macy } else { 148eda14cbcSMatt Macy return (tsk); 149eda14cbcSMatt Macy } 150eda14cbcSMatt Macy } while (1); 151eda14cbcSMatt Macy } 152eda14cbcSMatt Macy EXPORT_SYMBOL(spl_kthread_create); 15316038816SMartin Matuska 15416038816SMartin Matuska /* 155aca928a5SMartin Matuska * Extract the next pending signal from p_sig into p_cursig; stop the process 156aca928a5SMartin Matuska * if a stop has been requested or if a traced signal is pending. 15716038816SMartin Matuska */ 15816038816SMartin Matuska int 159aca928a5SMartin Matuska issig(void) 16016038816SMartin Matuska { 16116038816SMartin Matuska 16216038816SMartin Matuska if (!signal_pending(current)) 16316038816SMartin Matuska return (0); 16416038816SMartin Matuska 16516038816SMartin Matuska spl_kernel_siginfo_t __info; 16616038816SMartin Matuska sigset_t set; 16716038816SMartin Matuska siginitsetinv(&set, 1ULL << (SIGSTOP - 1) | 1ULL << (SIGTSTP - 1)); 1687a7741afSMartin Matuska sigorsets(&set, ¤t->blocked, &set); 16916038816SMartin Matuska 1707a7741afSMartin Matuska spin_lock_irq(¤t->sighand->siglock); 1717a7741afSMartin Matuska #if defined(HAVE_DEQUEUE_SIGNAL_4ARG) 172c03c5b1cSMartin Matuska enum pid_type __type; 1737a7741afSMartin Matuska if (dequeue_signal(current, &set, &__info, &__type) != 0) { 174*5c65a0a9SMartin Matuska #elif defined(HAVE_DEQUEUE_SIGNAL_3ARG_TYPE) 1757a7741afSMartin Matuska enum pid_type __type; 1767a7741afSMartin Matuska if (dequeue_signal(&set, &__info, &__type) != 0) { 177*5c65a0a9SMartin Matuska #else 178*5c65a0a9SMartin Matuska if (dequeue_signal(current, &set, &__info) != 0) { 179c03c5b1cSMartin Matuska #endif 18016038816SMartin Matuska spin_unlock_irq(¤t->sighand->siglock); 1817a7741afSMartin Matuska kernel_signal_stop(); 18216038816SMartin Matuska 183e2df9bb4SMartin Matuska /* 184e2df9bb4SMartin Matuska * Dequeued SIGSTOP/SIGTSTP. 185e2df9bb4SMartin Matuska * Check if process has other singal pending. 186e2df9bb4SMartin Matuska */ 187e2df9bb4SMartin Matuska if (signal_pending(current)) 188e2df9bb4SMartin Matuska return (1); 189e2df9bb4SMartin Matuska 19016038816SMartin Matuska return (0); 19116038816SMartin Matuska } 19216038816SMartin Matuska 1937a7741afSMartin Matuska spin_unlock_irq(¤t->sighand->siglock); 19416038816SMartin Matuska 19516038816SMartin Matuska return (1); 19616038816SMartin Matuska } 19716038816SMartin Matuska 19816038816SMartin Matuska EXPORT_SYMBOL(issig); 199