1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "lint.h" 30 #include "thr_uberdata.h" 31 #include <sched.h> 32 33 /* 34 * Default attribute object for pthread_create() with NULL attr pointer. 35 * Note that the 'guardsize' field is initialized on the first call. 36 */ 37 const thrattr_t * 38 def_thrattr(void) 39 { 40 static thrattr_t thrattr = { 41 0, /* stksize */ 42 NULL, /* stkaddr */ 43 PTHREAD_CREATE_JOINABLE, /* detachstate */ 44 PTHREAD_CREATE_NONDAEMON_NP, /* daemonstate */ 45 PTHREAD_SCOPE_PROCESS, /* scope */ 46 0, /* prio */ 47 SCHED_OTHER, /* policy */ 48 PTHREAD_EXPLICIT_SCHED, /* inherit */ 49 0 /* guardsize */ 50 }; 51 if (thrattr.guardsize == 0) 52 thrattr.guardsize = _sysconf(_SC_PAGESIZE); 53 return (&thrattr); 54 } 55 56 /* 57 * pthread_attr_init: allocates the attribute object and initializes it 58 * with the default values. 59 */ 60 #pragma weak pthread_attr_init = _pthread_attr_init 61 int 62 _pthread_attr_init(pthread_attr_t *attr) 63 { 64 thrattr_t *ap; 65 66 if ((ap = lmalloc(sizeof (thrattr_t))) != NULL) { 67 *ap = *def_thrattr(); 68 attr->__pthread_attrp = ap; 69 return (0); 70 } 71 return (ENOMEM); 72 } 73 74 /* 75 * pthread_attr_destroy: frees the attribute object and invalidates it 76 * with NULL value. 77 */ 78 #pragma weak pthread_attr_destroy = _pthread_attr_destroy 79 int 80 _pthread_attr_destroy(pthread_attr_t *attr) 81 { 82 if (attr == NULL || attr->__pthread_attrp == NULL) 83 return (EINVAL); 84 lfree(attr->__pthread_attrp, sizeof (thrattr_t)); 85 attr->__pthread_attrp = NULL; 86 return (0); 87 } 88 89 /* 90 * _pthread_attr_clone: make a copy of a pthread_attr_t. 91 */ 92 int 93 _pthread_attr_clone(pthread_attr_t *attr, const pthread_attr_t *old_attr) 94 { 95 thrattr_t *ap; 96 const thrattr_t *old_ap = 97 old_attr? old_attr->__pthread_attrp : def_thrattr(); 98 99 if (old_ap == NULL) 100 return (EINVAL); 101 if ((ap = lmalloc(sizeof (thrattr_t))) == NULL) 102 return (ENOMEM); 103 *ap = *old_ap; 104 attr->__pthread_attrp = ap; 105 return (0); 106 } 107 108 /* 109 * _pthread_attr_equal: compare two pthread_attr_t's, return 1 if equal. 110 * A NULL pthread_attr_t pointer implies default attributes. 111 * This is a consolidation-private interface, for librt. 112 */ 113 int 114 _pthread_attr_equal(const pthread_attr_t *attr1, const pthread_attr_t *attr2) 115 { 116 const thrattr_t *ap1 = attr1? attr1->__pthread_attrp : def_thrattr(); 117 const thrattr_t *ap2 = attr2? attr2->__pthread_attrp : def_thrattr(); 118 119 if (ap1 == NULL || ap2 == NULL) 120 return (0); 121 return (ap1 == ap2 || _memcmp(ap1, ap2, sizeof (thrattr_t)) == 0); 122 } 123 124 /* 125 * pthread_attr_setstacksize: sets the user stack size, minimum should 126 * be PTHREAD_STACK_MIN (MINSTACK). 127 * This is equivalent to stksize argument in thr_create(). 128 */ 129 #pragma weak pthread_attr_setstacksize = _pthread_attr_setstacksize 130 int 131 _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) 132 { 133 thrattr_t *ap; 134 135 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 136 stacksize >= MINSTACK) { 137 ap->stksize = stacksize; 138 return (0); 139 } 140 return (EINVAL); 141 } 142 143 /* 144 * pthread_attr_getstacksize: gets the user stack size. 145 */ 146 #pragma weak pthread_attr_getstacksize = _pthread_attr_getstacksize 147 int 148 _pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) 149 { 150 thrattr_t *ap; 151 152 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 153 stacksize != NULL) { 154 *stacksize = ap->stksize; 155 return (0); 156 } 157 return (EINVAL); 158 } 159 160 /* 161 * pthread_attr_setstackaddr: sets the user stack addr. 162 * This is equivalent to stkaddr argument in thr_create(). 163 */ 164 #pragma weak pthread_attr_setstackaddr = _pthread_attr_setstackaddr 165 int 166 _pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) 167 { 168 thrattr_t *ap; 169 170 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL) { 171 ap->stkaddr = stackaddr; 172 return (0); 173 } 174 return (EINVAL); 175 } 176 177 /* 178 * pthread_attr_getstackaddr: gets the user stack addr. 179 */ 180 #pragma weak pthread_attr_getstackaddr = _pthread_attr_getstackaddr 181 int 182 _pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) 183 { 184 thrattr_t *ap; 185 186 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 187 stackaddr != NULL) { 188 *stackaddr = ap->stkaddr; 189 return (0); 190 } 191 return (EINVAL); 192 } 193 194 /* 195 * pthread_attr_setdetachstate: sets the detach state to DETACHED or JOINABLE. 196 * PTHREAD_CREATE_DETACHED is equivalent to thr_create(THR_DETACHED). 197 */ 198 #pragma weak pthread_attr_setdetachstate = _pthread_attr_setdetachstate 199 int 200 _pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 201 { 202 thrattr_t *ap; 203 204 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 205 (detachstate == PTHREAD_CREATE_DETACHED || 206 detachstate == PTHREAD_CREATE_JOINABLE)) { 207 ap->detachstate = detachstate; 208 return (0); 209 } 210 return (EINVAL); 211 } 212 213 /* 214 * pthread_attr_getdetachstate: gets the detach state. 215 */ 216 #pragma weak pthread_attr_getdetachstate = _pthread_attr_getdetachstate 217 int 218 _pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) 219 { 220 thrattr_t *ap; 221 222 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 223 detachstate != NULL) { 224 *detachstate = ap->detachstate; 225 return (0); 226 } 227 return (EINVAL); 228 } 229 230 /* 231 * pthread_attr_setdaemonstate_np: sets the daemon state to DAEMON or NONDAEMON. 232 * PTHREAD_CREATE_DAEMON is equivalent to thr_create(THR_DAEMON). 233 * For now, this is a private interface in libc. 234 */ 235 int 236 _pthread_attr_setdaemonstate_np(pthread_attr_t *attr, int daemonstate) 237 { 238 thrattr_t *ap; 239 240 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 241 (daemonstate == PTHREAD_CREATE_DAEMON_NP || 242 daemonstate == PTHREAD_CREATE_NONDAEMON_NP)) { 243 ap->daemonstate = daemonstate; 244 return (0); 245 } 246 return (EINVAL); 247 } 248 249 /* 250 * pthread_attr_getdaemonstate_np: gets the daemon state. 251 * For now, this is a private interface in libc. 252 */ 253 int 254 _pthread_attr_getdaemonstate_np(const pthread_attr_t *attr, int *daemonstate) 255 { 256 thrattr_t *ap; 257 258 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 259 daemonstate != NULL) { 260 *daemonstate = ap->daemonstate; 261 return (0); 262 } 263 return (EINVAL); 264 } 265 266 /* 267 * pthread_attr_setscope: sets the scope to SYSTEM or PROCESS. 268 * This is equivalent to setting THR_BOUND flag in thr_create(). 269 */ 270 #pragma weak pthread_attr_setscope = _pthread_attr_setscope 271 int 272 _pthread_attr_setscope(pthread_attr_t *attr, int scope) 273 { 274 thrattr_t *ap; 275 276 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 277 (scope == PTHREAD_SCOPE_SYSTEM || 278 scope == PTHREAD_SCOPE_PROCESS)) { 279 ap->scope = scope; 280 return (0); 281 } 282 return (EINVAL); 283 } 284 285 /* 286 * pthread_attr_getscope: gets the scheduling scope. 287 */ 288 #pragma weak pthread_attr_getscope = _pthread_attr_getscope 289 int 290 _pthread_attr_getscope(const pthread_attr_t *attr, int *scope) 291 { 292 thrattr_t *ap; 293 294 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 295 scope != NULL) { 296 *scope = ap->scope; 297 return (0); 298 } 299 return (EINVAL); 300 } 301 302 /* 303 * pthread_attr_setinheritsched: sets the scheduling parameters to be 304 * EXPLICIT or INHERITED from parent thread. 305 */ 306 #pragma weak pthread_attr_setinheritsched = _pthread_attr_setinheritsched 307 int 308 _pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) 309 { 310 thrattr_t *ap; 311 312 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 313 (inherit == PTHREAD_EXPLICIT_SCHED || 314 inherit == PTHREAD_INHERIT_SCHED)) { 315 ap->inherit = inherit; 316 return (0); 317 } 318 return (EINVAL); 319 } 320 321 /* 322 * pthread_attr_getinheritsched: gets the scheduling inheritance. 323 */ 324 #pragma weak pthread_attr_getinheritsched = _pthread_attr_getinheritsched 325 int 326 _pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) 327 { 328 thrattr_t *ap; 329 330 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 331 inherit != NULL) { 332 *inherit = ap->inherit; 333 return (0); 334 } 335 return (EINVAL); 336 } 337 338 /* 339 * pthread_attr_setschedpolicy: sets the scheduling policy to SCHED_RR, 340 * SCHED_FIFO or SCHED_OTHER. 341 */ 342 #pragma weak pthread_attr_setschedpolicy = _pthread_attr_setschedpolicy 343 int 344 _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) 345 { 346 thrattr_t *ap; 347 348 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 349 (policy == SCHED_OTHER || 350 policy == SCHED_FIFO || 351 policy == SCHED_RR)) { 352 ap->policy = policy; 353 return (0); 354 } 355 return (EINVAL); 356 } 357 358 /* 359 * pthread_attr_getpolicy: gets the scheduling policy. 360 */ 361 #pragma weak pthread_attr_getschedpolicy = _pthread_attr_getschedpolicy 362 int 363 _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) 364 { 365 thrattr_t *ap; 366 367 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 368 policy != NULL) { 369 *policy = ap->policy; 370 return (0); 371 } 372 return (EINVAL); 373 } 374 375 /* 376 * pthread_attr_setschedparam: sets the scheduling parameters. 377 * Currently, we support priority only. 378 */ 379 #pragma weak pthread_attr_setschedparam = _pthread_attr_setschedparam 380 int 381 _pthread_attr_setschedparam(pthread_attr_t *attr, 382 const struct sched_param *param) 383 { 384 thrattr_t *ap; 385 int policy; 386 int pri; 387 388 if (attr == NULL || (ap = attr->__pthread_attrp) == NULL) 389 return (EINVAL); 390 391 policy = ap->policy; 392 pri = param->sched_priority; 393 if (policy == SCHED_OTHER) { 394 if ((pri < THREAD_MIN_PRIORITY || pri > THREAD_MAX_PRIORITY) && 395 _validate_rt_prio(policy, pri)) 396 return (EINVAL); 397 } else if (_validate_rt_prio(policy, pri)) { 398 return (EINVAL); 399 } 400 ap->prio = pri; 401 return (0); 402 } 403 404 /* 405 * pthread_attr_getschedparam: gets the scheduling parameters. 406 * Currently, only priority is defined as sched parameter. 407 */ 408 #pragma weak pthread_attr_getschedparam = _pthread_attr_getschedparam 409 int 410 _pthread_attr_getschedparam(const pthread_attr_t *attr, 411 struct sched_param *param) 412 { 413 thrattr_t *ap; 414 415 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 416 param != NULL) { 417 param->sched_priority = ap->prio; 418 return (0); 419 } 420 return (EINVAL); 421 } 422 423 /* 424 * UNIX98 425 * pthread_attr_setguardsize: sets the guardsize 426 */ 427 #pragma weak pthread_attr_setguardsize = _pthread_attr_setguardsize 428 int 429 _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) 430 { 431 thrattr_t *ap; 432 433 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL) { 434 ap->guardsize = guardsize; 435 return (0); 436 } 437 return (EINVAL); 438 } 439 440 /* 441 * UNIX98 442 * pthread_attr_getguardsize: gets the guardsize 443 */ 444 #pragma weak pthread_attr_getguardsize = _pthread_attr_getguardsize 445 int 446 _pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) 447 { 448 thrattr_t *ap; 449 450 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 451 guardsize != NULL) { 452 *guardsize = ap->guardsize; 453 return (0); 454 } 455 return (EINVAL); 456 } 457 458 /* 459 * pthread_attr_setstack: sets the user stack addr and stack size. 460 * This is equivalent to the stack_base and stack_size arguments 461 * to thr_create(). 462 */ 463 #pragma weak pthread_attr_setstack = _pthread_attr_setstack 464 int 465 _pthread_attr_setstack(pthread_attr_t *attr, 466 void *stackaddr, size_t stacksize) 467 { 468 thrattr_t *ap; 469 470 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 471 stacksize >= MINSTACK) { 472 ap->stkaddr = stackaddr; 473 ap->stksize = stacksize; 474 return (0); 475 } 476 return (EINVAL); 477 } 478 479 /* 480 * pthread_attr_getstack: gets the user stack addr and stack size. 481 */ 482 #pragma weak pthread_attr_getstack = _pthread_attr_getstack 483 int 484 _pthread_attr_getstack(const pthread_attr_t *attr, 485 void **stackaddr, size_t *stacksize) 486 { 487 thrattr_t *ap; 488 489 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 490 stackaddr != NULL && stacksize != NULL) { 491 *stackaddr = ap->stkaddr; 492 *stacksize = ap->stksize; 493 return (0); 494 } 495 return (EINVAL); 496 } 497