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