1 /* 2 * Copyright (c) 2003 Craig Rodrigues <rodrigc@attbi.com>. 3 * Copyright (c) 2002,2003 Alexey Zelkin <phantom@FreeBSD.org> 4 * Copyright (C) 2001 Jason Evans <jasone@freebsd.org>. 5 * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. 6 * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice(s), this list of conditions and the following disclaimer 14 * unmodified other than the allowable addition of one or more 15 * copyright notices. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice(s), this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 30 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 31 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * $DragonFly: src/lib/libthread_xu/thread/thr_attr.c,v 1.7 2006/04/06 13:03:09 davidxu Exp $ 34 */ 35 36 #include "namespace.h" 37 #include <machine/tls.h> 38 39 #include <errno.h> 40 #include <pthread.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <pthread_np.h> 44 #include "un-namespace.h" 45 46 #include "thr_private.h" 47 48 /* Default thread attributes. */ 49 struct pthread_attr _pthread_attr_default = { 50 .sched_policy = SCHED_OTHER, 51 .sched_inherit = 0, 52 .sched_interval = TIMESLICE_USEC, 53 .prio = THR_DEFAULT_PRIORITY, 54 .suspend = THR_CREATE_RUNNING, 55 .flags = 0, 56 .stackaddr_attr = NULL, 57 .stacksize_attr = THR_STACK_DEFAULT, 58 .guardsize_attr = 0 59 }; 60 61 int 62 _pthread_attr_destroy(pthread_attr_t *attr) 63 { 64 int ret; 65 66 /* Check for invalid arguments: */ 67 if (attr == NULL || *attr == NULL) 68 /* Invalid argument: */ 69 ret = EINVAL; 70 else { 71 /* Free the memory allocated to the attribute object: */ 72 free(*attr); 73 74 /* 75 * Leave the attribute pointer NULL now that the memory 76 * has been freed: 77 */ 78 *attr = NULL; 79 ret = 0; 80 } 81 return(ret); 82 } 83 84 __strong_reference(_pthread_attr_destroy, pthread_attr_destroy); 85 86 int 87 _pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst) 88 { 89 struct pthread *curthread; 90 struct pthread_attr attr; 91 int ret; 92 93 if (pid == NULL || dst == NULL || *dst == NULL) 94 return (EINVAL); 95 96 curthread = tls_get_curthread(); 97 if ((ret = _thr_ref_add(curthread, pid, /*include dead*/0)) != 0) 98 return (ret); 99 attr = pid->attr; 100 if (pid->tlflags & TLFLAGS_DETACHED) 101 attr.flags |= PTHREAD_DETACHED; 102 _thr_ref_delete(curthread, pid); 103 memcpy(*dst, &attr, sizeof(struct pthread_attr)); 104 105 return (0); 106 } 107 108 __strong_reference(_pthread_attr_get_np, pthread_attr_get_np); 109 110 int 111 _pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) 112 { 113 int ret; 114 115 /* Check for invalid arguments: */ 116 if (attr == NULL || *attr == NULL || detachstate == NULL) 117 ret = EINVAL; 118 else { 119 /* Check if the detached flag is set: */ 120 if ((*attr)->flags & PTHREAD_DETACHED) 121 /* Return detached: */ 122 *detachstate = PTHREAD_CREATE_DETACHED; 123 else 124 /* Return joinable: */ 125 *detachstate = PTHREAD_CREATE_JOINABLE; 126 ret = 0; 127 } 128 return(ret); 129 } 130 131 __strong_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate); 132 133 int 134 _pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) 135 { 136 int ret; 137 138 /* Check for invalid arguments: */ 139 if (attr == NULL || *attr == NULL || guardsize == NULL) 140 ret = EINVAL; 141 else { 142 /* Return the guard size: */ 143 *guardsize = (*attr)->guardsize_attr; 144 ret = 0; 145 } 146 return(ret); 147 } 148 149 __strong_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize); 150 151 int 152 _pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit) 153 { 154 int ret = 0; 155 156 if ((attr == NULL) || (*attr == NULL)) 157 ret = EINVAL; 158 else 159 *sched_inherit = (*attr)->sched_inherit; 160 161 return(ret); 162 } 163 164 __strong_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched); 165 166 int 167 _pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) 168 { 169 int ret = 0; 170 171 if ((attr == NULL) || (*attr == NULL) || (param == NULL)) 172 ret = EINVAL; 173 else 174 param->sched_priority = (*attr)->prio; 175 176 return(ret); 177 } 178 179 __strong_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam); 180 181 int 182 _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) 183 { 184 int ret = 0; 185 186 if ((attr == NULL) || (*attr == NULL) || (policy == NULL)) 187 ret = EINVAL; 188 else 189 *policy = (*attr)->sched_policy; 190 191 return(ret); 192 } 193 194 __strong_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy); 195 196 int 197 _pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope) 198 { 199 int ret = 0; 200 201 if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL)) 202 /* Return an invalid argument: */ 203 ret = EINVAL; 204 205 else 206 *contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ? 207 PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; 208 209 return(ret); 210 } 211 212 __strong_reference(_pthread_attr_getscope, pthread_attr_getscope); 213 214 int 215 _pthread_attr_getstack(const pthread_attr_t * __restrict attr, 216 void ** __restrict stackaddr, 217 size_t * __restrict stacksize) 218 { 219 int ret; 220 221 /* Check for invalid arguments: */ 222 if (attr == NULL || *attr == NULL || stackaddr == NULL 223 || stacksize == NULL ) 224 ret = EINVAL; 225 else { 226 /* Return the stack address and size */ 227 *stackaddr = (*attr)->stackaddr_attr; 228 *stacksize = (*attr)->stacksize_attr; 229 ret = 0; 230 } 231 return(ret); 232 } 233 234 __strong_reference(_pthread_attr_getstack, pthread_attr_getstack); 235 236 int 237 _pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) 238 { 239 int ret; 240 241 /* Check for invalid arguments: */ 242 if (attr == NULL || *attr == NULL || stackaddr == NULL) 243 ret = EINVAL; 244 else { 245 /* Return the stack address: */ 246 *stackaddr = (*attr)->stackaddr_attr; 247 ret = 0; 248 } 249 return(ret); 250 } 251 252 __strong_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr); 253 254 int 255 _pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) 256 { 257 int ret; 258 259 /* Check for invalid arguments: */ 260 if (attr == NULL || *attr == NULL || stacksize == NULL) 261 ret = EINVAL; 262 else { 263 /* Return the stack size: */ 264 *stacksize = (*attr)->stacksize_attr; 265 ret = 0; 266 } 267 return(ret); 268 } 269 270 __strong_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize); 271 272 int 273 _pthread_attr_init(pthread_attr_t *attr) 274 { 275 int ret; 276 pthread_attr_t pattr; 277 278 _thr_check_init(); 279 280 /* Allocate memory for the attribute object: */ 281 if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) 282 /* Insufficient memory: */ 283 ret = ENOMEM; 284 else { 285 /* Initialise the attribute object with the defaults: */ 286 memcpy(pattr, &_pthread_attr_default, 287 sizeof(struct pthread_attr)); 288 289 /* Return a pointer to the attribute object: */ 290 *attr = pattr; 291 ret = 0; 292 } 293 return(ret); 294 } 295 296 __strong_reference(_pthread_attr_init, pthread_attr_init); 297 298 int 299 _pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) 300 { 301 int ret; 302 303 if (attr == NULL || *attr == NULL) { 304 ret = EINVAL; 305 } else { 306 (*attr)->suspend = THR_CREATE_SUSPENDED; 307 ret = 0; 308 } 309 return(ret); 310 } 311 312 __strong_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np); 313 314 int 315 _pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 316 { 317 int ret; 318 319 /* Check for invalid arguments: */ 320 if (attr == NULL || *attr == NULL || 321 (detachstate != PTHREAD_CREATE_DETACHED && 322 detachstate != PTHREAD_CREATE_JOINABLE)) 323 ret = EINVAL; 324 else { 325 /* Check if detached state: */ 326 if (detachstate == PTHREAD_CREATE_DETACHED) 327 /* Set the detached flag: */ 328 (*attr)->flags |= PTHREAD_DETACHED; 329 else 330 /* Reset the detached flag: */ 331 (*attr)->flags &= ~PTHREAD_DETACHED; 332 ret = 0; 333 } 334 return(ret); 335 } 336 337 __strong_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate); 338 339 int 340 _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) 341 { 342 int ret; 343 344 /* Check for invalid arguments. */ 345 if (attr == NULL || *attr == NULL) 346 ret = EINVAL; 347 else { 348 /* Save the stack size. */ 349 (*attr)->guardsize_attr = guardsize; 350 ret = 0; 351 } 352 return(ret); 353 } 354 355 __strong_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize); 356 357 int 358 _pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit) 359 { 360 int ret = 0; 361 362 if ((attr == NULL) || (*attr == NULL)) 363 ret = EINVAL; 364 else if (sched_inherit != PTHREAD_INHERIT_SCHED && 365 sched_inherit != PTHREAD_EXPLICIT_SCHED) 366 ret = ENOTSUP; 367 else 368 (*attr)->sched_inherit = sched_inherit; 369 370 return(ret); 371 } 372 373 __strong_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched); 374 375 int 376 _pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param) 377 { 378 int ret = 0; 379 380 if ((attr == NULL) || (*attr == NULL)) 381 ret = EINVAL; 382 else if (param == NULL) { 383 ret = ENOTSUP; 384 } else if ((param->sched_priority < THR_MIN_PRIORITY) || 385 (param->sched_priority > THR_MAX_PRIORITY)) { 386 /* Return an unsupported value error. */ 387 ret = ENOTSUP; 388 } else 389 (*attr)->prio = param->sched_priority; 390 391 return(ret); 392 } 393 394 __strong_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam); 395 396 int 397 _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) 398 { 399 int ret = 0; 400 401 if ((attr == NULL) || (*attr == NULL)) 402 ret = EINVAL; 403 else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) { 404 ret = ENOTSUP; 405 } else 406 (*attr)->sched_policy = policy; 407 408 return(ret); 409 } 410 411 __strong_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy); 412 413 int 414 _pthread_attr_setscope(pthread_attr_t *attr, int contentionscope) 415 { 416 int ret = 0; 417 418 if ((attr == NULL) || (*attr == NULL)) { 419 /* Return an invalid argument: */ 420 ret = EINVAL; 421 } else if ((contentionscope != PTHREAD_SCOPE_PROCESS) && 422 (contentionscope != PTHREAD_SCOPE_SYSTEM)) { 423 ret = EINVAL; 424 } else if (contentionscope == PTHREAD_SCOPE_SYSTEM) { 425 (*attr)->flags |= contentionscope; 426 } else { 427 (*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM; 428 } 429 return (ret); 430 } 431 432 __strong_reference(_pthread_attr_setscope, pthread_attr_setscope); 433 434 int 435 _pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, 436 size_t stacksize) 437 { 438 int ret; 439 440 /* Check for invalid arguments: */ 441 if (attr == NULL || *attr == NULL || stackaddr == NULL 442 || stacksize < PTHREAD_STACK_MIN) 443 ret = EINVAL; 444 else { 445 /* Save the stack address and stack size */ 446 (*attr)->stackaddr_attr = stackaddr; 447 (*attr)->stacksize_attr = stacksize; 448 ret = 0; 449 } 450 return(ret); 451 } 452 453 __strong_reference(_pthread_attr_setstack, pthread_attr_setstack); 454 455 int 456 _pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) 457 { 458 int ret; 459 460 /* Check for invalid arguments: */ 461 if (attr == NULL || *attr == NULL || stackaddr == NULL) 462 ret = EINVAL; 463 else { 464 /* Save the stack address: */ 465 (*attr)->stackaddr_attr = stackaddr; 466 ret = 0; 467 } 468 return(ret); 469 } 470 471 __strong_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr); 472 473 int 474 _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) 475 { 476 int ret; 477 478 /* Check for invalid arguments: */ 479 if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) 480 ret = EINVAL; 481 else { 482 /* Save the stack size: */ 483 (*attr)->stacksize_attr = stacksize; 484 ret = 0; 485 } 486 return(ret); 487 } 488 489 __strong_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize); 490 491