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 __FBSDID("$FreeBSD$"); 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 <sys/sysctl.h> 106 #include "un-namespace.h" 107 108 #include "thr_private.h" 109 110 static size_t _get_kern_cpuset_size(void); 111 112 __weak_reference(_thr_attr_destroy, _pthread_attr_destroy); 113 __weak_reference(_thr_attr_destroy, pthread_attr_destroy); 114 115 int 116 _thr_attr_destroy(pthread_attr_t *attr) 117 { 118 int ret; 119 120 /* Check for invalid arguments: */ 121 if (attr == NULL || *attr == NULL) 122 /* Invalid argument: */ 123 ret = EINVAL; 124 else { 125 if ((*attr)->cpuset != NULL) 126 free((*attr)->cpuset); 127 /* Free the memory allocated to the attribute object: */ 128 free(*attr); 129 130 /* 131 * Leave the attribute pointer NULL now that the memory 132 * has been freed: 133 */ 134 *attr = NULL; 135 ret = 0; 136 } 137 return (ret); 138 } 139 140 __weak_reference(_thr_attr_get_np, pthread_attr_get_np); 141 __weak_reference(_thr_attr_get_np, _pthread_attr_get_np); 142 143 int 144 _thr_attr_get_np(pthread_t pthread, pthread_attr_t *dstattr) 145 { 146 struct pthread *curthread; 147 struct pthread_attr attr, *dst; 148 int ret; 149 size_t kern_size; 150 151 if (pthread == NULL || dstattr == NULL || (dst = *dstattr) == NULL) 152 return (EINVAL); 153 kern_size = _get_kern_cpuset_size(); 154 if (dst->cpuset == NULL) { 155 dst->cpuset = calloc(1, kern_size); 156 dst->cpusetsize = kern_size; 157 } 158 curthread = _get_curthread(); 159 if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/0)) != 0) 160 return (ret); 161 attr = pthread->attr; 162 if (pthread->flags & THR_FLAGS_DETACHED) 163 attr.flags |= PTHREAD_DETACHED; 164 ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, TID(pthread), 165 dst->cpusetsize, dst->cpuset); 166 if (ret == -1) 167 ret = errno; 168 THR_THREAD_UNLOCK(curthread, pthread); 169 if (ret == 0) { 170 memcpy(&dst->pthread_attr_start_copy, 171 &attr.pthread_attr_start_copy, 172 offsetof(struct pthread_attr, pthread_attr_end_copy) - 173 offsetof(struct pthread_attr, pthread_attr_start_copy)); 174 } 175 return (ret); 176 } 177 178 __weak_reference(_thr_attr_getdetachstate, pthread_attr_getdetachstate); 179 __weak_reference(_thr_attr_getdetachstate, _pthread_attr_getdetachstate); 180 181 int 182 _thr_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) 183 { 184 int ret; 185 186 /* Check for invalid arguments: */ 187 if (attr == NULL || *attr == NULL || detachstate == NULL) 188 ret = EINVAL; 189 else { 190 /* Check if the detached flag is set: */ 191 if ((*attr)->flags & PTHREAD_DETACHED) 192 /* Return detached: */ 193 *detachstate = PTHREAD_CREATE_DETACHED; 194 else 195 /* Return joinable: */ 196 *detachstate = PTHREAD_CREATE_JOINABLE; 197 ret = 0; 198 } 199 return (ret); 200 } 201 202 __weak_reference(_thr_attr_getguardsize, pthread_attr_getguardsize); 203 __weak_reference(_thr_attr_getguardsize, _pthread_attr_getguardsize); 204 205 int 206 _thr_attr_getguardsize(const pthread_attr_t * __restrict attr, 207 size_t * __restrict guardsize) 208 { 209 int ret; 210 211 /* Check for invalid arguments: */ 212 if (attr == NULL || *attr == NULL || guardsize == NULL) 213 ret = EINVAL; 214 else { 215 /* Return the guard size: */ 216 *guardsize = (*attr)->guardsize_attr; 217 ret = 0; 218 } 219 return (ret); 220 } 221 222 __weak_reference(_thr_attr_getinheritsched, pthread_attr_getinheritsched); 223 __weak_reference(_thr_attr_getinheritsched, _pthread_attr_getinheritsched); 224 225 int 226 _thr_attr_getinheritsched(const pthread_attr_t * __restrict attr, 227 int * __restrict sched_inherit) 228 { 229 int ret = 0; 230 231 if ((attr == NULL) || (*attr == NULL)) 232 ret = EINVAL; 233 else 234 *sched_inherit = (*attr)->sched_inherit; 235 236 return (ret); 237 } 238 239 __weak_reference(_thr_attr_getschedparam, pthread_attr_getschedparam); 240 __weak_reference(_thr_attr_getschedparam, _pthread_attr_getschedparam); 241 242 int 243 _thr_attr_getschedparam(const pthread_attr_t * __restrict attr, 244 struct sched_param * __restrict param) 245 { 246 int ret = 0; 247 248 if ((attr == NULL) || (*attr == NULL) || (param == NULL)) 249 ret = EINVAL; 250 else 251 param->sched_priority = (*attr)->prio; 252 253 return (ret); 254 } 255 256 __weak_reference(_thr_attr_getschedpolicy, pthread_attr_getschedpolicy); 257 __weak_reference(_thr_attr_getschedpolicy, _pthread_attr_getschedpolicy); 258 259 int 260 _thr_attr_getschedpolicy(const pthread_attr_t * __restrict attr, 261 int * __restrict policy) 262 { 263 int ret = 0; 264 265 if ((attr == NULL) || (*attr == NULL) || (policy == NULL)) 266 ret = EINVAL; 267 else 268 *policy = (*attr)->sched_policy; 269 270 return (ret); 271 } 272 273 __weak_reference(_thr_attr_getscope, pthread_attr_getscope); 274 __weak_reference(_thr_attr_getscope, _pthread_attr_getscope); 275 276 int 277 _thr_attr_getscope(const pthread_attr_t * __restrict attr, 278 int * __restrict contentionscope) 279 { 280 int ret = 0; 281 282 if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL)) 283 /* Return an invalid argument: */ 284 ret = EINVAL; 285 286 else 287 *contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ? 288 PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; 289 290 return (ret); 291 } 292 293 __weak_reference(_pthread_attr_getstack, pthread_attr_getstack); 294 295 int 296 _pthread_attr_getstack(const pthread_attr_t * __restrict attr, 297 void ** __restrict stackaddr, size_t * __restrict stacksize) 298 { 299 int ret; 300 301 /* Check for invalid arguments: */ 302 if (attr == NULL || *attr == NULL || stackaddr == NULL 303 || stacksize == NULL ) 304 ret = EINVAL; 305 else { 306 /* Return the stack address and size */ 307 *stackaddr = (*attr)->stackaddr_attr; 308 *stacksize = (*attr)->stacksize_attr; 309 ret = 0; 310 } 311 return (ret); 312 } 313 314 __weak_reference(_thr_attr_getstackaddr, pthread_attr_getstackaddr); 315 __weak_reference(_thr_attr_getstackaddr, _pthread_attr_getstackaddr); 316 317 int 318 _thr_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) 319 { 320 int ret; 321 322 /* Check for invalid arguments: */ 323 if (attr == NULL || *attr == NULL || stackaddr == NULL) 324 ret = EINVAL; 325 else { 326 /* Return the stack address: */ 327 *stackaddr = (*attr)->stackaddr_attr; 328 ret = 0; 329 } 330 return (ret); 331 } 332 333 __weak_reference(_thr_attr_getstacksize, pthread_attr_getstacksize); 334 __weak_reference(_thr_attr_getstacksize, _pthread_attr_getstacksize); 335 336 int 337 _thr_attr_getstacksize(const pthread_attr_t * __restrict attr, 338 size_t * __restrict stacksize) 339 { 340 int ret; 341 342 /* Check for invalid arguments: */ 343 if (attr == NULL || *attr == NULL || stacksize == NULL) 344 ret = EINVAL; 345 else { 346 /* Return the stack size: */ 347 *stacksize = (*attr)->stacksize_attr; 348 ret = 0; 349 } 350 return (ret); 351 } 352 353 __weak_reference(_thr_attr_init, pthread_attr_init); 354 __weak_reference(_thr_attr_init, _pthread_attr_init); 355 356 int 357 _thr_attr_init(pthread_attr_t *attr) 358 { 359 int ret; 360 pthread_attr_t pattr; 361 362 _thr_check_init(); 363 364 /* Allocate memory for the attribute object: */ 365 if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) 366 /* Insufficient memory: */ 367 ret = ENOMEM; 368 else { 369 /* Initialise the attribute object with the defaults: */ 370 memcpy(pattr, &_pthread_attr_default, sizeof(struct pthread_attr)); 371 372 /* Return a pointer to the attribute object: */ 373 *attr = pattr; 374 ret = 0; 375 } 376 return (ret); 377 } 378 379 __weak_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np); 380 381 int 382 _pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) 383 { 384 int ret; 385 386 if (attr == NULL || *attr == NULL) { 387 ret = EINVAL; 388 } else { 389 (*attr)->suspend = THR_CREATE_SUSPENDED; 390 ret = 0; 391 } 392 return (ret); 393 } 394 395 __weak_reference(_thr_attr_setdetachstate, pthread_attr_setdetachstate); 396 __weak_reference(_thr_attr_setdetachstate, _pthread_attr_setdetachstate); 397 398 int 399 _thr_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 400 { 401 int ret; 402 403 /* Check for invalid arguments: */ 404 if (attr == NULL || *attr == NULL || 405 (detachstate != PTHREAD_CREATE_DETACHED && 406 detachstate != PTHREAD_CREATE_JOINABLE)) 407 ret = EINVAL; 408 else { 409 /* Check if detached state: */ 410 if (detachstate == PTHREAD_CREATE_DETACHED) 411 /* Set the detached flag: */ 412 (*attr)->flags |= PTHREAD_DETACHED; 413 else 414 /* Reset the detached flag: */ 415 (*attr)->flags &= ~PTHREAD_DETACHED; 416 ret = 0; 417 } 418 return (ret); 419 } 420 421 __weak_reference(_thr_attr_setguardsize, pthread_attr_setguardsize); 422 __weak_reference(_thr_attr_setguardsize, _pthread_attr_setguardsize); 423 424 int 425 _thr_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) 426 { 427 int ret; 428 429 /* Check for invalid arguments. */ 430 if (attr == NULL || *attr == NULL) 431 ret = EINVAL; 432 else { 433 /* Save the stack size. */ 434 (*attr)->guardsize_attr = guardsize; 435 ret = 0; 436 } 437 return (ret); 438 } 439 440 __weak_reference(_thr_attr_setinheritsched, pthread_attr_setinheritsched); 441 __weak_reference(_thr_attr_setinheritsched, _pthread_attr_setinheritsched); 442 443 int 444 _thr_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit) 445 { 446 int ret = 0; 447 448 if ((attr == NULL) || (*attr == NULL)) 449 ret = EINVAL; 450 else if (sched_inherit != PTHREAD_INHERIT_SCHED && 451 sched_inherit != PTHREAD_EXPLICIT_SCHED) 452 ret = ENOTSUP; 453 else 454 (*attr)->sched_inherit = sched_inherit; 455 456 return (ret); 457 } 458 459 __weak_reference(_thr_attr_setschedparam, pthread_attr_setschedparam); 460 __weak_reference(_thr_attr_setschedparam, _pthread_attr_setschedparam); 461 462 int 463 _thr_attr_setschedparam(pthread_attr_t * __restrict attr, 464 const struct sched_param * __restrict param) 465 { 466 int policy; 467 468 if ((attr == NULL) || (*attr == NULL)) 469 return (EINVAL); 470 471 if (param == NULL) 472 return (ENOTSUP); 473 474 policy = (*attr)->sched_policy; 475 476 if (policy == SCHED_FIFO || policy == SCHED_RR) { 477 if (param->sched_priority < _thr_priorities[policy-1].pri_min || 478 param->sched_priority > _thr_priorities[policy-1].pri_max) 479 return (ENOTSUP); 480 } else { 481 /* 482 * Ignore it for SCHED_OTHER now, patches for glib ports 483 * are wrongly using M:N thread library's internal macro 484 * THR_MIN_PRIORITY and THR_MAX_PRIORITY. 485 */ 486 } 487 488 (*attr)->prio = param->sched_priority; 489 490 return (0); 491 } 492 493 __weak_reference(_thr_attr_setschedpolicy, pthread_attr_setschedpolicy); 494 __weak_reference(_thr_attr_setschedpolicy, _pthread_attr_setschedpolicy); 495 496 int 497 _thr_attr_setschedpolicy(pthread_attr_t *attr, int policy) 498 { 499 int ret = 0; 500 501 if ((attr == NULL) || (*attr == NULL)) 502 ret = EINVAL; 503 else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) { 504 ret = ENOTSUP; 505 } else { 506 (*attr)->sched_policy = policy; 507 (*attr)->prio = _thr_priorities[policy-1].pri_default; 508 } 509 return (ret); 510 } 511 512 __weak_reference(_thr_attr_setscope, pthread_attr_setscope); 513 __weak_reference(_thr_attr_setscope, _pthread_attr_setscope); 514 515 int 516 _thr_attr_setscope(pthread_attr_t *attr, int contentionscope) 517 { 518 int ret = 0; 519 520 if ((attr == NULL) || (*attr == NULL)) { 521 /* Return an invalid argument: */ 522 ret = EINVAL; 523 } else if ((contentionscope != PTHREAD_SCOPE_PROCESS) && 524 (contentionscope != PTHREAD_SCOPE_SYSTEM)) { 525 ret = EINVAL; 526 } else if (contentionscope == PTHREAD_SCOPE_SYSTEM) { 527 (*attr)->flags |= contentionscope; 528 } else { 529 (*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM; 530 } 531 return (ret); 532 } 533 534 __weak_reference(_pthread_attr_setstack, pthread_attr_setstack); 535 536 int 537 _pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, 538 size_t stacksize) 539 { 540 int ret; 541 542 /* Check for invalid arguments: */ 543 if (attr == NULL || *attr == NULL || stackaddr == NULL 544 || stacksize < PTHREAD_STACK_MIN) 545 ret = EINVAL; 546 else { 547 /* Save the stack address and stack size */ 548 (*attr)->stackaddr_attr = stackaddr; 549 (*attr)->stacksize_attr = stacksize; 550 ret = 0; 551 } 552 return (ret); 553 } 554 555 __weak_reference(_thr_attr_setstackaddr, pthread_attr_setstackaddr); 556 __weak_reference(_thr_attr_setstackaddr, _pthread_attr_setstackaddr); 557 558 int 559 _thr_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) 560 { 561 int ret; 562 563 /* Check for invalid arguments: */ 564 if (attr == NULL || *attr == NULL || stackaddr == NULL) 565 ret = EINVAL; 566 else { 567 /* Save the stack address: */ 568 (*attr)->stackaddr_attr = stackaddr; 569 ret = 0; 570 } 571 return(ret); 572 } 573 574 __weak_reference(_thr_attr_setstacksize, pthread_attr_setstacksize); 575 __weak_reference(_thr_attr_setstacksize, _pthread_attr_setstacksize); 576 577 int 578 _thr_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) 579 { 580 int ret; 581 582 /* Check for invalid arguments: */ 583 if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) 584 ret = EINVAL; 585 else { 586 /* Save the stack size: */ 587 (*attr)->stacksize_attr = stacksize; 588 ret = 0; 589 } 590 return (ret); 591 } 592 593 static size_t 594 _get_kern_cpuset_size(void) 595 { 596 static int kern_cpuset_size = 0; 597 598 if (kern_cpuset_size == 0) { 599 size_t len; 600 601 len = sizeof(kern_cpuset_size); 602 if (sysctlbyname("kern.sched.cpusetsize", &kern_cpuset_size, 603 &len, NULL, 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