1 /*- 2 * SPDX-License-Identifier: BSD-4-Clause 3 * 4 * Copyright (c) 2003 Craig Rodrigues <rodrigc@attbi.com>. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Craig Rodrigues. 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY CRAIG RODRIGUES AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35 36 /* 37 * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. 38 * Copyright (C) 2001 Jason Evans <jasone@freebsd.org>. 39 * Copyright (c) 2002,2003 Alexey Zelkin <phantom@FreeBSD.org> 40 * All rights reserved. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice(s), this list of conditions and the following disclaimer 47 * unmodified other than the allowable addition of one or more 48 * copyright notices. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice(s), this list of conditions and the following disclaimer in 51 * the documentation and/or other materials provided with the 52 * distribution. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY 55 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 57 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE 58 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 61 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 62 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 63 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 64 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 65 */ 66 67 /* 68 * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. 69 * All rights reserved. 70 * 71 * Redistribution and use in source and binary forms, with or without 72 * modification, are permitted provided that the following conditions 73 * are met: 74 * 1. Redistributions of source code must retain the above copyright 75 * notice, this list of conditions and the following disclaimer. 76 * 2. Redistributions in binary form must reproduce the above copyright 77 * notice, this list of conditions and the following disclaimer in the 78 * documentation and/or other materials provided with the distribution. 79 * 3. Neither the name of the author nor the names of any co-contributors 80 * may be used to endorse or promote products derived from this software 81 * without specific prior written permission. 82 * 83 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 84 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 85 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 86 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 87 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 88 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 89 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 90 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 91 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 92 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 93 * SUCH DAMAGE. 94 */ 95 96 #include <sys/cdefs.h> 97 #include "namespace.h" 98 #include <errno.h> 99 #include <pthread.h> 100 #include <stdlib.h> 101 #include <string.h> 102 #include <pthread_np.h> 103 #include <sys/sysctl.h> 104 #include "un-namespace.h" 105 106 #include "thr_private.h" 107 108 static size_t _get_kern_cpuset_size(void); 109 110 __weak_reference(_thr_attr_destroy, _pthread_attr_destroy); 111 __weak_reference(_thr_attr_destroy, pthread_attr_destroy); 112 113 int 114 _thr_attr_destroy(pthread_attr_t *attr) 115 { 116 int ret; 117 118 /* Check for invalid arguments: */ 119 if (attr == NULL || *attr == NULL) 120 /* Invalid argument: */ 121 ret = EINVAL; 122 else { 123 if ((*attr)->cpuset != NULL) 124 free((*attr)->cpuset); 125 /* Free the memory allocated to the attribute object: */ 126 free(*attr); 127 128 /* 129 * Leave the attribute pointer NULL now that the memory 130 * has been freed: 131 */ 132 *attr = NULL; 133 ret = 0; 134 } 135 return (ret); 136 } 137 138 __weak_reference(_thr_attr_get_np, pthread_attr_get_np); 139 __weak_reference(_thr_attr_get_np, _pthread_attr_get_np); 140 141 int 142 _thr_attr_get_np(pthread_t pthread, pthread_attr_t *dstattr) 143 { 144 struct pthread *curthread; 145 struct pthread_attr attr, *dst; 146 int ret; 147 size_t kern_size; 148 149 if (pthread == NULL || dstattr == NULL || (dst = *dstattr) == NULL) 150 return (EINVAL); 151 kern_size = _get_kern_cpuset_size(); 152 if (dst->cpuset == NULL) { 153 dst->cpuset = calloc(1, kern_size); 154 dst->cpusetsize = kern_size; 155 } 156 curthread = _get_curthread(); 157 if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/0)) != 0) 158 return (ret); 159 attr = pthread->attr; 160 if (pthread->flags & THR_FLAGS_DETACHED) 161 attr.flags |= PTHREAD_DETACHED; 162 ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, TID(pthread), 163 dst->cpusetsize, dst->cpuset); 164 if (ret == -1) 165 ret = errno; 166 THR_THREAD_UNLOCK(curthread, pthread); 167 if (ret == 0) { 168 memcpy(&dst->pthread_attr_start_copy, 169 &attr.pthread_attr_start_copy, 170 offsetof(struct pthread_attr, pthread_attr_end_copy) - 171 offsetof(struct pthread_attr, pthread_attr_start_copy)); 172 } 173 return (ret); 174 } 175 176 __weak_reference(_thr_attr_getdetachstate, pthread_attr_getdetachstate); 177 __weak_reference(_thr_attr_getdetachstate, _pthread_attr_getdetachstate); 178 179 int 180 _thr_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) 181 { 182 int ret; 183 184 /* Check for invalid arguments: */ 185 if (attr == NULL || *attr == NULL || detachstate == NULL) 186 ret = EINVAL; 187 else { 188 /* Check if the detached flag is set: */ 189 if ((*attr)->flags & PTHREAD_DETACHED) 190 /* Return detached: */ 191 *detachstate = PTHREAD_CREATE_DETACHED; 192 else 193 /* Return joinable: */ 194 *detachstate = PTHREAD_CREATE_JOINABLE; 195 ret = 0; 196 } 197 return (ret); 198 } 199 200 __weak_reference(_thr_attr_getguardsize, pthread_attr_getguardsize); 201 __weak_reference(_thr_attr_getguardsize, _pthread_attr_getguardsize); 202 203 int 204 _thr_attr_getguardsize(const pthread_attr_t * __restrict attr, 205 size_t * __restrict guardsize) 206 { 207 int ret; 208 209 /* Check for invalid arguments: */ 210 if (attr == NULL || *attr == NULL || guardsize == NULL) 211 ret = EINVAL; 212 else { 213 /* Return the guard size: */ 214 *guardsize = (*attr)->guardsize_attr; 215 ret = 0; 216 } 217 return (ret); 218 } 219 220 __weak_reference(_thr_attr_getinheritsched, pthread_attr_getinheritsched); 221 __weak_reference(_thr_attr_getinheritsched, _pthread_attr_getinheritsched); 222 223 int 224 _thr_attr_getinheritsched(const pthread_attr_t * __restrict attr, 225 int * __restrict sched_inherit) 226 { 227 int ret = 0; 228 229 if ((attr == NULL) || (*attr == NULL)) 230 ret = EINVAL; 231 else 232 *sched_inherit = (*attr)->sched_inherit; 233 234 return (ret); 235 } 236 237 __weak_reference(_thr_attr_getschedparam, pthread_attr_getschedparam); 238 __weak_reference(_thr_attr_getschedparam, _pthread_attr_getschedparam); 239 240 int 241 _thr_attr_getschedparam(const pthread_attr_t * __restrict attr, 242 struct sched_param * __restrict param) 243 { 244 int ret = 0; 245 246 if ((attr == NULL) || (*attr == NULL) || (param == NULL)) 247 ret = EINVAL; 248 else 249 param->sched_priority = (*attr)->prio; 250 251 return (ret); 252 } 253 254 __weak_reference(_thr_attr_getschedpolicy, pthread_attr_getschedpolicy); 255 __weak_reference(_thr_attr_getschedpolicy, _pthread_attr_getschedpolicy); 256 257 int 258 _thr_attr_getschedpolicy(const pthread_attr_t * __restrict attr, 259 int * __restrict policy) 260 { 261 int ret = 0; 262 263 if ((attr == NULL) || (*attr == NULL) || (policy == NULL)) 264 ret = EINVAL; 265 else 266 *policy = (*attr)->sched_policy; 267 268 return (ret); 269 } 270 271 __weak_reference(_thr_attr_getscope, pthread_attr_getscope); 272 __weak_reference(_thr_attr_getscope, _pthread_attr_getscope); 273 274 int 275 _thr_attr_getscope(const pthread_attr_t * __restrict attr, 276 int * __restrict contentionscope) 277 { 278 int ret = 0; 279 280 if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL)) 281 /* Return an invalid argument: */ 282 ret = EINVAL; 283 284 else 285 *contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ? 286 PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; 287 288 return (ret); 289 } 290 291 __weak_reference(_pthread_attr_getstack, pthread_attr_getstack); 292 293 int 294 _pthread_attr_getstack(const pthread_attr_t * __restrict attr, 295 void ** __restrict stackaddr, size_t * __restrict stacksize) 296 { 297 int ret; 298 299 /* Check for invalid arguments: */ 300 if (attr == NULL || *attr == NULL || stackaddr == NULL 301 || stacksize == NULL ) 302 ret = EINVAL; 303 else { 304 /* Return the stack address and size */ 305 *stackaddr = (*attr)->stackaddr_attr; 306 *stacksize = (*attr)->stacksize_attr; 307 ret = 0; 308 } 309 return (ret); 310 } 311 312 __weak_reference(_thr_attr_getstackaddr, pthread_attr_getstackaddr); 313 __weak_reference(_thr_attr_getstackaddr, _pthread_attr_getstackaddr); 314 315 int 316 _thr_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) 317 { 318 int ret; 319 320 /* Check for invalid arguments: */ 321 if (attr == NULL || *attr == NULL || stackaddr == NULL) 322 ret = EINVAL; 323 else { 324 /* Return the stack address: */ 325 *stackaddr = (*attr)->stackaddr_attr; 326 ret = 0; 327 } 328 return (ret); 329 } 330 331 __weak_reference(_thr_attr_getstacksize, pthread_attr_getstacksize); 332 __weak_reference(_thr_attr_getstacksize, _pthread_attr_getstacksize); 333 334 int 335 _thr_attr_getstacksize(const pthread_attr_t * __restrict attr, 336 size_t * __restrict stacksize) 337 { 338 int ret; 339 340 /* Check for invalid arguments: */ 341 if (attr == NULL || *attr == NULL || stacksize == NULL) 342 ret = EINVAL; 343 else { 344 /* Return the stack size: */ 345 *stacksize = (*attr)->stacksize_attr; 346 ret = 0; 347 } 348 return (ret); 349 } 350 351 __weak_reference(_thr_attr_init, pthread_attr_init); 352 __weak_reference(_thr_attr_init, _pthread_attr_init); 353 354 int 355 _thr_attr_init(pthread_attr_t *attr) 356 { 357 int ret; 358 pthread_attr_t pattr; 359 360 _thr_check_init(); 361 362 /* Allocate memory for the attribute object: */ 363 if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) 364 /* Insufficient memory: */ 365 ret = ENOMEM; 366 else { 367 /* Initialise the attribute object with the defaults: */ 368 memcpy(pattr, &_pthread_attr_default, sizeof(struct pthread_attr)); 369 370 /* Return a pointer to the attribute object: */ 371 *attr = pattr; 372 ret = 0; 373 } 374 return (ret); 375 } 376 377 __weak_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np); 378 379 int 380 _pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) 381 { 382 int ret; 383 384 if (attr == NULL || *attr == NULL) { 385 ret = EINVAL; 386 } else { 387 (*attr)->suspend = THR_CREATE_SUSPENDED; 388 ret = 0; 389 } 390 return (ret); 391 } 392 393 __weak_reference(_thr_attr_setdetachstate, pthread_attr_setdetachstate); 394 __weak_reference(_thr_attr_setdetachstate, _pthread_attr_setdetachstate); 395 396 int 397 _thr_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 398 { 399 int ret; 400 401 /* Check for invalid arguments: */ 402 if (attr == NULL || *attr == NULL || 403 (detachstate != PTHREAD_CREATE_DETACHED && 404 detachstate != PTHREAD_CREATE_JOINABLE)) 405 ret = EINVAL; 406 else { 407 /* Check if detached state: */ 408 if (detachstate == PTHREAD_CREATE_DETACHED) 409 /* Set the detached flag: */ 410 (*attr)->flags |= PTHREAD_DETACHED; 411 else 412 /* Reset the detached flag: */ 413 (*attr)->flags &= ~PTHREAD_DETACHED; 414 ret = 0; 415 } 416 return (ret); 417 } 418 419 __weak_reference(_thr_attr_setguardsize, pthread_attr_setguardsize); 420 __weak_reference(_thr_attr_setguardsize, _pthread_attr_setguardsize); 421 422 int 423 _thr_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) 424 { 425 int ret; 426 427 /* Check for invalid arguments. */ 428 if (attr == NULL || *attr == NULL) 429 ret = EINVAL; 430 else { 431 /* Save the stack size. */ 432 (*attr)->guardsize_attr = guardsize; 433 ret = 0; 434 } 435 return (ret); 436 } 437 438 __weak_reference(_thr_attr_setinheritsched, pthread_attr_setinheritsched); 439 __weak_reference(_thr_attr_setinheritsched, _pthread_attr_setinheritsched); 440 441 int 442 _thr_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit) 443 { 444 int ret = 0; 445 446 if ((attr == NULL) || (*attr == NULL)) 447 ret = EINVAL; 448 else if (sched_inherit != PTHREAD_INHERIT_SCHED && 449 sched_inherit != PTHREAD_EXPLICIT_SCHED) 450 ret = ENOTSUP; 451 else 452 (*attr)->sched_inherit = sched_inherit; 453 454 return (ret); 455 } 456 457 __weak_reference(_thr_attr_setschedparam, pthread_attr_setschedparam); 458 __weak_reference(_thr_attr_setschedparam, _pthread_attr_setschedparam); 459 460 int 461 _thr_attr_setschedparam(pthread_attr_t * __restrict attr, 462 const struct sched_param * __restrict param) 463 { 464 int policy; 465 466 if ((attr == NULL) || (*attr == NULL)) 467 return (EINVAL); 468 469 if (param == NULL) 470 return (ENOTSUP); 471 472 policy = (*attr)->sched_policy; 473 474 if (policy == SCHED_FIFO || policy == SCHED_RR) { 475 if (param->sched_priority < _thr_priorities[policy-1].pri_min || 476 param->sched_priority > _thr_priorities[policy-1].pri_max) 477 return (ENOTSUP); 478 } else { 479 /* 480 * Ignore it for SCHED_OTHER now, patches for glib ports 481 * are wrongly using M:N thread library's internal macro 482 * THR_MIN_PRIORITY and THR_MAX_PRIORITY. 483 */ 484 } 485 486 (*attr)->prio = param->sched_priority; 487 488 return (0); 489 } 490 491 __weak_reference(_thr_attr_setschedpolicy, pthread_attr_setschedpolicy); 492 __weak_reference(_thr_attr_setschedpolicy, _pthread_attr_setschedpolicy); 493 494 int 495 _thr_attr_setschedpolicy(pthread_attr_t *attr, int policy) 496 { 497 int ret = 0; 498 499 if ((attr == NULL) || (*attr == NULL)) 500 ret = EINVAL; 501 else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) { 502 ret = ENOTSUP; 503 } else { 504 (*attr)->sched_policy = policy; 505 (*attr)->prio = _thr_priorities[policy-1].pri_default; 506 } 507 return (ret); 508 } 509 510 __weak_reference(_thr_attr_setscope, pthread_attr_setscope); 511 __weak_reference(_thr_attr_setscope, _pthread_attr_setscope); 512 513 int 514 _thr_attr_setscope(pthread_attr_t *attr, int contentionscope) 515 { 516 int ret = 0; 517 518 if ((attr == NULL) || (*attr == NULL)) { 519 /* Return an invalid argument: */ 520 ret = EINVAL; 521 } else if ((contentionscope != PTHREAD_SCOPE_PROCESS) && 522 (contentionscope != PTHREAD_SCOPE_SYSTEM)) { 523 ret = EINVAL; 524 } else if (contentionscope == PTHREAD_SCOPE_SYSTEM) { 525 (*attr)->flags |= contentionscope; 526 } else { 527 (*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM; 528 } 529 return (ret); 530 } 531 532 __weak_reference(_pthread_attr_setstack, pthread_attr_setstack); 533 534 int 535 _pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, 536 size_t stacksize) 537 { 538 int ret; 539 540 /* Check for invalid arguments: */ 541 if (attr == NULL || *attr == NULL || stackaddr == NULL 542 || stacksize < PTHREAD_STACK_MIN) 543 ret = EINVAL; 544 else { 545 /* Save the stack address and stack size */ 546 (*attr)->stackaddr_attr = stackaddr; 547 (*attr)->stacksize_attr = stacksize; 548 ret = 0; 549 } 550 return (ret); 551 } 552 553 __weak_reference(_thr_attr_setstackaddr, pthread_attr_setstackaddr); 554 __weak_reference(_thr_attr_setstackaddr, _pthread_attr_setstackaddr); 555 556 int 557 _thr_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) 558 { 559 int ret; 560 561 /* Check for invalid arguments: */ 562 if (attr == NULL || *attr == NULL || stackaddr == NULL) 563 ret = EINVAL; 564 else { 565 /* Save the stack address: */ 566 (*attr)->stackaddr_attr = stackaddr; 567 ret = 0; 568 } 569 return(ret); 570 } 571 572 __weak_reference(_thr_attr_setstacksize, pthread_attr_setstacksize); 573 __weak_reference(_thr_attr_setstacksize, _pthread_attr_setstacksize); 574 575 int 576 _thr_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) 577 { 578 int ret; 579 580 /* Check for invalid arguments: */ 581 if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) 582 ret = EINVAL; 583 else { 584 /* Save the stack size: */ 585 (*attr)->stacksize_attr = stacksize; 586 ret = 0; 587 } 588 return (ret); 589 } 590 591 static size_t 592 _get_kern_cpuset_size(void) 593 { 594 static int kern_cpuset_size = 0; 595 596 if (kern_cpuset_size == 0) { 597 size_t len; 598 599 len = sizeof(kern_cpuset_size); 600 if (sysctlbyname("kern.sched.cpusetsizemin", &kern_cpuset_size, 601 &len, NULL, 0) != 0 && 602 sysctlbyname("kern.sched.cpusetsize", &kern_cpuset_size, 603 &len, NULL, 0) != 0) 604 PANIC("failed to get sysctl kern.sched.cpusetsize"); 605 } 606 607 return (kern_cpuset_size); 608 } 609 610 __weak_reference(_pthread_attr_setaffinity_np, pthread_attr_setaffinity_np); 611 int 612 _pthread_attr_setaffinity_np(pthread_attr_t *pattr, size_t cpusetsize, 613 const cpuset_t *cpusetp) 614 { 615 pthread_attr_t attr; 616 int ret; 617 618 if (pattr == NULL || (attr = (*pattr)) == NULL) 619 ret = EINVAL; 620 else { 621 if (cpusetsize == 0 || cpusetp == NULL) { 622 if (attr->cpuset != NULL) { 623 free(attr->cpuset); 624 attr->cpuset = NULL; 625 attr->cpusetsize = 0; 626 } 627 return (0); 628 } 629 size_t kern_size = _get_kern_cpuset_size(); 630 /* Kernel rejects small set, we check it here too. */ 631 if (cpusetsize < kern_size) 632 return (ERANGE); 633 if (cpusetsize > kern_size) { 634 /* Kernel checks invalid bits, we check it here too. */ 635 size_t i; 636 for (i = kern_size; i < cpusetsize; ++i) { 637 if (((const char *)cpusetp)[i]) 638 return (EINVAL); 639 } 640 } 641 if (attr->cpuset == NULL) { 642 attr->cpuset = calloc(1, kern_size); 643 if (attr->cpuset == NULL) 644 return (errno); 645 attr->cpusetsize = kern_size; 646 } 647 memcpy(attr->cpuset, cpusetp, kern_size); 648 ret = 0; 649 } 650 return (ret); 651 } 652 653 __weak_reference(_pthread_attr_getaffinity_np, pthread_attr_getaffinity_np); 654 int 655 _pthread_attr_getaffinity_np(const pthread_attr_t *pattr, size_t cpusetsize, 656 cpuset_t *cpusetp) 657 { 658 pthread_attr_t attr; 659 int ret = 0; 660 661 if (pattr == NULL || (attr = (*pattr)) == NULL) 662 ret = EINVAL; 663 else { 664 /* Kernel rejects small set, we check it here too. */ 665 size_t kern_size = _get_kern_cpuset_size(); 666 if (cpusetsize < kern_size) 667 return (ERANGE); 668 if (attr->cpuset != NULL) 669 memcpy(cpusetp, attr->cpuset, MIN(cpusetsize, 670 attr->cpusetsize)); 671 else 672 memset(cpusetp, -1, kern_size); 673 if (cpusetsize > kern_size) 674 memset(((char *)cpusetp) + kern_size, 0, 675 cpusetsize - kern_size); 676 } 677 return (ret); 678 } 679