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