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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 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 * pthread_attr_init: allocates the attribute object and initializes it 35 * with the default values. 36 */ 37 #pragma weak pthread_attr_init = _pthread_attr_init 38 int 39 _pthread_attr_init(pthread_attr_t *attr) 40 { 41 thrattr_t *ap; 42 43 if ((ap = lmalloc(sizeof (thrattr_t))) != NULL) { 44 if (_lpagesize == 0) 45 _lpagesize = _sysconf(_SC_PAGESIZE); 46 ap->stksize = 0; 47 ap->stkaddr = NULL; 48 ap->prio = 0; 49 ap->policy = SCHED_OTHER; 50 ap->inherit = PTHREAD_EXPLICIT_SCHED; 51 ap->detachstate = PTHREAD_CREATE_JOINABLE; 52 ap->scope = PTHREAD_SCOPE_PROCESS; 53 ap->guardsize = _lpagesize; 54 attr->__pthread_attrp = ap; 55 return (0); 56 } 57 return (ENOMEM); 58 } 59 60 /* 61 * pthread_attr_destroy: frees the attribute object and invalidates it 62 * with NULL value. 63 */ 64 #pragma weak pthread_attr_destroy = _pthread_attr_destroy 65 int 66 _pthread_attr_destroy(pthread_attr_t *attr) 67 { 68 if (attr == NULL || attr->__pthread_attrp == NULL) 69 return (EINVAL); 70 lfree(attr->__pthread_attrp, sizeof (thrattr_t)); 71 attr->__pthread_attrp = NULL; 72 return (0); 73 } 74 75 /* 76 * pthread_attr_setstacksize: sets the user stack size, minimum should 77 * be PTHREAD_STACK_MIN (MINSTACK). 78 * This is equivalent to stksize argument in thr_create(). 79 */ 80 #pragma weak pthread_attr_setstacksize = _pthread_attr_setstacksize 81 int 82 _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) 83 { 84 thrattr_t *ap; 85 86 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 87 stacksize >= MINSTACK) { 88 ap->stksize = stacksize; 89 return (0); 90 } 91 return (EINVAL); 92 } 93 94 /* 95 * pthread_attr_getstacksize: gets the user stack size. 96 */ 97 #pragma weak pthread_attr_getstacksize = _pthread_attr_getstacksize 98 int 99 _pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) 100 { 101 thrattr_t *ap; 102 103 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 104 stacksize != NULL) { 105 *stacksize = ap->stksize; 106 return (0); 107 } 108 return (EINVAL); 109 } 110 111 /* 112 * pthread_attr_setstackaddr: sets the user stack addr. 113 * This is equivalent to stkaddr argument in thr_create(). 114 */ 115 #pragma weak pthread_attr_setstackaddr = _pthread_attr_setstackaddr 116 int 117 _pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) 118 { 119 thrattr_t *ap; 120 121 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL) { 122 ap->stkaddr = stackaddr; 123 return (0); 124 } 125 return (EINVAL); 126 } 127 128 /* 129 * pthread_attr_getstackaddr: gets the user stack addr. 130 */ 131 #pragma weak pthread_attr_getstackaddr = _pthread_attr_getstackaddr 132 int 133 _pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) 134 { 135 thrattr_t *ap; 136 137 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 138 stackaddr != NULL) { 139 *stackaddr = ap->stkaddr; 140 return (0); 141 } 142 return (EINVAL); 143 } 144 145 /* 146 * pthread_attr_setdetachstate: sets the detach state to JOINABLE or 147 * DETACHED. 148 * This is equivalent to setting THR_DETACHED flag in thr_create(). 149 */ 150 #pragma weak pthread_attr_setdetachstate = _pthread_attr_setdetachstate 151 int 152 _pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 153 { 154 thrattr_t *ap; 155 156 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 157 (detachstate == PTHREAD_CREATE_DETACHED || 158 detachstate == PTHREAD_CREATE_JOINABLE)) { 159 ap->detachstate = detachstate; 160 return (0); 161 } 162 return (EINVAL); 163 } 164 165 /* 166 * pthread_attr_getdetachstate: gets the detach state. 167 */ 168 #pragma weak pthread_attr_getdetachstate = _pthread_attr_getdetachstate 169 int 170 _pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) 171 { 172 thrattr_t *ap; 173 174 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 175 detachstate != NULL) { 176 *detachstate = ap->detachstate; 177 return (0); 178 } 179 return (EINVAL); 180 } 181 182 /* 183 * pthread_attr_setscope: sets the scope to SYSTEM or PROCESS. 184 * This is equivalent to setting THR_BOUND flag in thr_create(). 185 */ 186 #pragma weak pthread_attr_setscope = _pthread_attr_setscope 187 int 188 _pthread_attr_setscope(pthread_attr_t *attr, int scope) 189 { 190 thrattr_t *ap; 191 192 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 193 (scope == PTHREAD_SCOPE_SYSTEM || 194 scope == PTHREAD_SCOPE_PROCESS)) { 195 ap->scope = scope; 196 return (0); 197 } 198 return (EINVAL); 199 } 200 201 /* 202 * pthread_attr_getscope: gets the scheduling scope. 203 */ 204 #pragma weak pthread_attr_getscope = _pthread_attr_getscope 205 int 206 _pthread_attr_getscope(const pthread_attr_t *attr, int *scope) 207 { 208 thrattr_t *ap; 209 210 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 211 scope != NULL) { 212 *scope = ap->scope; 213 return (0); 214 } 215 return (EINVAL); 216 } 217 218 /* 219 * pthread_attr_setinheritsched: sets the scheduling parameters to be 220 * EXPLICIT or INHERITED from parent thread. 221 */ 222 #pragma weak pthread_attr_setinheritsched = _pthread_attr_setinheritsched 223 int 224 _pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) 225 { 226 thrattr_t *ap; 227 228 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 229 (inherit == PTHREAD_EXPLICIT_SCHED || 230 inherit == PTHREAD_INHERIT_SCHED)) { 231 ap->inherit = inherit; 232 return (0); 233 } 234 return (EINVAL); 235 } 236 237 /* 238 * pthread_attr_getinheritsched: gets the scheduling inheritance. 239 */ 240 #pragma weak pthread_attr_getinheritsched = _pthread_attr_getinheritsched 241 int 242 _pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) 243 { 244 thrattr_t *ap; 245 246 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 247 inherit != NULL) { 248 *inherit = ap->inherit; 249 return (0); 250 } 251 return (EINVAL); 252 } 253 254 /* 255 * pthread_attr_setschedpolicy: sets the scheduling policy to SCHED_RR, 256 * SCHED_FIFO or SCHED_OTHER. 257 */ 258 #pragma weak pthread_attr_setschedpolicy = _pthread_attr_setschedpolicy 259 int 260 _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) 261 { 262 thrattr_t *ap; 263 264 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 265 (policy == SCHED_OTHER || 266 policy == SCHED_FIFO || 267 policy == SCHED_RR)) { 268 ap->policy = policy; 269 return (0); 270 } 271 return (EINVAL); 272 } 273 274 /* 275 * pthread_attr_getpolicy: gets the scheduling policy. 276 */ 277 #pragma weak pthread_attr_getschedpolicy = _pthread_attr_getschedpolicy 278 int 279 _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) 280 { 281 thrattr_t *ap; 282 283 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 284 policy != NULL) { 285 *policy = ap->policy; 286 return (0); 287 } 288 return (EINVAL); 289 } 290 291 /* 292 * pthread_attr_setschedparam: sets the scheduling parameters. 293 * Currently, we support priority only. 294 */ 295 #pragma weak pthread_attr_setschedparam = _pthread_attr_setschedparam 296 int 297 _pthread_attr_setschedparam(pthread_attr_t *attr, 298 const struct sched_param *param) 299 { 300 thrattr_t *ap; 301 int policy; 302 int pri; 303 304 if (attr == NULL || (ap = attr->__pthread_attrp) == NULL) 305 return (EINVAL); 306 307 policy = ap->policy; 308 pri = param->sched_priority; 309 if (policy == SCHED_OTHER) { 310 if ((pri < THREAD_MIN_PRIORITY || pri > THREAD_MAX_PRIORITY) && 311 _validate_rt_prio(policy, pri)) 312 return (EINVAL); 313 } else if (_validate_rt_prio(policy, pri)) { 314 return (EINVAL); 315 } 316 ap->prio = pri; 317 return (0); 318 } 319 320 /* 321 * pthread_attr_getschedparam: gets the scheduling parameters. 322 * Currently, only priority is defined as sched parameter. 323 */ 324 #pragma weak pthread_attr_getschedparam = _pthread_attr_getschedparam 325 int 326 _pthread_attr_getschedparam(const pthread_attr_t *attr, 327 struct sched_param *param) 328 { 329 thrattr_t *ap; 330 331 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 332 param != NULL) { 333 param->sched_priority = ap->prio; 334 return (0); 335 } 336 return (EINVAL); 337 } 338 339 /* 340 * UNIX98 341 * pthread_attr_setguardsize: sets the guardsize 342 */ 343 #pragma weak pthread_attr_setguardsize = _pthread_attr_setguardsize 344 int 345 _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) 346 { 347 thrattr_t *ap; 348 349 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL) { 350 ap->guardsize = guardsize; 351 return (0); 352 } 353 return (EINVAL); 354 } 355 356 /* 357 * UNIX98 358 * pthread_attr_getguardsize: gets the guardsize 359 */ 360 #pragma weak pthread_attr_getguardsize = _pthread_attr_getguardsize 361 int 362 _pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) 363 { 364 thrattr_t *ap; 365 366 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 367 guardsize != NULL) { 368 *guardsize = ap->guardsize; 369 return (0); 370 } 371 return (EINVAL); 372 } 373 374 /* 375 * pthread_attr_setstack: sets the user stack addr and stack size. 376 * This is equivalent to the stack_base and stack_size arguments 377 * to thr_create(). 378 */ 379 #pragma weak pthread_attr_setstack = _pthread_attr_setstack 380 int 381 _pthread_attr_setstack(pthread_attr_t *attr, 382 void *stackaddr, size_t stacksize) 383 { 384 thrattr_t *ap; 385 386 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 387 stacksize >= MINSTACK) { 388 ap->stkaddr = stackaddr; 389 ap->stksize = stacksize; 390 return (0); 391 } 392 return (EINVAL); 393 } 394 395 /* 396 * pthread_attr_getstack: gets the user stack addr and stack size. 397 */ 398 #pragma weak pthread_attr_getstack = _pthread_attr_getstack 399 int 400 _pthread_attr_getstack(const pthread_attr_t *attr, 401 void **stackaddr, size_t *stacksize) 402 { 403 thrattr_t *ap; 404 405 if (attr != NULL && (ap = attr->__pthread_attrp) != NULL && 406 stackaddr != NULL && stacksize != NULL) { 407 *stackaddr = ap->stkaddr; 408 *stacksize = ap->stksize; 409 return (0); 410 } 411 return (EINVAL); 412 } 413