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.9 2008/07/15 01:18:53 dillon 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 .prio = THR_DEFAULT_PRIORITY, 53 .suspend = THR_CREATE_RUNNING, 54 .flags = 0, 55 .stackaddr_attr = NULL, 56 .stacksize_attr = THR_STACK_DEFAULT, 57 .guardsize_attr = 0 58 }; 59 60 int 61 _pthread_attr_destroy(pthread_attr_t *attr) 62 { 63 int ret; 64 65 /* Check for invalid arguments: */ 66 if (attr == NULL || *attr == NULL) 67 /* Invalid argument: */ 68 ret = EINVAL; 69 else { 70 /* Free the memory allocated to the attribute object: */ 71 free(*attr); 72 73 /* 74 * Leave the attribute pointer NULL now that the memory 75 * has been freed: 76 */ 77 *attr = NULL; 78 ret = 0; 79 } 80 return(ret); 81 } 82 83 __strong_reference(_pthread_attr_destroy, pthread_attr_destroy); 84 85 int 86 _pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst) 87 { 88 struct pthread *curthread; 89 struct pthread_attr attr; 90 int ret; 91 92 if (pid == NULL || dst == NULL || *dst == NULL) 93 return (EINVAL); 94 95 curthread = tls_get_curthread(); 96 if ((ret = _thr_ref_add(curthread, pid, /*include dead*/0)) != 0) 97 return (ret); 98 attr = pid->attr; 99 if (pid->tlflags & TLFLAGS_DETACHED) 100 attr.flags |= PTHREAD_DETACHED; 101 _thr_ref_delete(curthread, pid); 102 memcpy(*dst, &attr, sizeof(struct pthread_attr)); 103 104 return (0); 105 } 106 107 __strong_reference(_pthread_attr_get_np, pthread_attr_get_np); 108 109 int 110 _pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) 111 { 112 int ret; 113 114 /* Check for invalid arguments: */ 115 if (attr == NULL || *attr == NULL || detachstate == NULL) 116 ret = EINVAL; 117 else { 118 /* Check if the detached flag is set: */ 119 if ((*attr)->flags & PTHREAD_DETACHED) 120 /* Return detached: */ 121 *detachstate = PTHREAD_CREATE_DETACHED; 122 else 123 /* Return joinable: */ 124 *detachstate = PTHREAD_CREATE_JOINABLE; 125 ret = 0; 126 } 127 return(ret); 128 } 129 130 __strong_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate); 131 132 int 133 _pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) 134 { 135 int ret; 136 137 /* Check for invalid arguments: */ 138 if (attr == NULL || *attr == NULL || guardsize == NULL) 139 ret = EINVAL; 140 else { 141 /* Return the guard size: */ 142 *guardsize = (*attr)->guardsize_attr; 143 ret = 0; 144 } 145 return(ret); 146 } 147 148 __strong_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize); 149 150 int 151 _pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit) 152 { 153 int ret = 0; 154 155 if ((attr == NULL) || (*attr == NULL)) 156 ret = EINVAL; 157 else 158 *sched_inherit = (*attr)->sched_inherit; 159 160 return(ret); 161 } 162 163 __strong_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched); 164 165 int 166 _pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) 167 { 168 int ret = 0; 169 170 if ((attr == NULL) || (*attr == NULL) || (param == NULL)) 171 ret = EINVAL; 172 else 173 param->sched_priority = (*attr)->prio; 174 175 return(ret); 176 } 177 178 __strong_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam); 179 180 int 181 _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) 182 { 183 int ret = 0; 184 185 if ((attr == NULL) || (*attr == NULL) || (policy == NULL)) 186 ret = EINVAL; 187 else 188 *policy = (*attr)->sched_policy; 189 190 return(ret); 191 } 192 193 __strong_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy); 194 195 int 196 _pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope) 197 { 198 int ret = 0; 199 200 if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL)) 201 /* Return an invalid argument: */ 202 ret = EINVAL; 203 204 else 205 *contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ? 206 PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; 207 208 return(ret); 209 } 210 211 __strong_reference(_pthread_attr_getscope, pthread_attr_getscope); 212 213 int 214 _pthread_attr_getstack(const pthread_attr_t * __restrict attr, 215 void ** __restrict stackaddr, 216 size_t * __restrict stacksize) 217 { 218 int ret; 219 220 /* Check for invalid arguments: */ 221 if (attr == NULL || *attr == NULL || stackaddr == NULL 222 || stacksize == NULL ) 223 ret = EINVAL; 224 else { 225 /* Return the stack address and size */ 226 *stackaddr = (*attr)->stackaddr_attr; 227 *stacksize = (*attr)->stacksize_attr; 228 ret = 0; 229 } 230 return(ret); 231 } 232 233 __strong_reference(_pthread_attr_getstack, pthread_attr_getstack); 234 235 int 236 _pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) 237 { 238 int ret; 239 240 /* Check for invalid arguments: */ 241 if (attr == NULL || *attr == NULL || stackaddr == NULL) 242 ret = EINVAL; 243 else { 244 /* Return the stack address: */ 245 *stackaddr = (*attr)->stackaddr_attr; 246 ret = 0; 247 } 248 return(ret); 249 } 250 251 __strong_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr); 252 253 int 254 _pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) 255 { 256 int ret; 257 258 /* Check for invalid arguments: */ 259 if (attr == NULL || *attr == NULL || stacksize == NULL) 260 ret = EINVAL; 261 else { 262 /* Return the stack size: */ 263 *stacksize = (*attr)->stacksize_attr; 264 ret = 0; 265 } 266 return(ret); 267 } 268 269 __strong_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize); 270 271 int 272 _pthread_attr_init(pthread_attr_t *attr) 273 { 274 int ret; 275 pthread_attr_t pattr; 276 277 _thr_check_init(); 278 279 /* Allocate memory for the attribute object: */ 280 if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) 281 /* Insufficient memory: */ 282 ret = ENOMEM; 283 else { 284 /* Initialise the attribute object with the defaults: */ 285 memcpy(pattr, &_pthread_attr_default, 286 sizeof(struct pthread_attr)); 287 288 /* Return a pointer to the attribute object: */ 289 *attr = pattr; 290 ret = 0; 291 } 292 return(ret); 293 } 294 295 __strong_reference(_pthread_attr_init, pthread_attr_init); 296 297 int 298 _pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) 299 { 300 int ret; 301 302 if (attr == NULL || *attr == NULL) { 303 ret = EINVAL; 304 } else { 305 (*attr)->suspend = THR_CREATE_SUSPENDED; 306 ret = 0; 307 } 308 return(ret); 309 } 310 311 __strong_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np); 312 313 int 314 _pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 315 { 316 int ret; 317 318 /* Check for invalid arguments: */ 319 if (attr == NULL || *attr == NULL || 320 (detachstate != PTHREAD_CREATE_DETACHED && 321 detachstate != PTHREAD_CREATE_JOINABLE)) 322 ret = EINVAL; 323 else { 324 /* Check if detached state: */ 325 if (detachstate == PTHREAD_CREATE_DETACHED) 326 /* Set the detached flag: */ 327 (*attr)->flags |= PTHREAD_DETACHED; 328 else 329 /* Reset the detached flag: */ 330 (*attr)->flags &= ~PTHREAD_DETACHED; 331 ret = 0; 332 } 333 return(ret); 334 } 335 336 __strong_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate); 337 338 int 339 _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) 340 { 341 int ret; 342 343 /* Check for invalid arguments. */ 344 if (attr == NULL || *attr == NULL) 345 ret = EINVAL; 346 else { 347 /* Save the stack size. */ 348 (*attr)->guardsize_attr = guardsize; 349 ret = 0; 350 } 351 return(ret); 352 } 353 354 __strong_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize); 355 356 int 357 _pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit) 358 { 359 int ret = 0; 360 361 if ((attr == NULL) || (*attr == NULL)) 362 ret = EINVAL; 363 else if (sched_inherit != PTHREAD_INHERIT_SCHED && 364 sched_inherit != PTHREAD_EXPLICIT_SCHED) 365 ret = ENOTSUP; 366 else 367 (*attr)->sched_inherit = sched_inherit; 368 369 return(ret); 370 } 371 372 __strong_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched); 373 374 int 375 _pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param) 376 { 377 int ret = 0; 378 379 if ((attr == NULL) || (*attr == NULL)) 380 ret = EINVAL; 381 else if (param == NULL) { 382 ret = ENOTSUP; 383 } else { 384 int minv = sched_get_priority_min((*attr)->sched_policy); 385 int maxv = sched_get_priority_max((*attr)->sched_policy); 386 if (minv == -1 || maxv == -1 || 387 param->sched_priority < minv || 388 param->sched_priority > maxv) { 389 ret = ENOTSUP; 390 } else { 391 (*attr)->prio = param->sched_priority; 392 } 393 } 394 return(ret); 395 } 396 397 __strong_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam); 398 399 int 400 _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) 401 { 402 int ret = 0; 403 404 if ((attr == NULL) || (*attr == NULL)) 405 ret = EINVAL; 406 else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) { 407 ret = ENOTSUP; 408 } else 409 (*attr)->sched_policy = policy; 410 411 return(ret); 412 } 413 414 __strong_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy); 415 416 int 417 _pthread_attr_setscope(pthread_attr_t *attr, int contentionscope) 418 { 419 int ret = 0; 420 421 if ((attr == NULL) || (*attr == NULL)) { 422 /* Return an invalid argument: */ 423 ret = EINVAL; 424 } else if ((contentionscope != PTHREAD_SCOPE_PROCESS) && 425 (contentionscope != PTHREAD_SCOPE_SYSTEM)) { 426 ret = EINVAL; 427 } else if (contentionscope == PTHREAD_SCOPE_SYSTEM) { 428 (*attr)->flags |= contentionscope; 429 } else { 430 (*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM; 431 } 432 return (ret); 433 } 434 435 __strong_reference(_pthread_attr_setscope, pthread_attr_setscope); 436 437 int 438 _pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, 439 size_t stacksize) 440 { 441 int ret; 442 443 /* Check for invalid arguments: */ 444 if (attr == NULL || *attr == NULL || stackaddr == NULL 445 || stacksize < PTHREAD_STACK_MIN) 446 ret = EINVAL; 447 else { 448 /* Save the stack address and stack size */ 449 (*attr)->stackaddr_attr = stackaddr; 450 (*attr)->stacksize_attr = stacksize; 451 ret = 0; 452 } 453 return(ret); 454 } 455 456 __strong_reference(_pthread_attr_setstack, pthread_attr_setstack); 457 458 int 459 _pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) 460 { 461 int ret; 462 463 /* Check for invalid arguments: */ 464 if (attr == NULL || *attr == NULL || stackaddr == NULL) 465 ret = EINVAL; 466 else { 467 /* Save the stack address: */ 468 (*attr)->stackaddr_attr = stackaddr; 469 ret = 0; 470 } 471 return(ret); 472 } 473 474 __strong_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr); 475 476 int 477 _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) 478 { 479 int ret; 480 481 /* Check for invalid arguments: */ 482 if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) 483 ret = EINVAL; 484 else { 485 /* Save the stack size: */ 486 (*attr)->stacksize_attr = stacksize; 487 ret = 0; 488 } 489 return(ret); 490 } 491 492 __strong_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize); 493 494