The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/module/os/linux/spl/spl-thread.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 929ed26e95ac99416e2fc03142bf6d95


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.