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 }