1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2016 Joyent, Inc.
  14  */
  15 
  16 /*
  17  * Test and verify that pthrad_attr_get_np works as we expect.
  18  *
  19  * Verify the following:
  20  *   o ESRCH
  21  *   o stack size is set to a valid value after a thread is created.
  22  *   o main thread can grab an alternate thread's info.
  23  *   o custom guard size is honored
  24  *   o detach state
  25  *      - detached      1
  26  *      - joinable              2
  27  *      - changing              2
  28  *   o daemon state
  29  *      - enabled       1
  30  *      - disabled              2
  31  *   o scope
  32  *      - system        1
  33  *      - process               2
  34  *   o inheritable
  35  *      - inherit       1
  36  *      - explicit              2
  37  *   o priority
  38  *      - honors change         2
  39  *   o policy
  40  *      - honours change        2
  41  *
  42  *
  43  * For each of the cases above we explicitly go through and create the set of
  44  * attributes as marked above and then inside of a thread, verify that the
  45  * attributes match what we expect. Because each case ends up in creating a
  46  * detached thread, we opt to have both it and the main thread enter a barrier
  47  * to indicate that we have completed the test successfully.
  48  */
  49 
  50 #include <errno.h>
  51 #include <limits.h>
  52 #include <stdio.h>
  53 #include <pthread.h>
  54 #include <unistd.h>
  55 #include <ucontext.h>
  56 #include <sched.h>
  57 #include <strings.h>
  58 #include <stdlib.h>
  59 
  60 #include <sys/procfs.h>
  61 #include <sys/debug.h>
  62 
  63 /*
  64  * Currently these are only defined in thr_uberdata.h. Rather than trying and
  65  * fight with libc headers, just explicitly define them here.
  66  */
  67 #define PTHREAD_CREATE_DAEMON_NP        0x100   /* = THR_DAEMON */
  68 #define PTHREAD_CREATE_NONDAEMON_NP     0
  69 extern  int     pthread_attr_setdaemonstate_np(pthread_attr_t *, int);
  70 extern  int     pthread_attr_getdaemonstate_np(const pthread_attr_t *, int *);
  71 
  72 #define PGN_TEST_PRI    23
  73 
  74 static pthread_attr_t pgn_attr;
  75 static pthread_attr_t pgn_thr_attr;
  76 static pthread_barrier_t pgn_barrier;
  77 
  78 #ifdef  __sparc
  79 #define gregs   __gregs
  80 #endif
  81 
  82 /*
  83  * Verify that the stack pointer of a context is consistent with where the
  84  * attributes indicate.
  85  */
  86 static void
  87 pgn_verif_thr_stack(pthread_attr_t *attr)
  88 {
  89         size_t stksz;
  90         void *stk;
  91         ucontext_t ctx;
  92         uint32_t sp;
  93 
  94         VERIFY0(getcontext(&ctx));
  95         VERIFY0(pthread_attr_getstack(attr, &stk, &stksz));
  96         VERIFY3P(stk, !=, NULL);
  97         VERIFY3S(stksz, !=, 0);
  98         sp = ctx.uc_mcontext.gregs[R_SP];
  99         VERIFY3U(sp, >, (uintptr_t)stk);
 100         VERIFY3U(sp, <, (uintptr_t)stk + stksz);
 101 }
 102 
 103 #ifdef  __sparc
 104 #undef  gregs
 105 #endif
 106 
 107 static void
 108 pgn_test_fini(void)
 109 {
 110         int ret;
 111 
 112         ret = pthread_barrier_wait(&pgn_barrier);
 113         VERIFY(ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD);
 114         VERIFY0(pthread_attr_destroy(&pgn_attr));
 115         VERIFY0(pthread_attr_destroy(&pgn_thr_attr));
 116         VERIFY0(pthread_barrier_destroy(&pgn_barrier));
 117 }
 118 
 119 static void
 120 pgn_test_init(void)
 121 {
 122         VERIFY0(pthread_attr_init(&pgn_attr));
 123         VERIFY0(pthread_attr_init(&pgn_thr_attr));
 124         VERIFY0(pthread_barrier_init(&pgn_barrier, NULL, 2));
 125 }
 126 
 127 /* ARGSUSED */
 128 static void *
 129 pgn_set_one_thr(void *arg)
 130 {
 131         int odetach, ndetach;
 132         int odaemon, ndaemon;
 133         int oscope, nscope;
 134         int oinherit, ninherit;
 135 
 136         VERIFY0(pthread_attr_get_np(pthread_self(), &pgn_attr));
 137         pgn_verif_thr_stack(&pgn_attr);
 138 
 139         VERIFY0(pthread_attr_getdetachstate(&pgn_thr_attr, &odetach));
 140         VERIFY0(pthread_attr_getdetachstate(&pgn_attr, &ndetach));
 141 
 142         VERIFY3S(odetach, ==, ndetach);
 143         VERIFY3S(ndetach, ==, PTHREAD_CREATE_DETACHED);
 144 
 145         VERIFY0(pthread_attr_getdaemonstate_np(&pgn_thr_attr, &odaemon));
 146         VERIFY0(pthread_attr_getdaemonstate_np(&pgn_attr, &ndaemon));
 147 
 148         VERIFY3S(odaemon, ==, ndaemon);
 149         VERIFY3S(ndaemon, ==, PTHREAD_CREATE_DAEMON_NP);
 150 
 151         VERIFY0(pthread_attr_getscope(&pgn_thr_attr, &oscope));
 152         VERIFY0(pthread_attr_getscope(&pgn_attr, &nscope));
 153 
 154         VERIFY3S(oscope, ==, nscope);
 155         VERIFY3S(nscope, ==, PTHREAD_SCOPE_SYSTEM);
 156 
 157         VERIFY0(pthread_attr_getinheritsched(&pgn_thr_attr, &oinherit));
 158         VERIFY0(pthread_attr_getinheritsched(&pgn_attr, &ninherit));
 159 
 160         VERIFY3S(oinherit, ==, ninherit);
 161         VERIFY3S(ninherit, ==, PTHREAD_INHERIT_SCHED);
 162 
 163         VERIFY3S(pthread_barrier_wait(&pgn_barrier), !=, 1);
 164         return (NULL);
 165 }
 166 
 167 static void
 168 pgn_set_one(void)
 169 {
 170         int ret;
 171         pthread_t thr;
 172 
 173         pgn_test_init();
 174 
 175         VERIFY0(pthread_attr_setdetachstate(&pgn_thr_attr,
 176             PTHREAD_CREATE_DETACHED));
 177         VERIFY0(pthread_attr_setdaemonstate_np(&pgn_thr_attr,
 178             PTHREAD_CREATE_DAEMON_NP));
 179         VERIFY0(pthread_attr_setscope(&pgn_thr_attr, PTHREAD_SCOPE_SYSTEM));
 180         VERIFY0(pthread_attr_setinheritsched(&pgn_thr_attr,
 181             PTHREAD_INHERIT_SCHED));
 182 
 183         VERIFY0(pthread_create(&thr, &pgn_thr_attr, pgn_set_one_thr, NULL));
 184 
 185         /*
 186          * Verify it's not joinable.
 187          */
 188         ret = pthread_join(thr, NULL);
 189         VERIFY3S(ret, ==, EINVAL);
 190 
 191         /*
 192          * At this point we let the test continue and wait on the barrier. We'll
 193          * wake up when the other thread is done.
 194          */
 195         pgn_test_fini();
 196 }
 197 
 198 /* ARGSUSED */
 199 static void *
 200 pgn_set_two_thr(void *arg)
 201 {
 202         int odetach, ndetach;
 203         int odaemon, ndaemon;
 204         int oscope, nscope;
 205         int oinherit, ninherit;
 206         int opolicy, npolicy;
 207         struct sched_param oparam, nparam;
 208 
 209         VERIFY0(pthread_attr_get_np(pthread_self(), &pgn_attr));
 210         pgn_verif_thr_stack(&pgn_attr);
 211 
 212         VERIFY0(pthread_attr_getdetachstate(&pgn_thr_attr, &odetach));
 213         VERIFY0(pthread_attr_getdetachstate(&pgn_attr, &ndetach));
 214 
 215         VERIFY3S(odetach, ==, ndetach);
 216         VERIFY3S(ndetach, ==, PTHREAD_CREATE_JOINABLE);
 217 
 218         VERIFY0(pthread_attr_getdaemonstate_np(&pgn_thr_attr, &odaemon));
 219         VERIFY0(pthread_attr_getdaemonstate_np(&pgn_attr, &ndaemon));
 220 
 221         VERIFY3S(odaemon, ==, ndaemon);
 222         VERIFY3S(ndaemon, ==, PTHREAD_CREATE_NONDAEMON_NP);
 223 
 224         VERIFY0(pthread_attr_getscope(&pgn_thr_attr, &oscope));
 225         VERIFY0(pthread_attr_getscope(&pgn_attr, &nscope));
 226 
 227         VERIFY3S(oscope, ==, nscope);
 228         VERIFY3S(nscope, ==, PTHREAD_SCOPE_PROCESS);
 229 
 230         VERIFY0(pthread_attr_getinheritsched(&pgn_thr_attr, &oinherit));
 231         VERIFY0(pthread_attr_getinheritsched(&pgn_attr, &ninherit));
 232 
 233         VERIFY3S(oinherit, ==, ninherit);
 234         VERIFY3S(ninherit, ==, PTHREAD_EXPLICIT_SCHED);
 235 
 236         VERIFY0(pthread_attr_getschedpolicy(&pgn_thr_attr, &opolicy));
 237         VERIFY0(pthread_attr_getschedpolicy(&pgn_attr, &npolicy));
 238 
 239         VERIFY3S(opolicy, ==, npolicy);
 240         VERIFY3S(npolicy, ==, SCHED_FSS);
 241 
 242         /*
 243          * Now that we've validated the basics, go ahead and test the changes,
 244          * which include making sure that we see updates via
 245          * pthread_setschedparam() and pthread_detach().
 246          */
 247         VERIFY0(pthread_detach(pthread_self()));
 248 
 249         opolicy = SCHED_FX;
 250         oparam.sched_priority = PGN_TEST_PRI;
 251         VERIFY0(pthread_setschedparam(pthread_self(), opolicy, &oparam));
 252 
 253         VERIFY0(pthread_attr_get_np(pthread_self(), &pgn_attr));
 254         VERIFY0(pthread_attr_getdetachstate(&pgn_attr, &ndetach));
 255 
 256         VERIFY3S(odetach, !=, ndetach);
 257         VERIFY3S(ndetach, ==, PTHREAD_CREATE_DETACHED);
 258 
 259         VERIFY0(pthread_attr_getschedpolicy(&pgn_attr, &npolicy));
 260         VERIFY0(pthread_attr_getschedparam(&pgn_attr, &nparam));
 261 
 262         VERIFY3S(opolicy, ==, npolicy);
 263         VERIFY3S(npolicy, ==, SCHED_FX);
 264 
 265         VERIFY3S(oparam.sched_priority, ==, nparam.sched_priority);
 266         VERIFY3S(nparam.sched_priority, ==, PGN_TEST_PRI);
 267 
 268         VERIFY3S(pthread_barrier_wait(&pgn_barrier), !=, 1);
 269 
 270         return (NULL);
 271 }
 272 
 273 static void
 274 pgn_set_two(void)
 275 {
 276         pthread_t thr;
 277 
 278         pgn_test_init();
 279 
 280         VERIFY0(pthread_attr_setdetachstate(&pgn_thr_attr,
 281             PTHREAD_CREATE_JOINABLE));
 282         VERIFY0(pthread_attr_setdaemonstate_np(&pgn_thr_attr,
 283             PTHREAD_CREATE_NONDAEMON_NP));
 284         VERIFY0(pthread_attr_setscope(&pgn_thr_attr, PTHREAD_SCOPE_PROCESS));
 285         VERIFY0(pthread_attr_setinheritsched(&pgn_thr_attr,
 286             PTHREAD_EXPLICIT_SCHED));
 287         VERIFY0(pthread_attr_setschedpolicy(&pgn_thr_attr, SCHED_FSS));
 288 
 289         VERIFY0(pthread_create(&thr, &pgn_thr_attr, pgn_set_two_thr, NULL));
 290 
 291         /*
 292          * At this point we let the test continue and wait on the barrier. We'll
 293          * wake up when the other thread is done.
 294          */
 295         pgn_test_fini();
 296 }
 297 
 298 /* ARGSUSED */
 299 static void *
 300 pgn_set_three_thr(void *arg)
 301 {
 302         VERIFY3S(pthread_barrier_wait(&pgn_barrier), !=, 1);
 303 
 304         return (NULL);
 305 }
 306 
 307 void
 308 pgn_set_three(void)
 309 {
 310         pthread_t thr;
 311         pthread_attr_t altattr, selfattr;
 312         void *altstk, *selfstk;
 313         size_t altsz, selfsz;
 314 
 315         VERIFY0(pthread_attr_init(&altattr));
 316         VERIFY0(pthread_attr_init(&selfattr));
 317         pgn_test_init();
 318 
 319         VERIFY0(pthread_create(&thr, NULL, pgn_set_three_thr, NULL));
 320 
 321         VERIFY0(pthread_attr_get_np(thr, &altattr));
 322         VERIFY0(pthread_attr_get_np(pthread_self(), &selfattr));
 323 
 324         VERIFY0(pthread_attr_getstack(&selfattr, &selfstk, &selfsz));
 325         VERIFY0(pthread_attr_getstack(&altattr, &altstk, &altsz));
 326         VERIFY3P(altstk, !=, selfstk);
 327 
 328         pgn_test_fini();
 329         VERIFY0(pthread_attr_destroy(&selfattr));
 330         VERIFY0(pthread_attr_destroy(&altattr));
 331 }
 332 
 333 int
 334 main(void)
 335 {
 336         int ret;
 337 
 338         VERIFY0(pthread_attr_init(&pgn_attr));
 339 
 340         ret = pthread_attr_get_np(UINT32_MAX, &pgn_attr);
 341         VERIFY3S(ret, ==, ESRCH);
 342 
 343         pgn_set_one();
 344         pgn_set_two();
 345         pgn_set_three();
 346 
 347         exit(0);
 348 }