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. Neither the name of the author nor the names of any co-contributors 78 * may be used to endorse or promote products derived from this software 79 * without specific prior written permission. 80 * 81 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 82 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 83 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 84 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 85 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 86 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 87 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 88 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 89 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 90 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 91 * SUCH DAMAGE. 92 * 93 * $FreeBSD$ 94 */ 95 96 #include "namespace.h" 97 #include <errno.h> 98 #include <pthread.h> 99 #include <stdlib.h> 100 #include <string.h> 101 #include <pthread_np.h> 102 #include "un-namespace.h" 103 104 #include "thr_private.h" 105 106 __weak_reference(_pthread_attr_destroy, pthread_attr_destroy); 107 108 int 109 _pthread_attr_destroy(pthread_attr_t *attr) 110 { 111 int ret; 112 113 /* Check for invalid arguments: */ 114 if (attr == NULL || *attr == NULL) 115 /* Invalid argument: */ 116 ret = EINVAL; 117 else { 118 /* Free the memory allocated to the attribute object: */ 119 free(*attr); 120 121 /* 122 * Leave the attribute pointer NULL now that the memory 123 * has been freed: 124 */ 125 *attr = NULL; 126 ret = 0; 127 } 128 return(ret); 129 } 130 131 __weak_reference(_pthread_attr_get_np, pthread_attr_get_np); 132 133 int 134 _pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst) 135 { 136 struct pthread *curthread; 137 struct pthread_attr attr; 138 int ret; 139 140 if (pid == NULL || dst == NULL || *dst == NULL) 141 return (EINVAL); 142 143 curthread = _get_curthread(); 144 if ((ret = _thr_ref_add(curthread, pid, /*include dead*/0)) != 0) 145 return (ret); 146 attr = pid->attr; 147 if (pid->tlflags & TLFLAGS_DETACHED) 148 attr.flags |= PTHREAD_DETACHED; 149 _thr_ref_delete(curthread, pid); 150 memcpy(*dst, &attr, sizeof(struct pthread_attr)); 151 152 return (0); 153 } 154 155 __weak_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate); 156 157 int 158 _pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) 159 { 160 int ret; 161 162 /* Check for invalid arguments: */ 163 if (attr == NULL || *attr == NULL || detachstate == NULL) 164 ret = EINVAL; 165 else { 166 /* Check if the detached flag is set: */ 167 if ((*attr)->flags & PTHREAD_DETACHED) 168 /* Return detached: */ 169 *detachstate = PTHREAD_CREATE_DETACHED; 170 else 171 /* Return joinable: */ 172 *detachstate = PTHREAD_CREATE_JOINABLE; 173 ret = 0; 174 } 175 return(ret); 176 } 177 178 __weak_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize); 179 180 int 181 _pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) 182 { 183 int ret; 184 185 /* Check for invalid arguments: */ 186 if (attr == NULL || *attr == NULL || guardsize == NULL) 187 ret = EINVAL; 188 else { 189 /* Return the guard size: */ 190 *guardsize = (*attr)->guardsize_attr; 191 ret = 0; 192 } 193 return(ret); 194 } 195 196 __weak_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched); 197 198 int 199 _pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit) 200 { 201 int ret = 0; 202 203 if ((attr == NULL) || (*attr == NULL)) 204 ret = EINVAL; 205 else 206 *sched_inherit = (*attr)->sched_inherit; 207 208 return(ret); 209 } 210 211 __weak_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam); 212 213 int 214 _pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) 215 { 216 int ret = 0; 217 218 if ((attr == NULL) || (*attr == NULL) || (param == NULL)) 219 ret = EINVAL; 220 else 221 param->sched_priority = (*attr)->prio; 222 223 return(ret); 224 } 225 226 __weak_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy); 227 228 int 229 _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) 230 { 231 int ret = 0; 232 233 if ((attr == NULL) || (*attr == NULL) || (policy == NULL)) 234 ret = EINVAL; 235 else 236 *policy = (*attr)->sched_policy; 237 238 return(ret); 239 } 240 241 __weak_reference(_pthread_attr_getscope, pthread_attr_getscope); 242 243 int 244 _pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope) 245 { 246 int ret = 0; 247 248 if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL)) 249 /* Return an invalid argument: */ 250 ret = EINVAL; 251 252 else 253 *contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ? 254 PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; 255 256 return(ret); 257 } 258 259 __weak_reference(_pthread_attr_getstack, pthread_attr_getstack); 260 261 int 262 _pthread_attr_getstack(const pthread_attr_t * __restrict attr, 263 void ** __restrict stackaddr, 264 size_t * __restrict stacksize) 265 { 266 int ret; 267 268 /* Check for invalid arguments: */ 269 if (attr == NULL || *attr == NULL || stackaddr == NULL 270 || stacksize == NULL ) 271 ret = EINVAL; 272 else { 273 /* Return the stack address and size */ 274 *stackaddr = (*attr)->stackaddr_attr; 275 *stacksize = (*attr)->stacksize_attr; 276 ret = 0; 277 } 278 return(ret); 279 } 280 281 __weak_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr); 282 283 int 284 _pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) 285 { 286 int ret; 287 288 /* Check for invalid arguments: */ 289 if (attr == NULL || *attr == NULL || stackaddr == NULL) 290 ret = EINVAL; 291 else { 292 /* Return the stack address: */ 293 *stackaddr = (*attr)->stackaddr_attr; 294 ret = 0; 295 } 296 return(ret); 297 } 298 299 __weak_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize); 300 301 int 302 _pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) 303 { 304 int ret; 305 306 /* Check for invalid arguments: */ 307 if (attr == NULL || *attr == NULL || stacksize == NULL) 308 ret = EINVAL; 309 else { 310 /* Return the stack size: */ 311 *stacksize = (*attr)->stacksize_attr; 312 ret = 0; 313 } 314 return(ret); 315 } 316 317 __weak_reference(_pthread_attr_init, pthread_attr_init); 318 319 int 320 _pthread_attr_init(pthread_attr_t *attr) 321 { 322 int ret; 323 pthread_attr_t pattr; 324 325 _thr_check_init(); 326 327 /* Allocate memory for the attribute object: */ 328 if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) 329 /* Insufficient memory: */ 330 ret = ENOMEM; 331 else { 332 /* Initialise the attribute object with the defaults: */ 333 memcpy(pattr, &_pthread_attr_default, 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 policy; 425 426 if ((attr == NULL) || (*attr == NULL)) 427 return (EINVAL); 428 429 if (param == NULL) 430 return (ENOTSUP); 431 432 policy = (*attr)->sched_policy; 433 434 if (policy == SCHED_FIFO || policy == SCHED_RR) { 435 if (param->sched_priority < _thr_priorities[policy-1].pri_min || 436 param->sched_priority > _thr_priorities[policy-1].pri_max) 437 return (ENOTSUP); 438 } else { 439 /* 440 * Ignore it for SCHED_OTHER now, patches for glib ports 441 * are wrongly using M:N thread library's internal macro 442 * THR_MIN_PRIORITY and THR_MAX_PRIORITY. 443 */ 444 } 445 446 (*attr)->prio = param->sched_priority; 447 448 return (0); 449 } 450 451 __weak_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy); 452 453 int 454 _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) 455 { 456 int ret = 0; 457 458 if ((attr == NULL) || (*attr == NULL)) 459 ret = EINVAL; 460 else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) { 461 ret = ENOTSUP; 462 } else { 463 (*attr)->sched_policy = policy; 464 (*attr)->prio = _thr_priorities[policy-1].pri_default; 465 } 466 return(ret); 467 } 468 469 __weak_reference(_pthread_attr_setscope, pthread_attr_setscope); 470 471 int 472 _pthread_attr_setscope(pthread_attr_t *attr, int contentionscope) 473 { 474 int ret = 0; 475 476 if ((attr == NULL) || (*attr == NULL)) { 477 /* Return an invalid argument: */ 478 ret = EINVAL; 479 } else if ((contentionscope != PTHREAD_SCOPE_PROCESS) && 480 (contentionscope != PTHREAD_SCOPE_SYSTEM)) { 481 ret = EINVAL; 482 } else if (contentionscope == PTHREAD_SCOPE_SYSTEM) { 483 (*attr)->flags |= contentionscope; 484 } else { 485 (*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM; 486 } 487 return (ret); 488 } 489 490 __weak_reference(_pthread_attr_setstack, pthread_attr_setstack); 491 492 int 493 _pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, 494 size_t stacksize) 495 { 496 int ret; 497 498 /* Check for invalid arguments: */ 499 if (attr == NULL || *attr == NULL || stackaddr == NULL 500 || stacksize < PTHREAD_STACK_MIN) 501 ret = EINVAL; 502 else { 503 /* Save the stack address and stack size */ 504 (*attr)->stackaddr_attr = stackaddr; 505 (*attr)->stacksize_attr = stacksize; 506 ret = 0; 507 } 508 return(ret); 509 } 510 511 __weak_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr); 512 513 int 514 _pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) 515 { 516 int ret; 517 518 /* Check for invalid arguments: */ 519 if (attr == NULL || *attr == NULL || stackaddr == NULL) 520 ret = EINVAL; 521 else { 522 /* Save the stack address: */ 523 (*attr)->stackaddr_attr = stackaddr; 524 ret = 0; 525 } 526 return(ret); 527 } 528 529 __weak_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize); 530 531 int 532 _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) 533 { 534 int ret; 535 536 /* Check for invalid arguments: */ 537 if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) 538 ret = EINVAL; 539 else { 540 /* Save the stack size: */ 541 (*attr)->stacksize_attr = stacksize; 542 ret = 0; 543 } 544 return(ret); 545 } 546