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