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 * This is a consolidation-private interface, for librt. 92 */ 93 int 94 _pthread_attr_clone(pthread_attr_t *attr, const pthread_attr_t *old_attr) 95 { 96 thrattr_t *ap; 97 const thrattr_t *old_ap = 98 old_attr? old_attr->__pthread_attrp : def_thrattr(); 99 100 if (old_ap == NULL) 101 return (EINVAL); 102 if ((ap = lmalloc(sizeof (thrattr_t))) == NULL) 103 return (ENOMEM); 104 *ap = *old_ap; 105 attr->__pthread_attrp = ap; 106 return (0); 107 } 108 109 /* 110 * _pthread_attr_equal: compare two pthread_attr_t's, return 1 if equal. 111 * A NULL pthread_attr_t pointer implies default attributes. 112 * This is a consolidation-private interface, for librt. 113 */ 114 int 115 _pthread_attr_equal(const pthread_attr_t *attr1, const pthread_attr_t *attr2) 116 { 117 const thrattr_t *ap1 = attr1? attr1->__pthread_attrp : def_thrattr(); 118 const thrattr_t *ap2 = attr2? attr2->__pthread_attrp : def_thrattr(); 119 120 if (ap1 == NULL || ap2 == NULL) 121 return (0); 122 return (ap1 == ap2 || _memcmp(ap1, ap2, sizeof (thrattr_t)) == 0); 123 } 124 125 /* 126 * pthread_attr_setstacksize: sets the user stack size, minimum should 127 * be PTHREAD_STACK_MIN (MINSTACK). 128 * This is equivalent to stksize argument in thr_create(). 129 */ 130 #pragma weak pthread_attr_setstacksize = _pthread_attr_setstacksize 131 int 132 _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) 133 { 134 thrattr_t *ap; 135 136 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 137 stacksize >= MINSTACK) { 138 ap->stksize = stacksize; 139 return (0); 140 } 141 return (EINVAL); 142 } 143 144 /* 145 * pthread_attr_getstacksize: gets the user stack size. 146 */ 147 #pragma weak pthread_attr_getstacksize = _pthread_attr_getstacksize 148 int 149 _pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) 150 { 151 thrattr_t *ap; 152 153 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 154 stacksize != NULL) { 155 *stacksize = ap->stksize; 156 return (0); 157 } 158 return (EINVAL); 159 } 160 161 /* 162 * pthread_attr_setstackaddr: sets the user stack addr. 163 * This is equivalent to stkaddr argument in thr_create(). 164 */ 165 #pragma weak pthread_attr_setstackaddr = _pthread_attr_setstackaddr 166 int 167 _pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) 168 { 169 thrattr_t *ap; 170 171 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL) { 172 ap->stkaddr = stackaddr; 173 return (0); 174 } 175 return (EINVAL); 176 } 177 178 /* 179 * pthread_attr_getstackaddr: gets the user stack addr. 180 */ 181 #pragma weak pthread_attr_getstackaddr = _pthread_attr_getstackaddr 182 int 183 _pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) 184 { 185 thrattr_t *ap; 186 187 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 188 stackaddr != NULL) { 189 *stackaddr = ap->stkaddr; 190 return (0); 191 } 192 return (EINVAL); 193 } 194 195 /* 196 * pthread_attr_setdetachstate: sets the detach state to DETACHED or JOINABLE. 197 * PTHREAD_CREATE_DETACHED is equivalent to thr_create(THR_DETACHED). 198 */ 199 #pragma weak pthread_attr_setdetachstate = _pthread_attr_setdetachstate 200 int 201 _pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 202 { 203 thrattr_t *ap; 204 205 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 206 (detachstate == PTHREAD_CREATE_DETACHED || 207 detachstate == PTHREAD_CREATE_JOINABLE)) { 208 ap->detachstate = detachstate; 209 return (0); 210 } 211 return (EINVAL); 212 } 213 214 /* 215 * pthread_attr_getdetachstate: gets the detach state. 216 */ 217 #pragma weak pthread_attr_getdetachstate = _pthread_attr_getdetachstate 218 int 219 _pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) 220 { 221 thrattr_t *ap; 222 223 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 224 detachstate != NULL) { 225 *detachstate = ap->detachstate; 226 return (0); 227 } 228 return (EINVAL); 229 } 230 231 /* 232 * pthread_attr_setdaemonstate_np: sets the daemon state to DAEMON or NONDAEMON. 233 * PTHREAD_CREATE_DAEMON is equivalent to thr_create(THR_DAEMON). 234 * For now, this is a consolidation-private interface for librt. 235 */ 236 int 237 _pthread_attr_setdaemonstate_np(pthread_attr_t *attr, int daemonstate) 238 { 239 thrattr_t *ap; 240 241 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 242 (daemonstate == PTHREAD_CREATE_DAEMON_NP || 243 daemonstate == PTHREAD_CREATE_NONDAEMON_NP)) { 244 ap->daemonstate = daemonstate; 245 return (0); 246 } 247 return (EINVAL); 248 } 249 250 /* 251 * pthread_attr_getdaemonstate_np: gets the daemon state. 252 * For now, this is a consolidation-private interface for librt. 253 */ 254 int 255 _pthread_attr_getdaemonstate_np(const pthread_attr_t *attr, int *daemonstate) 256 { 257 thrattr_t *ap; 258 259 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 260 daemonstate != NULL) { 261 *daemonstate = ap->daemonstate; 262 return (0); 263 } 264 return (EINVAL); 265 } 266 267 /* 268 * pthread_attr_setscope: sets the scope to SYSTEM or PROCESS. 269 * This is equivalent to setting THR_BOUND flag in thr_create(). 270 */ 271 #pragma weak pthread_attr_setscope = _pthread_attr_setscope 272 int 273 _pthread_attr_setscope(pthread_attr_t *attr, int scope) 274 { 275 thrattr_t *ap; 276 277 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 278 (scope == PTHREAD_SCOPE_SYSTEM || 279 scope == PTHREAD_SCOPE_PROCESS)) { 280 ap->scope = scope; 281 return (0); 282 } 283 return (EINVAL); 284 } 285 286 /* 287 * pthread_attr_getscope: gets the scheduling scope. 288 */ 289 #pragma weak pthread_attr_getscope = _pthread_attr_getscope 290 int 291 _pthread_attr_getscope(const pthread_attr_t *attr, int *scope) 292 { 293 thrattr_t *ap; 294 295 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 296 scope != NULL) { 297 *scope = ap->scope; 298 return (0); 299 } 300 return (EINVAL); 301 } 302 303 /* 304 * pthread_attr_setinheritsched: sets the scheduling parameters to be 305 * EXPLICIT or INHERITED from parent thread. 306 */ 307 #pragma weak pthread_attr_setinheritsched = _pthread_attr_setinheritsched 308 int 309 _pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) 310 { 311 thrattr_t *ap; 312 313 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 314 (inherit == PTHREAD_EXPLICIT_SCHED || 315 inherit == PTHREAD_INHERIT_SCHED)) { 316 ap->inherit = inherit; 317 return (0); 318 } 319 return (EINVAL); 320 } 321 322 /* 323 * pthread_attr_getinheritsched: gets the scheduling inheritance. 324 */ 325 #pragma weak pthread_attr_getinheritsched = _pthread_attr_getinheritsched 326 int 327 _pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) 328 { 329 thrattr_t *ap; 330 331 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 332 inherit != NULL) { 333 *inherit = ap->inherit; 334 return (0); 335 } 336 return (EINVAL); 337 } 338 339 /* 340 * pthread_attr_setschedpolicy: sets the scheduling policy to SCHED_RR, 341 * SCHED_FIFO or SCHED_OTHER. 342 */ 343 #pragma weak pthread_attr_setschedpolicy = _pthread_attr_setschedpolicy 344 int 345 _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) 346 { 347 thrattr_t *ap; 348 349 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 350 (policy == SCHED_OTHER || 351 policy == SCHED_FIFO || 352 policy == SCHED_RR)) { 353 ap->policy = policy; 354 return (0); 355 } 356 return (EINVAL); 357 } 358 359 /* 360 * pthread_attr_getpolicy: gets the scheduling policy. 361 */ 362 #pragma weak pthread_attr_getschedpolicy = _pthread_attr_getschedpolicy 363 int 364 _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) 365 { 366 thrattr_t *ap; 367 368 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 369 policy != NULL) { 370 *policy = ap->policy; 371 return (0); 372 } 373 return (EINVAL); 374 } 375 376 /* 377 * pthread_attr_setschedparam: sets the scheduling parameters. 378 * Currently, we support priority only. 379 */ 380 #pragma weak pthread_attr_setschedparam = _pthread_attr_setschedparam 381 int 382 _pthread_attr_setschedparam(pthread_attr_t *attr, 383 const struct sched_param *param) 384 { 385 thrattr_t *ap; 386 int policy; 387 int pri; 388 389 if (attr == NULL || (ap = attr->__pthread_attrp) == NULL) 390 return (EINVAL); 391 392 policy = ap->policy; 393 pri = param->sched_priority; 394 if (policy == SCHED_OTHER) { 395 if ((pri < THREAD_MIN_PRIORITY || pri > THREAD_MAX_PRIORITY) && 396 _validate_rt_prio(policy, pri)) 397 return (EINVAL); 398 } else if (_validate_rt_prio(policy, pri)) { 399 return (EINVAL); 400 } 401 ap->prio = pri; 402 return (0); 403 } 404 405 /* 406 * pthread_attr_getschedparam: gets the scheduling parameters. 407 * Currently, only priority is defined as sched parameter. 408 */ 409 #pragma weak pthread_attr_getschedparam = _pthread_attr_getschedparam 410 int 411 _pthread_attr_getschedparam(const pthread_attr_t *attr, 412 struct sched_param *param) 413 { 414 thrattr_t *ap; 415 416 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 417 param != NULL) { 418 param->sched_priority = ap->prio; 419 return (0); 420 } 421 return (EINVAL); 422 } 423 424 /* 425 * UNIX98 426 * pthread_attr_setguardsize: sets the guardsize 427 */ 428 #pragma weak pthread_attr_setguardsize = _pthread_attr_setguardsize 429 int 430 _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) 431 { 432 thrattr_t *ap; 433 434 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL) { 435 ap->guardsize = guardsize; 436 return (0); 437 } 438 return (EINVAL); 439 } 440 441 /* 442 * UNIX98 443 * pthread_attr_getguardsize: gets the guardsize 444 */ 445 #pragma weak pthread_attr_getguardsize = _pthread_attr_getguardsize 446 int 447 _pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) 448 { 449 thrattr_t *ap; 450 451 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 452 guardsize != NULL) { 453 *guardsize = ap->guardsize; 454 return (0); 455 } 456 return (EINVAL); 457 } 458 459 /* 460 * pthread_attr_setstack: sets the user stack addr and stack size. 461 * This is equivalent to the stack_base and stack_size arguments 462 * to thr_create(). 463 */ 464 #pragma weak pthread_attr_setstack = _pthread_attr_setstack 465 int 466 _pthread_attr_setstack(pthread_attr_t *attr, 467 void *stackaddr, size_t stacksize) 468 { 469 thrattr_t *ap; 470 471 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 472 stacksize >= MINSTACK) { 473 ap->stkaddr = stackaddr; 474 ap->stksize = stacksize; 475 return (0); 476 } 477 return (EINVAL); 478 } 479 480 /* 481 * pthread_attr_getstack: gets the user stack addr and stack size. 482 */ 483 #pragma weak pthread_attr_getstack = _pthread_attr_getstack 484 int 485 _pthread_attr_getstack(const pthread_attr_t *attr, 486 void **stackaddr, size_t *stacksize) 487 { 488 thrattr_t *ap; 489 490 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 491 stackaddr != NULL && stacksize != NULL) { 492 *stackaddr = ap->stkaddr; 493 *stacksize = ap->stksize; 494 return (0); 495 } 496 return (EINVAL); 497 } 498