thr_attr.c revision 214653
1169689Skan/* 2169689Skan * Copyright (c) 2003 Craig Rodrigues <rodrigc@attbi.com>. 3169689Skan * All rights reserved. 4169689Skan * 5169689Skan * Redistribution and use in source and binary forms, with or without 6169689Skan * modification, are permitted provided that the following conditions 7169689Skan * are met: 8169689Skan * 1. Redistributions of source code must retain the above copyright 9169689Skan * notice, this list of conditions and the following disclaimer. 10169689Skan * 2. Redistributions in binary form must reproduce the above copyright 11169689Skan * notice, this list of conditions and the following disclaimer in the 12169689Skan * documentation and/or other materials provided with the distribution. 13169689Skan * 3. All advertising materials mentioning features or use of this software 14169689Skan * must display the following acknowledgement: 15169689Skan * This product includes software developed by Craig Rodrigues. 16169689Skan * 4. Neither the name of the author nor the names of any co-contributors 17169689Skan * may be used to endorse or promote products derived from this software 18169689Skan * without specific prior written permission. 19169689Skan * 20169689Skan * THIS SOFTWARE IS PROVIDED BY CRAIG RODRIGUES AND CONTRIBUTORS ``AS IS'' AND 21169689Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23169689Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30169689Skan * SUCH DAMAGE. 31169689Skan * 32169689Skan */ 33169689Skan 34169689Skan/* 35169689Skan * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. 36169689Skan * Copyright (C) 2001 Jason Evans <jasone@freebsd.org>. 37169689Skan * Copyright (c) 2002,2003 Alexey Zelkin <phantom@FreeBSD.org> 38169689Skan * All rights reserved. 39169689Skan * 40169689Skan * Redistribution and use in source and binary forms, with or without 41169689Skan * modification, are permitted provided that the following conditions 42169689Skan * are met: 43169689Skan * 1. Redistributions of source code must retain the above copyright 44169689Skan * notice(s), this list of conditions and the following disclaimer 45169689Skan * unmodified other than the allowable addition of one or more 46169689Skan * copyright notices. 47169689Skan * 2. Redistributions in binary form must reproduce the above copyright 48169689Skan * notice(s), this list of conditions and the following disclaimer in 49169689Skan * the documentation and/or other materials provided with the 50169689Skan * distribution. 51169689Skan * 52169689Skan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY 53169689Skan * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 55169689Skan * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE 56169689Skan * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 57169689Skan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 58169689Skan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 59169689Skan * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 60169689Skan * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 61169689Skan * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 62169689Skan * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 63169689Skan */ 64169689Skan 65169689Skan/* 66169689Skan * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. 67169689Skan * All rights reserved. 68169689Skan * 69169689Skan * Redistribution and use in source and binary forms, with or without 70169689Skan * modification, are permitted provided that the following conditions 71169689Skan * are met: 72169689Skan * 1. Redistributions of source code must retain the above copyright 73169689Skan * notice, this list of conditions and the following disclaimer. 74169689Skan * 2. Redistributions in binary form must reproduce the above copyright 75169689Skan * notice, this list of conditions and the following disclaimer in the 76169689Skan * documentation and/or other materials provided with the distribution. 77169689Skan * 3. Neither the name of the author nor the names of any co-contributors 78169689Skan * may be used to endorse or promote products derived from this software 79169689Skan * without specific prior written permission. 80169689Skan * 81169689Skan * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 82169689Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 83169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 84169689Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 85169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 86169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 87169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 88169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 89169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 90169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 91169689Skan * SUCH DAMAGE. 92169689Skan * 93169689Skan * $FreeBSD: head/lib/libthr/thread/thr_attr.c 214653 2010-11-02 02:13:13Z davidxu $ 94169689Skan */ 95169689Skan 96169689Skan#include "namespace.h" 97169689Skan#include <errno.h> 98169689Skan#include <pthread.h> 99169689Skan#include <stdlib.h> 100169689Skan#include <string.h> 101169689Skan#include <pthread_np.h> 102169689Skan#include <sys/sysctl.h> 103169689Skan#include "un-namespace.h" 104169689Skan 105169689Skan#include "thr_private.h" 106169689Skan 107169689Skanstatic size_t _get_kern_cpuset_size(void); 108169689Skan 109169689Skan__weak_reference(_pthread_attr_destroy, pthread_attr_destroy); 110169689Skan 111169689Skanint 112169689Skan_pthread_attr_destroy(pthread_attr_t *attr) 113169689Skan{ 114169689Skan int ret; 115169689Skan 116169689Skan /* Check for invalid arguments: */ 117169689Skan if (attr == NULL || *attr == NULL) 118169689Skan /* Invalid argument: */ 119169689Skan ret = EINVAL; 120169689Skan else { 121169689Skan if ((*attr)->cpuset != NULL) 122169689Skan free((*attr)->cpuset); 123169689Skan /* Free the memory allocated to the attribute object: */ 124169689Skan free(*attr); 125169689Skan 126169689Skan /* 127169689Skan * Leave the attribute pointer NULL now that the memory 128169689Skan * has been freed: 129169689Skan */ 130169689Skan *attr = NULL; 131169689Skan ret = 0; 132169689Skan } 133169689Skan return(ret); 134169689Skan} 135169689Skan 136169689Skan__weak_reference(_pthread_attr_get_np, pthread_attr_get_np); 137169689Skan 138169689Skanint 139169689Skan_pthread_attr_get_np(pthread_t pthread, pthread_attr_t *dstattr) 140169689Skan{ 141169689Skan struct pthread *curthread; 142169689Skan struct pthread_attr attr, *dst; 143169689Skan int ret; 144169689Skan size_t kern_size; 145169689Skan 146169689Skan if (pthread == NULL || dstattr == NULL || (dst = *dstattr) == NULL) 147169689Skan return (EINVAL); 148169689Skan kern_size = _get_kern_cpuset_size(); 149169689Skan if (dst->cpuset == NULL) { 150169689Skan dst->cpuset = calloc(1, kern_size); 151169689Skan dst->cpusetsize = kern_size; 152169689Skan } 153169689Skan curthread = _get_curthread(); 154169689Skan if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/0)) != 0) 155169689Skan return (ret); 156169689Skan attr = pthread->attr; 157169689Skan if (pthread->flags & THR_FLAGS_DETACHED) 158169689Skan attr.flags |= PTHREAD_DETACHED; 159169689Skan ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, TID(pthread), 160169689Skan dst->cpusetsize, dst->cpuset); 161169689Skan if (ret == -1) 162169689Skan ret = errno; 163169689Skan THR_THREAD_UNLOCK(curthread, pthread); 164169689Skan if (ret == 0) { 165169689Skan memcpy(&dst->pthread_attr_start_copy, 166169689Skan &attr.pthread_attr_start_copy, 167169689Skan offsetof(struct pthread_attr, pthread_attr_end_copy) - 168169689Skan offsetof(struct pthread_attr, pthread_attr_start_copy)); 169169689Skan } 170169689Skan return (ret); 171169689Skan} 172169689Skan 173169689Skan__weak_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate); 174169689Skan 175169689Skanint 176169689Skan_pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) 177169689Skan{ 178169689Skan int ret; 179169689Skan 180169689Skan /* Check for invalid arguments: */ 181169689Skan if (attr == NULL || *attr == NULL || detachstate == NULL) 182169689Skan ret = EINVAL; 183169689Skan else { 184169689Skan /* Check if the detached flag is set: */ 185169689Skan if ((*attr)->flags & PTHREAD_DETACHED) 186169689Skan /* Return detached: */ 187169689Skan *detachstate = PTHREAD_CREATE_DETACHED; 188169689Skan else 189169689Skan /* Return joinable: */ 190169689Skan *detachstate = PTHREAD_CREATE_JOINABLE; 191169689Skan ret = 0; 192169689Skan } 193169689Skan return(ret); 194169689Skan} 195169689Skan 196169689Skan__weak_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize); 197169689Skan 198169689Skanint 199169689Skan_pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) 200169689Skan{ 201169689Skan int ret; 202169689Skan 203169689Skan /* Check for invalid arguments: */ 204169689Skan if (attr == NULL || *attr == NULL || guardsize == NULL) 205169689Skan ret = EINVAL; 206169689Skan else { 207169689Skan /* Return the guard size: */ 208169689Skan *guardsize = (*attr)->guardsize_attr; 209169689Skan ret = 0; 210169689Skan } 211169689Skan return(ret); 212169689Skan} 213169689Skan 214169689Skan__weak_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched); 215169689Skan 216169689Skanint 217169689Skan_pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit) 218169689Skan{ 219169689Skan int ret = 0; 220169689Skan 221169689Skan if ((attr == NULL) || (*attr == NULL)) 222169689Skan ret = EINVAL; 223169689Skan else 224169689Skan *sched_inherit = (*attr)->sched_inherit; 225169689Skan 226169689Skan return(ret); 227169689Skan} 228169689Skan 229169689Skan__weak_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam); 230169689Skan 231169689Skanint 232169689Skan_pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) 233169689Skan{ 234169689Skan int ret = 0; 235169689Skan 236169689Skan if ((attr == NULL) || (*attr == NULL) || (param == NULL)) 237169689Skan ret = EINVAL; 238169689Skan else 239169689Skan param->sched_priority = (*attr)->prio; 240169689Skan 241169689Skan return(ret); 242169689Skan} 243169689Skan 244169689Skan__weak_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy); 245169689Skan 246169689Skanint 247169689Skan_pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) 248169689Skan{ 249169689Skan int ret = 0; 250169689Skan 251169689Skan if ((attr == NULL) || (*attr == NULL) || (policy == NULL)) 252169689Skan ret = EINVAL; 253169689Skan else 254169689Skan *policy = (*attr)->sched_policy; 255169689Skan 256169689Skan return(ret); 257169689Skan} 258169689Skan 259169689Skan__weak_reference(_pthread_attr_getscope, pthread_attr_getscope); 260169689Skan 261169689Skanint 262169689Skan_pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope) 263169689Skan{ 264169689Skan int ret = 0; 265169689Skan 266169689Skan if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL)) 267169689Skan /* Return an invalid argument: */ 268169689Skan ret = EINVAL; 269169689Skan 270169689Skan else 271169689Skan *contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ? 272169689Skan PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; 273169689Skan 274169689Skan return(ret); 275169689Skan} 276169689Skan 277169689Skan__weak_reference(_pthread_attr_getstack, pthread_attr_getstack); 278169689Skan 279169689Skanint 280169689Skan_pthread_attr_getstack(const pthread_attr_t * __restrict attr, 281169689Skan void ** __restrict stackaddr, 282169689Skan size_t * __restrict stacksize) 283169689Skan{ 284169689Skan int ret; 285169689Skan 286169689Skan /* Check for invalid arguments: */ 287169689Skan if (attr == NULL || *attr == NULL || stackaddr == NULL 288169689Skan || stacksize == NULL ) 289169689Skan ret = EINVAL; 290169689Skan else { 291169689Skan /* Return the stack address and size */ 292169689Skan *stackaddr = (*attr)->stackaddr_attr; 293169689Skan *stacksize = (*attr)->stacksize_attr; 294169689Skan ret = 0; 295169689Skan } 296169689Skan return(ret); 297169689Skan} 298169689Skan 299169689Skan__weak_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr); 300169689Skan 301169689Skanint 302169689Skan_pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) 303169689Skan{ 304169689Skan int ret; 305169689Skan 306169689Skan /* Check for invalid arguments: */ 307169689Skan if (attr == NULL || *attr == NULL || stackaddr == NULL) 308169689Skan ret = EINVAL; 309169689Skan else { 310169689Skan /* Return the stack address: */ 311169689Skan *stackaddr = (*attr)->stackaddr_attr; 312169689Skan ret = 0; 313169689Skan } 314169689Skan return(ret); 315169689Skan} 316169689Skan 317169689Skan__weak_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize); 318169689Skan 319169689Skanint 320169689Skan_pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) 321169689Skan{ 322169689Skan int ret; 323169689Skan 324169689Skan /* Check for invalid arguments: */ 325169689Skan if (attr == NULL || *attr == NULL || stacksize == NULL) 326169689Skan ret = EINVAL; 327169689Skan else { 328169689Skan /* Return the stack size: */ 329169689Skan *stacksize = (*attr)->stacksize_attr; 330169689Skan ret = 0; 331169689Skan } 332169689Skan return(ret); 333169689Skan} 334169689Skan 335169689Skan__weak_reference(_pthread_attr_init, pthread_attr_init); 336169689Skan 337169689Skanint 338169689Skan_pthread_attr_init(pthread_attr_t *attr) 339169689Skan{ 340169689Skan int ret; 341169689Skan pthread_attr_t pattr; 342169689Skan 343169689Skan _thr_check_init(); 344169689Skan 345169689Skan /* Allocate memory for the attribute object: */ 346169689Skan if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) 347169689Skan /* Insufficient memory: */ 348169689Skan ret = ENOMEM; 349169689Skan else { 350169689Skan /* Initialise the attribute object with the defaults: */ 351169689Skan memcpy(pattr, &_pthread_attr_default, sizeof(struct pthread_attr)); 352169689Skan 353169689Skan /* Return a pointer to the attribute object: */ 354169689Skan *attr = pattr; 355169689Skan ret = 0; 356169689Skan } 357169689Skan return(ret); 358169689Skan} 359169689Skan 360169689Skan__weak_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np); 361169689Skan 362169689Skanint 363169689Skan_pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) 364169689Skan{ 365169689Skan int ret; 366169689Skan 367169689Skan if (attr == NULL || *attr == NULL) { 368169689Skan ret = EINVAL; 369169689Skan } else { 370169689Skan (*attr)->suspend = THR_CREATE_SUSPENDED; 371169689Skan ret = 0; 372169689Skan } 373169689Skan return(ret); 374169689Skan} 375169689Skan 376169689Skan__weak_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate); 377169689Skan 378169689Skanint 379169689Skan_pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 380169689Skan{ 381169689Skan int ret; 382169689Skan 383169689Skan /* Check for invalid arguments: */ 384169689Skan if (attr == NULL || *attr == NULL || 385169689Skan (detachstate != PTHREAD_CREATE_DETACHED && 386169689Skan detachstate != PTHREAD_CREATE_JOINABLE)) 387169689Skan ret = EINVAL; 388169689Skan else { 389169689Skan /* Check if detached state: */ 390169689Skan if (detachstate == PTHREAD_CREATE_DETACHED) 391169689Skan /* Set the detached flag: */ 392169689Skan (*attr)->flags |= PTHREAD_DETACHED; 393169689Skan else 394169689Skan /* Reset the detached flag: */ 395169689Skan (*attr)->flags &= ~PTHREAD_DETACHED; 396169689Skan ret = 0; 397169689Skan } 398169689Skan return(ret); 399169689Skan} 400169689Skan 401169689Skan__weak_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize); 402169689Skan 403169689Skanint 404169689Skan_pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) 405169689Skan{ 406169689Skan int ret; 407169689Skan 408169689Skan /* Check for invalid arguments. */ 409169689Skan if (attr == NULL || *attr == NULL) 410169689Skan ret = EINVAL; 411169689Skan else { 412169689Skan /* Save the stack size. */ 413169689Skan (*attr)->guardsize_attr = guardsize; 414169689Skan ret = 0; 415169689Skan } 416169689Skan return(ret); 417169689Skan} 418169689Skan 419169689Skan__weak_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched); 420169689Skan 421169689Skanint 422169689Skan_pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit) 423169689Skan{ 424169689Skan int ret = 0; 425169689Skan 426169689Skan if ((attr == NULL) || (*attr == NULL)) 427169689Skan ret = EINVAL; 428169689Skan else if (sched_inherit != PTHREAD_INHERIT_SCHED && 429169689Skan sched_inherit != PTHREAD_EXPLICIT_SCHED) 430169689Skan ret = ENOTSUP; 431169689Skan else 432169689Skan (*attr)->sched_inherit = sched_inherit; 433169689Skan 434169689Skan return(ret); 435169689Skan} 436169689Skan 437169689Skan__weak_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam); 438169689Skan 439169689Skanint 440169689Skan_pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param) 441169689Skan{ 442169689Skan int policy; 443169689Skan 444169689Skan if ((attr == NULL) || (*attr == NULL)) 445169689Skan return (EINVAL); 446169689Skan 447169689Skan if (param == NULL) 448169689Skan return (ENOTSUP); 449169689Skan 450169689Skan policy = (*attr)->sched_policy; 451169689Skan 452169689Skan if (policy == SCHED_FIFO || policy == SCHED_RR) { 453169689Skan if (param->sched_priority < _thr_priorities[policy-1].pri_min || 454169689Skan param->sched_priority > _thr_priorities[policy-1].pri_max) 455169689Skan return (ENOTSUP); 456169689Skan } else { 457169689Skan /* 458169689Skan * Ignore it for SCHED_OTHER now, patches for glib ports 459169689Skan * are wrongly using M:N thread library's internal macro 460169689Skan * THR_MIN_PRIORITY and THR_MAX_PRIORITY. 461169689Skan */ 462169689Skan } 463169689Skan 464169689Skan (*attr)->prio = param->sched_priority; 465169689Skan 466169689Skan return (0); 467169689Skan} 468169689Skan 469169689Skan__weak_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy); 470169689Skan 471169689Skanint 472169689Skan_pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) 473169689Skan{ 474169689Skan int ret = 0; 475169689Skan 476169689Skan if ((attr == NULL) || (*attr == NULL)) 477169689Skan ret = EINVAL; 478169689Skan else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) { 479169689Skan ret = ENOTSUP; 480169689Skan } else { 481169689Skan (*attr)->sched_policy = policy; 482169689Skan (*attr)->prio = _thr_priorities[policy-1].pri_default; 483169689Skan } 484169689Skan return(ret); 485169689Skan} 486169689Skan 487169689Skan__weak_reference(_pthread_attr_setscope, pthread_attr_setscope); 488169689Skan 489169689Skanint 490169689Skan_pthread_attr_setscope(pthread_attr_t *attr, int contentionscope) 491169689Skan{ 492169689Skan int ret = 0; 493169689Skan 494169689Skan if ((attr == NULL) || (*attr == NULL)) { 495169689Skan /* Return an invalid argument: */ 496169689Skan ret = EINVAL; 497169689Skan } else if ((contentionscope != PTHREAD_SCOPE_PROCESS) && 498169689Skan (contentionscope != PTHREAD_SCOPE_SYSTEM)) { 499169689Skan ret = EINVAL; 500169689Skan } else if (contentionscope == PTHREAD_SCOPE_SYSTEM) { 501169689Skan (*attr)->flags |= contentionscope; 502169689Skan } else { 503169689Skan (*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM; 504169689Skan } 505169689Skan return (ret); 506169689Skan} 507169689Skan 508169689Skan__weak_reference(_pthread_attr_setstack, pthread_attr_setstack); 509169689Skan 510169689Skanint 511169689Skan_pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, 512169689Skan size_t stacksize) 513169689Skan{ 514169689Skan int ret; 515169689Skan 516169689Skan /* Check for invalid arguments: */ 517169689Skan if (attr == NULL || *attr == NULL || stackaddr == NULL 518169689Skan || stacksize < PTHREAD_STACK_MIN) 519169689Skan ret = EINVAL; 520169689Skan else { 521169689Skan /* Save the stack address and stack size */ 522169689Skan (*attr)->stackaddr_attr = stackaddr; 523169689Skan (*attr)->stacksize_attr = stacksize; 524169689Skan ret = 0; 525169689Skan } 526169689Skan return(ret); 527169689Skan} 528169689Skan 529169689Skan__weak_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr); 530169689Skan 531169689Skanint 532169689Skan_pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) 533169689Skan{ 534169689Skan int ret; 535169689Skan 536169689Skan /* Check for invalid arguments: */ 537169689Skan if (attr == NULL || *attr == NULL || stackaddr == NULL) 538169689Skan ret = EINVAL; 539169689Skan else { 540169689Skan /* Save the stack address: */ 541169689Skan (*attr)->stackaddr_attr = stackaddr; 542169689Skan ret = 0; 543169689Skan } 544169689Skan return(ret); 545169689Skan} 546169689Skan 547169689Skan__weak_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize); 548169689Skan 549169689Skanint 550169689Skan_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) 551169689Skan{ 552169689Skan int ret; 553169689Skan 554169689Skan /* Check for invalid arguments: */ 555169689Skan if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) 556169689Skan ret = EINVAL; 557169689Skan else { 558169689Skan /* Save the stack size: */ 559169689Skan (*attr)->stacksize_attr = stacksize; 560169689Skan ret = 0; 561169689Skan } 562169689Skan return(ret); 563169689Skan} 564169689Skan 565169689Skanstatic size_t 566169689Skan_get_kern_cpuset_size(void) 567169689Skan{ 568169689Skan static int kern_cpuset_size = 0; 569169689Skan 570169689Skan if (kern_cpuset_size == 0) { 571169689Skan size_t len; 572169689Skan 573169689Skan len = sizeof(kern_cpuset_size); 574169689Skan if (sysctlbyname("kern.sched.cpusetsize", &kern_cpuset_size, 575169689Skan &len, NULL, 0)) 576169689Skan PANIC("failed to get sysctl kern.sched.cpusetsize"); 577169689Skan } 578169689Skan 579169689Skan return (kern_cpuset_size); 580169689Skan} 581169689Skan 582169689Skan__weak_reference(_pthread_attr_setaffinity_np, pthread_attr_setaffinity_np); 583169689Skanint 584169689Skan_pthread_attr_setaffinity_np(pthread_attr_t *pattr, size_t cpusetsize, 585169689Skan const cpuset_t *cpusetp) 586169689Skan{ 587169689Skan pthread_attr_t attr; 588169689Skan int ret; 589169689Skan 590169689Skan if (pattr == NULL || (attr = (*pattr)) == NULL) 591169689Skan ret = EINVAL; 592169689Skan else { 593169689Skan if (cpusetsize == 0 || cpusetp == NULL) { 594169689Skan if (attr->cpuset != NULL) { 595169689Skan free(attr->cpuset); 596169689Skan attr->cpuset = NULL; 597169689Skan attr->cpusetsize = 0; 598169689Skan } 599169689Skan return (0); 600169689Skan } 601169689Skan size_t kern_size = _get_kern_cpuset_size(); 602169689Skan /* Kernel rejects small set, we check it here too. */ 603169689Skan if (cpusetsize < kern_size) 604169689Skan return (ERANGE); 605169689Skan if (cpusetsize > kern_size) { 606169689Skan /* Kernel checks invalid bits, we check it here too. */ 607169689Skan size_t i; 608169689Skan for (i = kern_size; i < cpusetsize; ++i) { 609169689Skan if (((char *)cpusetp)[i]) 610169689Skan return (EINVAL); 611169689Skan } 612169689Skan } 613169689Skan if (attr->cpuset == NULL) { 614169689Skan attr->cpuset = calloc(1, kern_size); 615169689Skan if (attr->cpuset == NULL) 616169689Skan return (errno); 617169689Skan attr->cpusetsize = kern_size; 618169689Skan } 619169689Skan memcpy(attr->cpuset, cpusetp, kern_size); 620169689Skan ret = 0; 621169689Skan } 622169689Skan return (ret); 623169689Skan} 624169689Skan 625169689Skan__weak_reference(_pthread_attr_getaffinity_np, pthread_attr_getaffinity_np); 626169689Skanint 627169689Skan_pthread_attr_getaffinity_np(const pthread_attr_t *pattr, size_t cpusetsize, 628169689Skan cpuset_t *cpusetp) 629169689Skan{ 630169689Skan pthread_attr_t attr; 631169689Skan int ret = 0; 632169689Skan 633169689Skan if (pattr == NULL || (attr = (*pattr)) == NULL) 634169689Skan ret = EINVAL; 635169689Skan else { 636169689Skan /* Kernel rejects small set, we check it here too. */ 637169689Skan size_t kern_size = _get_kern_cpuset_size(); 638169689Skan if (cpusetsize < kern_size) 639169689Skan return (ERANGE); 640169689Skan if (attr->cpuset != NULL) 641169689Skan memcpy(cpusetp, attr->cpuset, MIN(cpusetsize, 642169689Skan attr->cpusetsize)); 643169689Skan else 644169689Skan memset(cpusetp, -1, kern_size); 645169689Skan if (cpusetsize > kern_size) 646169689Skan memset(((char *)cpusetp) + kern_size, 0, 647169689Skan cpusetsize - kern_size); 648169689Skan } 649169689Skan return (ret); 650169689Skan} 651169689Skan