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 2008 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_INHERIT_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. 340 */ 341 #pragma weak pthread_attr_setschedpolicy = _pthread_attr_setschedpolicy 342 int 343 _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) 344 { 345 thrattr_t *ap; 346 347 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 348 policy != SCHED_SYS && get_info_by_policy(policy) != NULL) { 349 ap->policy = policy; 350 return (0); 351 } 352 return (EINVAL); 353 } 354 355 /* 356 * pthread_attr_getpolicy: gets the scheduling policy. 357 */ 358 #pragma weak pthread_attr_getschedpolicy = _pthread_attr_getschedpolicy 359 int 360 _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) 361 { 362 thrattr_t *ap; 363 364 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 365 policy != NULL) { 366 *policy = ap->policy; 367 return (0); 368 } 369 return (EINVAL); 370 } 371 372 /* 373 * pthread_attr_setschedparam: sets the scheduling parameters. 374 * Currently, we support priority only. 375 */ 376 #pragma weak pthread_attr_setschedparam = _pthread_attr_setschedparam 377 int 378 _pthread_attr_setschedparam(pthread_attr_t *attr, 379 const struct sched_param *param) 380 { 381 thrattr_t *ap; 382 383 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 384 param != NULL) { 385 ap->prio = param->sched_priority; 386 return (0); 387 } 388 return (EINVAL); 389 } 390 391 /* 392 * pthread_attr_getschedparam: gets the scheduling parameters. 393 * Currently, only priority is defined as sched parameter. 394 */ 395 #pragma weak pthread_attr_getschedparam = _pthread_attr_getschedparam 396 int 397 _pthread_attr_getschedparam(const pthread_attr_t *attr, 398 struct sched_param *param) 399 { 400 thrattr_t *ap; 401 402 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 403 param != NULL) { 404 param->sched_priority = ap->prio; 405 return (0); 406 } 407 return (EINVAL); 408 } 409 410 /* 411 * UNIX98 412 * pthread_attr_setguardsize: sets the guardsize 413 */ 414 #pragma weak pthread_attr_setguardsize = _pthread_attr_setguardsize 415 int 416 _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) 417 { 418 thrattr_t *ap; 419 420 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL) { 421 ap->guardsize = guardsize; 422 return (0); 423 } 424 return (EINVAL); 425 } 426 427 /* 428 * UNIX98 429 * pthread_attr_getguardsize: gets the guardsize 430 */ 431 #pragma weak pthread_attr_getguardsize = _pthread_attr_getguardsize 432 int 433 _pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) 434 { 435 thrattr_t *ap; 436 437 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 438 guardsize != NULL) { 439 *guardsize = ap->guardsize; 440 return (0); 441 } 442 return (EINVAL); 443 } 444 445 /* 446 * pthread_attr_setstack: sets the user stack addr and stack size. 447 * This is equivalent to the stack_base and stack_size arguments 448 * to thr_create(). 449 */ 450 #pragma weak pthread_attr_setstack = _pthread_attr_setstack 451 int 452 _pthread_attr_setstack(pthread_attr_t *attr, 453 void *stackaddr, size_t stacksize) 454 { 455 thrattr_t *ap; 456 457 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 458 stacksize >= MINSTACK) { 459 ap->stkaddr = stackaddr; 460 ap->stksize = stacksize; 461 return (0); 462 } 463 return (EINVAL); 464 } 465 466 /* 467 * pthread_attr_getstack: gets the user stack addr and stack size. 468 */ 469 #pragma weak pthread_attr_getstack = _pthread_attr_getstack 470 int 471 _pthread_attr_getstack(const pthread_attr_t *attr, 472 void **stackaddr, size_t *stacksize) 473 { 474 thrattr_t *ap; 475 476 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 477 stackaddr != NULL && stacksize != NULL) { 478 *stackaddr = ap->stkaddr; 479 *stacksize = ap->stksize; 480 return (0); 481 } 482 return (EINVAL); 483 } 484