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