1112918Sjeff/* 2112918Sjeff * Copyright (c) 2003 Craig Rodrigues <rodrigc@attbi.com>. 3112918Sjeff * All rights reserved. 4112918Sjeff * 5112918Sjeff * Redistribution and use in source and binary forms, with or without 6112918Sjeff * modification, are permitted provided that the following conditions 7112918Sjeff * are met: 8112918Sjeff * 1. Redistributions of source code must retain the above copyright 9112918Sjeff * notice, this list of conditions and the following disclaimer. 10112918Sjeff * 2. Redistributions in binary form must reproduce the above copyright 11112918Sjeff * notice, this list of conditions and the following disclaimer in the 12112918Sjeff * documentation and/or other materials provided with the distribution. 13112918Sjeff * 3. All advertising materials mentioning features or use of this software 14112918Sjeff * must display the following acknowledgement: 15112918Sjeff * This product includes software developed by Craig Rodrigues. 16112918Sjeff * 4. Neither the name of the author nor the names of any co-contributors 17112918Sjeff * may be used to endorse or promote products derived from this software 18112918Sjeff * without specific prior written permission. 19112918Sjeff * 20112918Sjeff * THIS SOFTWARE IS PROVIDED BY CRAIG RODRIGUES AND CONTRIBUTORS ``AS IS'' AND 21112918Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22112918Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23112918Sjeff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24112918Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25112918Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26112918Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27112918Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28112918Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29112918Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30112918Sjeff * SUCH DAMAGE. 31112918Sjeff * 32112918Sjeff */ 33112918Sjeff 34112918Sjeff/* 35112918Sjeff * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. 36112918Sjeff * Copyright (C) 2001 Jason Evans <jasone@freebsd.org>. 37112918Sjeff * Copyright (c) 2002,2003 Alexey Zelkin <phantom@FreeBSD.org> 38112918Sjeff * All rights reserved. 39112918Sjeff * 40112918Sjeff * Redistribution and use in source and binary forms, with or without 41112918Sjeff * modification, are permitted provided that the following conditions 42112918Sjeff * are met: 43112918Sjeff * 1. Redistributions of source code must retain the above copyright 44112918Sjeff * notice(s), this list of conditions and the following disclaimer 45112918Sjeff * unmodified other than the allowable addition of one or more 46112918Sjeff * copyright notices. 47112918Sjeff * 2. Redistributions in binary form must reproduce the above copyright 48112918Sjeff * notice(s), this list of conditions and the following disclaimer in 49112918Sjeff * the documentation and/or other materials provided with the 50112918Sjeff * distribution. 51112918Sjeff * 52112918Sjeff * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY 53112918Sjeff * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54112918Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 55112918Sjeff * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE 56112918Sjeff * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 57112918Sjeff * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 58112918Sjeff * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 59112918Sjeff * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 60112918Sjeff * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 61112918Sjeff * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 62112918Sjeff * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 63112918Sjeff */ 64112918Sjeff 65144518Sdavidxu/* 66144518Sdavidxu * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. 67144518Sdavidxu * All rights reserved. 68144518Sdavidxu * 69144518Sdavidxu * Redistribution and use in source and binary forms, with or without 70144518Sdavidxu * modification, are permitted provided that the following conditions 71144518Sdavidxu * are met: 72144518Sdavidxu * 1. Redistributions of source code must retain the above copyright 73144518Sdavidxu * notice, this list of conditions and the following disclaimer. 74144518Sdavidxu * 2. Redistributions in binary form must reproduce the above copyright 75144518Sdavidxu * notice, this list of conditions and the following disclaimer in the 76144518Sdavidxu * documentation and/or other materials provided with the distribution. 77165967Simp * 3. Neither the name of the author nor the names of any co-contributors 78144518Sdavidxu * may be used to endorse or promote products derived from this software 79144518Sdavidxu * without specific prior written permission. 80144518Sdavidxu * 81144518Sdavidxu * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 82144518Sdavidxu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 83144518Sdavidxu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 84144518Sdavidxu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 85144518Sdavidxu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 86144518Sdavidxu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 87144518Sdavidxu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 88144518Sdavidxu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 89144518Sdavidxu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 90144518Sdavidxu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 91144518Sdavidxu * SUCH DAMAGE. 92144518Sdavidxu * 93144518Sdavidxu * $FreeBSD$ 94144518Sdavidxu */ 95112918Sjeff 96157457Sdavidxu#include "namespace.h" 97112918Sjeff#include <errno.h> 98112918Sjeff#include <pthread.h> 99112918Sjeff#include <stdlib.h> 100112918Sjeff#include <string.h> 101144518Sdavidxu#include <pthread_np.h> 102176815Sdavidxu#include <sys/sysctl.h> 103157457Sdavidxu#include "un-namespace.h" 104112918Sjeff 105112918Sjeff#include "thr_private.h" 106112918Sjeff 107214334Sdavidxustatic size_t _get_kern_cpuset_size(void); 108214334Sdavidxu 109125963Smtm__weak_reference(_pthread_attr_destroy, pthread_attr_destroy); 110112918Sjeff 111112918Sjeffint 112144518Sdavidxu_pthread_attr_destroy(pthread_attr_t *attr) 113112918Sjeff{ 114144518Sdavidxu int ret; 115112918Sjeff 116144518Sdavidxu /* Check for invalid arguments: */ 117144518Sdavidxu if (attr == NULL || *attr == NULL) 118144518Sdavidxu /* Invalid argument: */ 119144518Sdavidxu ret = EINVAL; 120144518Sdavidxu else { 121214334Sdavidxu if ((*attr)->cpuset != NULL) 122214334Sdavidxu free((*attr)->cpuset); 123144518Sdavidxu /* Free the memory allocated to the attribute object: */ 124144518Sdavidxu free(*attr); 125112918Sjeff 126144518Sdavidxu /* 127144518Sdavidxu * Leave the attribute pointer NULL now that the memory 128144518Sdavidxu * has been freed: 129144518Sdavidxu */ 130144518Sdavidxu *attr = NULL; 131144518Sdavidxu ret = 0; 132144518Sdavidxu } 133144518Sdavidxu return(ret); 134112918Sjeff} 135112918Sjeff 136144518Sdavidxu__weak_reference(_pthread_attr_get_np, pthread_attr_get_np); 137144518Sdavidxu 138112918Sjeffint 139214334Sdavidxu_pthread_attr_get_np(pthread_t pthread, pthread_attr_t *dstattr) 140112918Sjeff{ 141144518Sdavidxu struct pthread *curthread; 142214334Sdavidxu struct pthread_attr attr, *dst; 143144518Sdavidxu int ret; 144214413Sdavidxu size_t kern_size; 145144518Sdavidxu 146214335Sdavidxu if (pthread == NULL || dstattr == NULL || (dst = *dstattr) == NULL) 147112918Sjeff return (EINVAL); 148214413Sdavidxu kern_size = _get_kern_cpuset_size(); 149214413Sdavidxu if (dst->cpuset == NULL) { 150214413Sdavidxu dst->cpuset = calloc(1, kern_size); 151214413Sdavidxu dst->cpusetsize = kern_size; 152214334Sdavidxu } 153144518Sdavidxu curthread = _get_curthread(); 154212536Sdavidxu if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/0)) != 0) 155144518Sdavidxu return (ret); 156212536Sdavidxu attr = pthread->attr; 157212536Sdavidxu if (pthread->flags & THR_FLAGS_DETACHED) 158154126Sdavidxu attr.flags |= PTHREAD_DETACHED; 159214334Sdavidxu ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, TID(pthread), 160214334Sdavidxu dst->cpusetsize, dst->cpuset); 161214334Sdavidxu if (ret == -1) 162214334Sdavidxu ret = errno; 163212536Sdavidxu THR_THREAD_UNLOCK(curthread, pthread); 164214334Sdavidxu if (ret == 0) { 165214334Sdavidxu memcpy(&dst->pthread_attr_start_copy, 166214334Sdavidxu &attr.pthread_attr_start_copy, 167214334Sdavidxu offsetof(struct pthread_attr, pthread_attr_end_copy) - 168214334Sdavidxu offsetof(struct pthread_attr, pthread_attr_start_copy)); 169214334Sdavidxu } 170214334Sdavidxu return (ret); 171112918Sjeff} 172112918Sjeff 173144518Sdavidxu__weak_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate); 174144518Sdavidxu 175112918Sjeffint 176144518Sdavidxu_pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) 177112918Sjeff{ 178144518Sdavidxu int ret; 179144518Sdavidxu 180144518Sdavidxu /* Check for invalid arguments: */ 181144518Sdavidxu if (attr == NULL || *attr == NULL || detachstate == NULL) 182144518Sdavidxu ret = EINVAL; 183144518Sdavidxu else { 184144518Sdavidxu /* Check if the detached flag is set: */ 185144518Sdavidxu if ((*attr)->flags & PTHREAD_DETACHED) 186144518Sdavidxu /* Return detached: */ 187144518Sdavidxu *detachstate = PTHREAD_CREATE_DETACHED; 188144518Sdavidxu else 189144518Sdavidxu /* Return joinable: */ 190144518Sdavidxu *detachstate = PTHREAD_CREATE_JOINABLE; 191144518Sdavidxu ret = 0; 192112918Sjeff } 193144518Sdavidxu return(ret); 194112918Sjeff} 195112918Sjeff 196144518Sdavidxu__weak_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize); 197144518Sdavidxu 198112918Sjeffint 199144518Sdavidxu_pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) 200112918Sjeff{ 201144518Sdavidxu int ret; 202112918Sjeff 203144518Sdavidxu /* Check for invalid arguments: */ 204144518Sdavidxu if (attr == NULL || *attr == NULL || guardsize == NULL) 205144518Sdavidxu ret = EINVAL; 206144518Sdavidxu else { 207144518Sdavidxu /* Return the guard size: */ 208144518Sdavidxu *guardsize = (*attr)->guardsize_attr; 209144518Sdavidxu ret = 0; 210144518Sdavidxu } 211144518Sdavidxu return(ret); 212112918Sjeff} 213112918Sjeff 214144518Sdavidxu__weak_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched); 215144518Sdavidxu 216112918Sjeffint 217144518Sdavidxu_pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit) 218112918Sjeff{ 219144518Sdavidxu int ret = 0; 220112918Sjeff 221144518Sdavidxu if ((attr == NULL) || (*attr == NULL)) 222144518Sdavidxu ret = EINVAL; 223144518Sdavidxu else 224144518Sdavidxu *sched_inherit = (*attr)->sched_inherit; 225112918Sjeff 226144518Sdavidxu return(ret); 227112918Sjeff} 228112918Sjeff 229144518Sdavidxu__weak_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam); 230144518Sdavidxu 231112918Sjeffint 232144518Sdavidxu_pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) 233112918Sjeff{ 234144518Sdavidxu int ret = 0; 235112918Sjeff 236144518Sdavidxu if ((attr == NULL) || (*attr == NULL) || (param == NULL)) 237144518Sdavidxu ret = EINVAL; 238144518Sdavidxu else 239144518Sdavidxu param->sched_priority = (*attr)->prio; 240112918Sjeff 241144518Sdavidxu return(ret); 242112918Sjeff} 243112918Sjeff 244144518Sdavidxu__weak_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy); 245144518Sdavidxu 246112918Sjeffint 247144518Sdavidxu_pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) 248112918Sjeff{ 249144518Sdavidxu int ret = 0; 250112918Sjeff 251144518Sdavidxu if ((attr == NULL) || (*attr == NULL) || (policy == NULL)) 252144518Sdavidxu ret = EINVAL; 253144518Sdavidxu else 254144518Sdavidxu *policy = (*attr)->sched_policy; 255112918Sjeff 256144518Sdavidxu return(ret); 257144518Sdavidxu} 258112918Sjeff 259144518Sdavidxu__weak_reference(_pthread_attr_getscope, pthread_attr_getscope); 260112918Sjeff 261112918Sjeffint 262144518Sdavidxu_pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope) 263112918Sjeff{ 264144518Sdavidxu int ret = 0; 265112918Sjeff 266144518Sdavidxu if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL)) 267144518Sdavidxu /* Return an invalid argument: */ 268144518Sdavidxu ret = EINVAL; 269112918Sjeff 270144518Sdavidxu else 271144518Sdavidxu *contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ? 272144518Sdavidxu PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; 273112918Sjeff 274144518Sdavidxu return(ret); 275112918Sjeff} 276112918Sjeff 277144518Sdavidxu__weak_reference(_pthread_attr_getstack, pthread_attr_getstack); 278144518Sdavidxu 279112918Sjeffint 280144518Sdavidxu_pthread_attr_getstack(const pthread_attr_t * __restrict attr, 281144518Sdavidxu void ** __restrict stackaddr, 282144518Sdavidxu size_t * __restrict stacksize) 283112918Sjeff{ 284144518Sdavidxu int ret; 285112918Sjeff 286144518Sdavidxu /* Check for invalid arguments: */ 287144518Sdavidxu if (attr == NULL || *attr == NULL || stackaddr == NULL 288144518Sdavidxu || stacksize == NULL ) 289144518Sdavidxu ret = EINVAL; 290144518Sdavidxu else { 291144518Sdavidxu /* Return the stack address and size */ 292144518Sdavidxu *stackaddr = (*attr)->stackaddr_attr; 293144518Sdavidxu *stacksize = (*attr)->stacksize_attr; 294144518Sdavidxu ret = 0; 295144518Sdavidxu } 296144518Sdavidxu return(ret); 297144518Sdavidxu} 298112918Sjeff 299144518Sdavidxu__weak_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr); 300112918Sjeff 301112918Sjeffint 302144518Sdavidxu_pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) 303112918Sjeff{ 304144518Sdavidxu int ret; 305112918Sjeff 306144518Sdavidxu /* Check for invalid arguments: */ 307144518Sdavidxu if (attr == NULL || *attr == NULL || stackaddr == NULL) 308144518Sdavidxu ret = EINVAL; 309144518Sdavidxu else { 310144518Sdavidxu /* Return the stack address: */ 311144518Sdavidxu *stackaddr = (*attr)->stackaddr_attr; 312144518Sdavidxu ret = 0; 313144518Sdavidxu } 314144518Sdavidxu return(ret); 315112918Sjeff} 316112918Sjeff 317144518Sdavidxu__weak_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize); 318144518Sdavidxu 319112918Sjeffint 320144518Sdavidxu_pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) 321112918Sjeff{ 322144518Sdavidxu int ret; 323112918Sjeff 324144518Sdavidxu /* Check for invalid arguments: */ 325144518Sdavidxu if (attr == NULL || *attr == NULL || stacksize == NULL) 326144518Sdavidxu ret = EINVAL; 327144518Sdavidxu else { 328144518Sdavidxu /* Return the stack size: */ 329144518Sdavidxu *stacksize = (*attr)->stacksize_attr; 330144518Sdavidxu ret = 0; 331144518Sdavidxu } 332144518Sdavidxu return(ret); 333112918Sjeff} 334112918Sjeff 335144518Sdavidxu__weak_reference(_pthread_attr_init, pthread_attr_init); 336144518Sdavidxu 337112918Sjeffint 338144518Sdavidxu_pthread_attr_init(pthread_attr_t *attr) 339112918Sjeff{ 340144518Sdavidxu int ret; 341144518Sdavidxu pthread_attr_t pattr; 342112918Sjeff 343144518Sdavidxu _thr_check_init(); 344112918Sjeff 345144518Sdavidxu /* Allocate memory for the attribute object: */ 346144518Sdavidxu if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) 347144518Sdavidxu /* Insufficient memory: */ 348144518Sdavidxu ret = ENOMEM; 349144518Sdavidxu else { 350144518Sdavidxu /* Initialise the attribute object with the defaults: */ 351144518Sdavidxu memcpy(pattr, &_pthread_attr_default, sizeof(struct pthread_attr)); 352144518Sdavidxu 353144518Sdavidxu /* Return a pointer to the attribute object: */ 354144518Sdavidxu *attr = pattr; 355144518Sdavidxu ret = 0; 356144518Sdavidxu } 357144518Sdavidxu return(ret); 358112918Sjeff} 359112918Sjeff 360144518Sdavidxu__weak_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np); 361144518Sdavidxu 362112918Sjeffint 363144518Sdavidxu_pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) 364112918Sjeff{ 365112918Sjeff int ret; 366112918Sjeff 367144518Sdavidxu if (attr == NULL || *attr == NULL) { 368144518Sdavidxu ret = EINVAL; 369144518Sdavidxu } else { 370144518Sdavidxu (*attr)->suspend = THR_CREATE_SUSPENDED; 371144518Sdavidxu ret = 0; 372144518Sdavidxu } 373144518Sdavidxu return(ret); 374144518Sdavidxu} 375112918Sjeff 376144518Sdavidxu__weak_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate); 377112918Sjeff 378112918Sjeffint 379144518Sdavidxu_pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 380112918Sjeff{ 381144518Sdavidxu int ret; 382112918Sjeff 383144518Sdavidxu /* Check for invalid arguments: */ 384144518Sdavidxu if (attr == NULL || *attr == NULL || 385144518Sdavidxu (detachstate != PTHREAD_CREATE_DETACHED && 386144518Sdavidxu detachstate != PTHREAD_CREATE_JOINABLE)) 387144518Sdavidxu ret = EINVAL; 388144518Sdavidxu else { 389144518Sdavidxu /* Check if detached state: */ 390144518Sdavidxu if (detachstate == PTHREAD_CREATE_DETACHED) 391144518Sdavidxu /* Set the detached flag: */ 392144518Sdavidxu (*attr)->flags |= PTHREAD_DETACHED; 393144518Sdavidxu else 394144518Sdavidxu /* Reset the detached flag: */ 395144518Sdavidxu (*attr)->flags &= ~PTHREAD_DETACHED; 396144518Sdavidxu ret = 0; 397144518Sdavidxu } 398144518Sdavidxu return(ret); 399144518Sdavidxu} 400112918Sjeff 401144518Sdavidxu__weak_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize); 402112918Sjeff 403112918Sjeffint 404144518Sdavidxu_pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) 405112918Sjeff{ 406144518Sdavidxu int ret; 407112918Sjeff 408144518Sdavidxu /* Check for invalid arguments. */ 409144518Sdavidxu if (attr == NULL || *attr == NULL) 410144518Sdavidxu ret = EINVAL; 411144518Sdavidxu else { 412144518Sdavidxu /* Save the stack size. */ 413144518Sdavidxu (*attr)->guardsize_attr = guardsize; 414144518Sdavidxu ret = 0; 415144518Sdavidxu } 416144518Sdavidxu return(ret); 417112918Sjeff} 418112918Sjeff 419144518Sdavidxu__weak_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched); 420144518Sdavidxu 421112918Sjeffint 422144518Sdavidxu_pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit) 423112918Sjeff{ 424144518Sdavidxu int ret = 0; 425112918Sjeff 426144518Sdavidxu if ((attr == NULL) || (*attr == NULL)) 427144518Sdavidxu ret = EINVAL; 428144518Sdavidxu else if (sched_inherit != PTHREAD_INHERIT_SCHED && 429144518Sdavidxu sched_inherit != PTHREAD_EXPLICIT_SCHED) 430144518Sdavidxu ret = ENOTSUP; 431144518Sdavidxu else 432144518Sdavidxu (*attr)->sched_inherit = sched_inherit; 433112918Sjeff 434144518Sdavidxu return(ret); 435112918Sjeff} 436112918Sjeff 437144518Sdavidxu__weak_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam); 438144518Sdavidxu 439112918Sjeffint 440144518Sdavidxu_pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param) 441112918Sjeff{ 442158073Sdavidxu int policy; 443112918Sjeff 444144518Sdavidxu if ((attr == NULL) || (*attr == NULL)) 445158073Sdavidxu return (EINVAL); 446112918Sjeff 447158073Sdavidxu if (param == NULL) 448158073Sdavidxu return (ENOTSUP); 449158073Sdavidxu 450158073Sdavidxu policy = (*attr)->sched_policy; 451158073Sdavidxu 452160287Sdavidxu if (policy == SCHED_FIFO || policy == SCHED_RR) { 453160287Sdavidxu if (param->sched_priority < _thr_priorities[policy-1].pri_min || 454160287Sdavidxu param->sched_priority > _thr_priorities[policy-1].pri_max) 455158073Sdavidxu return (ENOTSUP); 456160287Sdavidxu } else { 457160287Sdavidxu /* 458160287Sdavidxu * Ignore it for SCHED_OTHER now, patches for glib ports 459160287Sdavidxu * are wrongly using M:N thread library's internal macro 460160287Sdavidxu * THR_MIN_PRIORITY and THR_MAX_PRIORITY. 461160287Sdavidxu */ 462160287Sdavidxu } 463158073Sdavidxu 464158073Sdavidxu (*attr)->prio = param->sched_priority; 465158073Sdavidxu 466158073Sdavidxu return (0); 467112918Sjeff} 468112918Sjeff 469144518Sdavidxu__weak_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy); 470144518Sdavidxu 471112918Sjeffint 472144518Sdavidxu_pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) 473112918Sjeff{ 474144518Sdavidxu int ret = 0; 475112918Sjeff 476144518Sdavidxu if ((attr == NULL) || (*attr == NULL)) 477144518Sdavidxu ret = EINVAL; 478144518Sdavidxu else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) { 479144518Sdavidxu ret = ENOTSUP; 480158073Sdavidxu } else { 481144518Sdavidxu (*attr)->sched_policy = policy; 482158073Sdavidxu (*attr)->prio = _thr_priorities[policy-1].pri_default; 483158073Sdavidxu } 484144518Sdavidxu return(ret); 485112918Sjeff} 486112918Sjeff 487144518Sdavidxu__weak_reference(_pthread_attr_setscope, pthread_attr_setscope); 488144518Sdavidxu 489112918Sjeffint 490144518Sdavidxu_pthread_attr_setscope(pthread_attr_t *attr, int contentionscope) 491112918Sjeff{ 492144518Sdavidxu int ret = 0; 493112918Sjeff 494144518Sdavidxu if ((attr == NULL) || (*attr == NULL)) { 495144518Sdavidxu /* Return an invalid argument: */ 496144518Sdavidxu ret = EINVAL; 497144518Sdavidxu } else if ((contentionscope != PTHREAD_SCOPE_PROCESS) && 498144518Sdavidxu (contentionscope != PTHREAD_SCOPE_SYSTEM)) { 499144518Sdavidxu ret = EINVAL; 500144518Sdavidxu } else if (contentionscope == PTHREAD_SCOPE_SYSTEM) { 501144518Sdavidxu (*attr)->flags |= contentionscope; 502144518Sdavidxu } else { 503144518Sdavidxu (*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM; 504144518Sdavidxu } 505144518Sdavidxu return (ret); 506112918Sjeff} 507112918Sjeff 508144518Sdavidxu__weak_reference(_pthread_attr_setstack, pthread_attr_setstack); 509144518Sdavidxu 510112918Sjeffint 511144518Sdavidxu_pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, 512144518Sdavidxu size_t stacksize) 513112918Sjeff{ 514144518Sdavidxu int ret; 515144518Sdavidxu 516144518Sdavidxu /* Check for invalid arguments: */ 517112918Sjeff if (attr == NULL || *attr == NULL || stackaddr == NULL 518144518Sdavidxu || stacksize < PTHREAD_STACK_MIN) 519144518Sdavidxu ret = EINVAL; 520144518Sdavidxu else { 521144518Sdavidxu /* Save the stack address and stack size */ 522144518Sdavidxu (*attr)->stackaddr_attr = stackaddr; 523144518Sdavidxu (*attr)->stacksize_attr = stacksize; 524144518Sdavidxu ret = 0; 525144518Sdavidxu } 526144518Sdavidxu return(ret); 527144518Sdavidxu} 528112918Sjeff 529144518Sdavidxu__weak_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr); 530112918Sjeff 531112918Sjeffint 532144518Sdavidxu_pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) 533112918Sjeff{ 534144518Sdavidxu int ret; 535144518Sdavidxu 536144518Sdavidxu /* Check for invalid arguments: */ 537112918Sjeff if (attr == NULL || *attr == NULL || stackaddr == NULL) 538144518Sdavidxu ret = EINVAL; 539144518Sdavidxu else { 540144518Sdavidxu /* Save the stack address: */ 541144518Sdavidxu (*attr)->stackaddr_attr = stackaddr; 542144518Sdavidxu ret = 0; 543144518Sdavidxu } 544144518Sdavidxu return(ret); 545144518Sdavidxu} 546112918Sjeff 547144518Sdavidxu__weak_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize); 548112918Sjeff 549112918Sjeffint 550144518Sdavidxu_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) 551112918Sjeff{ 552144518Sdavidxu int ret; 553112918Sjeff 554144518Sdavidxu /* Check for invalid arguments: */ 555144518Sdavidxu if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) 556144518Sdavidxu ret = EINVAL; 557144518Sdavidxu else { 558144518Sdavidxu /* Save the stack size: */ 559144518Sdavidxu (*attr)->stacksize_attr = stacksize; 560144518Sdavidxu ret = 0; 561144518Sdavidxu } 562144518Sdavidxu return(ret); 563112918Sjeff} 564176781Sdavidxu 565177605Srustatic size_t 566177605Sru_get_kern_cpuset_size(void) 567176815Sdavidxu{ 568176815Sdavidxu static int kern_cpuset_size = 0; 569176815Sdavidxu 570176815Sdavidxu if (kern_cpuset_size == 0) { 571177605Sru size_t len; 572176815Sdavidxu 573214653Sdavidxu len = sizeof(kern_cpuset_size); 574214653Sdavidxu if (sysctlbyname("kern.sched.cpusetsize", &kern_cpuset_size, 575214653Sdavidxu &len, NULL, 0)) 576214653Sdavidxu PANIC("failed to get sysctl kern.sched.cpusetsize"); 577176815Sdavidxu } 578176815Sdavidxu 579176815Sdavidxu return (kern_cpuset_size); 580176815Sdavidxu} 581176815Sdavidxu 582176815Sdavidxu__weak_reference(_pthread_attr_setaffinity_np, pthread_attr_setaffinity_np); 583176781Sdavidxuint 584176815Sdavidxu_pthread_attr_setaffinity_np(pthread_attr_t *pattr, size_t cpusetsize, 585178446Sdelphij const cpuset_t *cpusetp) 586176781Sdavidxu{ 587176781Sdavidxu pthread_attr_t attr; 588176781Sdavidxu int ret; 589176781Sdavidxu 590176781Sdavidxu if (pattr == NULL || (attr = (*pattr)) == NULL) 591176781Sdavidxu ret = EINVAL; 592176781Sdavidxu else { 593178446Sdelphij if (cpusetsize == 0 || cpusetp == NULL) { 594176781Sdavidxu if (attr->cpuset != NULL) { 595176781Sdavidxu free(attr->cpuset); 596176781Sdavidxu attr->cpuset = NULL; 597176781Sdavidxu attr->cpusetsize = 0; 598176781Sdavidxu } 599176781Sdavidxu return (0); 600176781Sdavidxu } 601214413Sdavidxu size_t kern_size = _get_kern_cpuset_size(); 602214413Sdavidxu /* Kernel rejects small set, we check it here too. */ 603214413Sdavidxu if (cpusetsize < kern_size) 604214413Sdavidxu return (ERANGE); 605214413Sdavidxu if (cpusetsize > kern_size) { 606214413Sdavidxu /* Kernel checks invalid bits, we check it here too. */ 607214413Sdavidxu size_t i; 608214413Sdavidxu for (i = kern_size; i < cpusetsize; ++i) { 609214413Sdavidxu if (((char *)cpusetp)[i]) 610214413Sdavidxu return (EINVAL); 611176815Sdavidxu } 612176781Sdavidxu } 613214413Sdavidxu if (attr->cpuset == NULL) { 614214413Sdavidxu attr->cpuset = calloc(1, kern_size); 615214413Sdavidxu if (attr->cpuset == NULL) 616214413Sdavidxu return (errno); 617214413Sdavidxu attr->cpusetsize = kern_size; 618214413Sdavidxu } 619214413Sdavidxu memcpy(attr->cpuset, cpusetp, kern_size); 620176781Sdavidxu ret = 0; 621176781Sdavidxu } 622176781Sdavidxu return (ret); 623176781Sdavidxu} 624176781Sdavidxu 625176815Sdavidxu__weak_reference(_pthread_attr_getaffinity_np, pthread_attr_getaffinity_np); 626176781Sdavidxuint 627176815Sdavidxu_pthread_attr_getaffinity_np(const pthread_attr_t *pattr, size_t cpusetsize, 628178446Sdelphij cpuset_t *cpusetp) 629176781Sdavidxu{ 630176781Sdavidxu pthread_attr_t attr; 631176781Sdavidxu int ret = 0; 632176781Sdavidxu 633176781Sdavidxu if (pattr == NULL || (attr = (*pattr)) == NULL) 634176781Sdavidxu ret = EINVAL; 635214413Sdavidxu else { 636214413Sdavidxu /* Kernel rejects small set, we check it here too. */ 637177605Sru size_t kern_size = _get_kern_cpuset_size(); 638214413Sdavidxu if (cpusetsize < kern_size) 639214413Sdavidxu return (ERANGE); 640214413Sdavidxu if (attr->cpuset != NULL) 641214413Sdavidxu memcpy(cpusetp, attr->cpuset, MIN(cpusetsize, 642214413Sdavidxu attr->cpusetsize)); 643214413Sdavidxu else 644214413Sdavidxu memset(cpusetp, -1, kern_size); 645176815Sdavidxu if (cpusetsize > kern_size) 646214413Sdavidxu memset(((char *)cpusetp) + kern_size, 0, 647176815Sdavidxu cpusetsize - kern_size); 648176781Sdavidxu } 649176781Sdavidxu return (ret); 650176781Sdavidxu} 651