Print this page
8158 Want named threads API
9857 proc manpages should have LIBRARY section

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/disp/thread.c
          +++ new/usr/src/uts/common/disp/thread.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
  24      - * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
       24 + * Copyright (c) 2018 Joyent, Inc.
  25   25   */
  26   26  
  27   27  #include <sys/types.h>
  28   28  #include <sys/param.h>
  29   29  #include <sys/sysmacros.h>
  30   30  #include <sys/signal.h>
  31   31  #include <sys/stack.h>
  32   32  #include <sys/pcb.h>
  33   33  #include <sys/user.h>
  34   34  #include <sys/systm.h>
↓ open down ↓ 32 lines elided ↑ open up ↑
  67   67  #include <sys/tsol/label.h>
  68   68  #include <sys/tsol/tndb.h>
  69   69  #include <sys/cpc_impl.h>
  70   70  #include <sys/sdt.h>
  71   71  #include <sys/reboot.h>
  72   72  #include <sys/kdi.h>
  73   73  #include <sys/schedctl.h>
  74   74  #include <sys/waitq.h>
  75   75  #include <sys/cpucaps.h>
  76   76  #include <sys/kiconv.h>
       77 +#include <sys/ctype.h>
  77   78  
  78   79  struct kmem_cache *thread_cache;        /* cache of free threads */
  79   80  struct kmem_cache *lwp_cache;           /* cache of free lwps */
  80   81  struct kmem_cache *turnstile_cache;     /* cache of free turnstiles */
  81   82  
  82   83  /*
  83   84   * allthreads is only for use by kmem_readers.  All kernel loops can use
  84   85   * the current thread as a start/end point.
  85   86   */
  86   87  kthread_t *allthreads = &t0;    /* circular list of all threads */
↓ open down ↓ 697 lines elided ↑ open up ↑
 784  785  
 785  786          ASSERT(ttoproj(t) == proj0p);
 786  787          project_rele(ttoproj(t));
 787  788  
 788  789          lgrp_affinity_free(&t->t_lgrp_affinity);
 789  790  
 790  791          mutex_enter(&pidlock);
 791  792          nthread--;
 792  793          mutex_exit(&pidlock);
 793  794  
      795 +        if (t->t_name != NULL) {
      796 +                kmem_free(t->t_name, THREAD_NAME_MAX);
      797 +                t->t_name = NULL;
      798 +        }
      799 +
 794  800          /*
 795  801           * Free thread, lwp and stack.  This needs to be done carefully, since
 796  802           * if T_TALLOCSTK is set, the thread is part of the stack.
 797  803           */
 798  804          t->t_lwp = NULL;
 799  805          t->t_swap = NULL;
 800  806  
 801  807          if (swap) {
 802  808                  segkp_release(segkp, swap);
 803  809          }
↓ open down ↓ 1315 lines elided ↑ open up ↑
2119 2125                          return (100);
2120 2126                  }
2121 2127                  percent = sp - t_stk + 1;
2122 2128                  s = t_stkbase - t_stk + 1;
2123 2129          }
2124 2130          percent = ((100 * percent) / s) + 1;
2125 2131          if (percent > 100) {
2126 2132                  percent = 100;
2127 2133          }
2128 2134          return (percent);
     2135 +}
     2136 +
     2137 +/*
     2138 + * NOTE: This will silently truncate a name > THREAD_NAME_MAX - 1 characters
     2139 + * long.  It is expected that callers (acting on behalf of userland clients)
     2140 + * will perform any required checks to return the correct error semantics.
     2141 + * It is also expected callers on behalf of userland clients have done
     2142 + * any necessary permission checks.
     2143 + */
     2144 +int
     2145 +thread_setname(kthread_t *t, const char *name)
     2146 +{
     2147 +        char *buf = NULL;
     2148 +
     2149 +        /*
     2150 +         * We optimistically assume that a thread's name will only be set
     2151 +         * once and so allocate memory in preparation of setting t_name.
     2152 +         * If it turns out a name has already been set, we just discard (free)
     2153 +         * the buffer we just allocated and reuse the current buffer
     2154 +         * (as all should be THREAD_NAME_MAX large).
     2155 +         *
     2156 +         * Such an arrangement means over the lifetime of a kthread_t, t_name
     2157 +         * is either NULL or has one value (the address of the buffer holding
     2158 +         * the current thread name).   The assumption is that most kthread_t
     2159 +         * instances will not have a name assigned, so dynamically allocating
     2160 +         * the memory should minimize the footprint of this feature, but by
     2161 +         * having the buffer persist for the life of the thread, it simplifies
     2162 +         * usage in highly constrained situations (e.g. dtrace).
     2163 +         */
     2164 +        if (name != NULL && name[0] != '\0') {
     2165 +                for (size_t i = 0; name[i] != '\0'; i++) {
     2166 +                        if (!isprint(name[i]))
     2167 +                                return (EINVAL);
     2168 +                }
     2169 +
     2170 +                buf = kmem_zalloc(THREAD_NAME_MAX, KM_SLEEP);
     2171 +                (void) strlcpy(buf, name, THREAD_NAME_MAX);
     2172 +        }
     2173 +
     2174 +        mutex_enter(&ttoproc(t)->p_lock);
     2175 +        if (t->t_name == NULL) {
     2176 +                t->t_name = buf;
     2177 +        } else {
     2178 +                if (buf != NULL) {
     2179 +                        (void) strlcpy(t->t_name, name, THREAD_NAME_MAX);
     2180 +                        kmem_free(buf, THREAD_NAME_MAX);
     2181 +                } else {
     2182 +                        bzero(t->t_name, THREAD_NAME_MAX);
     2183 +                }
     2184 +        }
     2185 +        mutex_exit(&ttoproc(t)->p_lock);
     2186 +        return (0);
     2187 +}
     2188 +
     2189 +int
     2190 +thread_vsetname(kthread_t *t, const char *fmt, ...)
     2191 +{
     2192 +        char name[THREAD_NAME_MAX];
     2193 +        va_list va;
     2194 +        int rc;
     2195 +
     2196 +        va_start(va, fmt);
     2197 +        rc = vsnprintf(name, sizeof (name), fmt, va);
     2198 +        va_end(va);
     2199 +
     2200 +        if (rc < 0)
     2201 +                return (EINVAL);
     2202 +
     2203 +        if (rc >= sizeof (name))
     2204 +                return (ENAMETOOLONG);
     2205 +
     2206 +        return (thread_setname(t, name));
2129 2207  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX