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