1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2015 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <sys/types.h> 8 #include <errno.h> 9 #include <sched.h> 10 #include <dlfcn.h> 11 12 #include <rte_log.h> 13 14 #include "lthread_api.h" 15 #include "pthread_shim.h" 16 17 #define RTE_LOGTYPE_PTHREAD_SHIM RTE_LOGTYPE_USER3 18 19 #define POSIX_ERRNO(x) (x) 20 21 /* some releases of FreeBSD 10, e.g. 10.0, don't have CPU_COUNT macro */ 22 #ifndef CPU_COUNT 23 #define CPU_COUNT(x) __cpu_count(x) 24 25 static inline unsigned int 26 __cpu_count(const rte_cpuset_t *cpuset) 27 { 28 unsigned int i, count = 0; 29 for (i = 0; i < RTE_MAX_LCORE; i++) 30 if (CPU_ISSET(i, cpuset)) 31 count++; 32 return count; 33 } 34 #endif 35 36 /* 37 * this flag determines at run time if we override pthread 38 * calls and map then to equivalent lthread calls 39 * or of we call the standard pthread function 40 */ 41 static __thread int override; 42 43 44 /* 45 * this structures contains function pointers that will be 46 * initialised to the loaded address of the real 47 * pthread library API functions 48 */ 49 struct pthread_lib_funcs { 50 int (*f_pthread_barrier_destroy) 51 (pthread_barrier_t *); 52 int (*f_pthread_barrier_init) 53 (pthread_barrier_t *, const pthread_barrierattr_t *, unsigned); 54 int (*f_pthread_barrier_wait) 55 (pthread_barrier_t *); 56 int (*f_pthread_cond_broadcast) 57 (pthread_cond_t *); 58 int (*f_pthread_cond_destroy) 59 (pthread_cond_t *); 60 int (*f_pthread_cond_init) 61 (pthread_cond_t *, const pthread_condattr_t *); 62 int (*f_pthread_cond_signal) 63 (pthread_cond_t *); 64 int (*f_pthread_cond_timedwait) 65 (pthread_cond_t *, pthread_mutex_t *, const struct timespec *); 66 int (*f_pthread_cond_wait) 67 (pthread_cond_t *, pthread_mutex_t *); 68 int (*f_pthread_create) 69 (pthread_t *, const pthread_attr_t *, void *(*)(void *), void *); 70 int (*f_pthread_detach) 71 (pthread_t); 72 int (*f_pthread_equal) 73 (pthread_t, pthread_t); 74 void (*f_pthread_exit) 75 (void *); 76 void * (*f_pthread_getspecific) 77 (pthread_key_t); 78 int (*f_pthread_getcpuclockid) 79 (pthread_t, clockid_t *); 80 int (*f_pthread_join) 81 (pthread_t, void **); 82 int (*f_pthread_key_create) 83 (pthread_key_t *, void (*) (void *)); 84 int (*f_pthread_key_delete) 85 (pthread_key_t); 86 int (*f_pthread_mutex_destroy) 87 (pthread_mutex_t *__mutex); 88 int (*f_pthread_mutex_init) 89 (pthread_mutex_t *__mutex, const pthread_mutexattr_t *); 90 int (*f_pthread_mutex_lock) 91 (pthread_mutex_t *__mutex); 92 int (*f_pthread_mutex_trylock) 93 (pthread_mutex_t *__mutex); 94 int (*f_pthread_mutex_timedlock) 95 (pthread_mutex_t *__mutex, const struct timespec *); 96 int (*f_pthread_mutex_unlock) 97 (pthread_mutex_t *__mutex); 98 int (*f_pthread_once) 99 (pthread_once_t *, void (*) (void)); 100 int (*f_pthread_rwlock_destroy) 101 (pthread_rwlock_t *__rwlock); 102 int (*f_pthread_rwlock_init) 103 (pthread_rwlock_t *__rwlock, const pthread_rwlockattr_t *); 104 int (*f_pthread_rwlock_rdlock) 105 (pthread_rwlock_t *__rwlock); 106 int (*f_pthread_rwlock_timedrdlock) 107 (pthread_rwlock_t *__rwlock, const struct timespec *); 108 int (*f_pthread_rwlock_timedwrlock) 109 (pthread_rwlock_t *__rwlock, const struct timespec *); 110 int (*f_pthread_rwlock_tryrdlock) 111 (pthread_rwlock_t *__rwlock); 112 int (*f_pthread_rwlock_trywrlock) 113 (pthread_rwlock_t *__rwlock); 114 int (*f_pthread_rwlock_unlock) 115 (pthread_rwlock_t *__rwlock); 116 int (*f_pthread_rwlock_wrlock) 117 (pthread_rwlock_t *__rwlock); 118 pthread_t (*f_pthread_self) 119 (void); 120 int (*f_pthread_setspecific) 121 (pthread_key_t, const void *); 122 int (*f_pthread_spin_init) 123 (pthread_spinlock_t *__spin, int); 124 int (*f_pthread_spin_destroy) 125 (pthread_spinlock_t *__spin); 126 int (*f_pthread_spin_lock) 127 (pthread_spinlock_t *__spin); 128 int (*f_pthread_spin_trylock) 129 (pthread_spinlock_t *__spin); 130 int (*f_pthread_spin_unlock) 131 (pthread_spinlock_t *__spin); 132 int (*f_pthread_cancel) 133 (pthread_t); 134 int (*f_pthread_setcancelstate) 135 (int, int *); 136 int (*f_pthread_setcanceltype) 137 (int, int *); 138 void (*f_pthread_testcancel) 139 (void); 140 int (*f_pthread_getschedparam) 141 (pthread_t pthread, int *, struct sched_param *); 142 int (*f_pthread_setschedparam) 143 (pthread_t, int, const struct sched_param *); 144 int (*f_pthread_yield) 145 (void); 146 int (*f_pthread_setaffinity_np) 147 (pthread_t thread, size_t cpusetsize, const rte_cpuset_t *cpuset); 148 int (*f_nanosleep) 149 (const struct timespec *req, struct timespec *rem); 150 } _sys_pthread_funcs = { 151 .f_pthread_barrier_destroy = NULL, 152 }; 153 154 155 /* 156 * this macro obtains the loaded address of a library function 157 * and saves it. 158 */ 159 static void *__libc_dl_handle = RTLD_NEXT; 160 161 #define get_addr_of_loaded_symbol(name) do { \ 162 char *error_str; \ 163 _sys_pthread_funcs.f_##name = dlsym(__libc_dl_handle, (#name)); \ 164 error_str = dlerror(); \ 165 if (error_str != NULL) { \ 166 fprintf(stderr, "%s\n", error_str); \ 167 } \ 168 } while (0) 169 170 171 /* 172 * The constructor function initialises the 173 * function pointers for pthread library functions 174 */ 175 RTE_INIT(pthread_intercept_ctor) 176 { 177 override = 0; 178 /* 179 * Get the original functions 180 */ 181 get_addr_of_loaded_symbol(pthread_barrier_destroy); 182 get_addr_of_loaded_symbol(pthread_barrier_init); 183 get_addr_of_loaded_symbol(pthread_barrier_wait); 184 get_addr_of_loaded_symbol(pthread_cond_broadcast); 185 get_addr_of_loaded_symbol(pthread_cond_destroy); 186 get_addr_of_loaded_symbol(pthread_cond_init); 187 get_addr_of_loaded_symbol(pthread_cond_signal); 188 get_addr_of_loaded_symbol(pthread_cond_timedwait); 189 get_addr_of_loaded_symbol(pthread_cond_wait); 190 get_addr_of_loaded_symbol(pthread_create); 191 get_addr_of_loaded_symbol(pthread_detach); 192 get_addr_of_loaded_symbol(pthread_equal); 193 get_addr_of_loaded_symbol(pthread_exit); 194 get_addr_of_loaded_symbol(pthread_getspecific); 195 get_addr_of_loaded_symbol(pthread_getcpuclockid); 196 get_addr_of_loaded_symbol(pthread_join); 197 get_addr_of_loaded_symbol(pthread_key_create); 198 get_addr_of_loaded_symbol(pthread_key_delete); 199 get_addr_of_loaded_symbol(pthread_mutex_destroy); 200 get_addr_of_loaded_symbol(pthread_mutex_init); 201 get_addr_of_loaded_symbol(pthread_mutex_lock); 202 get_addr_of_loaded_symbol(pthread_mutex_trylock); 203 get_addr_of_loaded_symbol(pthread_mutex_timedlock); 204 get_addr_of_loaded_symbol(pthread_mutex_unlock); 205 get_addr_of_loaded_symbol(pthread_once); 206 get_addr_of_loaded_symbol(pthread_rwlock_destroy); 207 get_addr_of_loaded_symbol(pthread_rwlock_init); 208 get_addr_of_loaded_symbol(pthread_rwlock_rdlock); 209 get_addr_of_loaded_symbol(pthread_rwlock_timedrdlock); 210 get_addr_of_loaded_symbol(pthread_rwlock_timedwrlock); 211 get_addr_of_loaded_symbol(pthread_rwlock_tryrdlock); 212 get_addr_of_loaded_symbol(pthread_rwlock_trywrlock); 213 get_addr_of_loaded_symbol(pthread_rwlock_unlock); 214 get_addr_of_loaded_symbol(pthread_rwlock_wrlock); 215 get_addr_of_loaded_symbol(pthread_self); 216 get_addr_of_loaded_symbol(pthread_setspecific); 217 get_addr_of_loaded_symbol(pthread_spin_init); 218 get_addr_of_loaded_symbol(pthread_spin_destroy); 219 get_addr_of_loaded_symbol(pthread_spin_lock); 220 get_addr_of_loaded_symbol(pthread_spin_trylock); 221 get_addr_of_loaded_symbol(pthread_spin_unlock); 222 get_addr_of_loaded_symbol(pthread_cancel); 223 get_addr_of_loaded_symbol(pthread_setcancelstate); 224 get_addr_of_loaded_symbol(pthread_setcanceltype); 225 get_addr_of_loaded_symbol(pthread_testcancel); 226 get_addr_of_loaded_symbol(pthread_getschedparam); 227 get_addr_of_loaded_symbol(pthread_setschedparam); 228 get_addr_of_loaded_symbol(pthread_yield); 229 get_addr_of_loaded_symbol(pthread_setaffinity_np); 230 get_addr_of_loaded_symbol(nanosleep); 231 } 232 233 234 /* 235 * Enable/Disable pthread override 236 * state 237 * 0 disable 238 * 1 enable 239 */ 240 void pthread_override_set(int state) 241 { 242 override = state; 243 } 244 245 246 /* 247 * Return pthread override state 248 * return 249 * 0 disable 250 * 1 enable 251 */ 252 int pthread_override_get(void) 253 { 254 return override; 255 } 256 257 /* 258 * This macro is used to catch and log 259 * invocation of stubs for unimplemented pthread 260 * API functions. 261 */ 262 #define NOT_IMPLEMENTED do { \ 263 if (override) { \ 264 RTE_LOG(WARNING, \ 265 PTHREAD_SHIM, \ 266 "WARNING %s NOT IMPLEMENTED\n", \ 267 __func__); \ 268 } \ 269 } while (0) 270 271 /* 272 * pthread API override functions follow 273 * Note in this example code only a subset of functions are 274 * implemented. 275 * 276 * The stub functions provided will issue a warning log 277 * message if an unimplemented function is invoked 278 * 279 */ 280 281 int pthread_barrier_destroy(pthread_barrier_t *a) 282 { 283 NOT_IMPLEMENTED; 284 return _sys_pthread_funcs.f_pthread_barrier_destroy(a); 285 } 286 287 int 288 pthread_barrier_init(pthread_barrier_t *a, 289 const pthread_barrierattr_t *b, unsigned c) 290 { 291 NOT_IMPLEMENTED; 292 return _sys_pthread_funcs.f_pthread_barrier_init(a, b, c); 293 } 294 295 int pthread_barrier_wait(pthread_barrier_t *a) 296 { 297 NOT_IMPLEMENTED; 298 return _sys_pthread_funcs.f_pthread_barrier_wait(a); 299 } 300 301 int pthread_cond_broadcast(pthread_cond_t *cond) 302 { 303 if (override) { 304 305 lthread_cond_broadcast(*(struct lthread_cond **)cond); 306 return 0; 307 } 308 return _sys_pthread_funcs.f_pthread_cond_broadcast(cond); 309 } 310 311 int pthread_mutex_destroy(pthread_mutex_t *mutex) 312 { 313 if (override) 314 return lthread_mutex_destroy(*(struct lthread_mutex **)mutex); 315 return _sys_pthread_funcs.f_pthread_mutex_destroy(mutex); 316 } 317 318 int pthread_cond_destroy(pthread_cond_t *cond) 319 { 320 if (override) 321 return lthread_cond_destroy(*(struct lthread_cond **)cond); 322 return _sys_pthread_funcs.f_pthread_cond_destroy(cond); 323 } 324 325 int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) 326 { 327 if (override) 328 return lthread_cond_init(NULL, 329 (struct lthread_cond **)cond, 330 (const struct lthread_condattr *) attr); 331 return _sys_pthread_funcs.f_pthread_cond_init(cond, attr); 332 } 333 334 int pthread_cond_signal(pthread_cond_t *cond) 335 { 336 if (override) { 337 lthread_cond_signal(*(struct lthread_cond **)cond); 338 return 0; 339 } 340 return _sys_pthread_funcs.f_pthread_cond_signal(cond); 341 } 342 343 int 344 pthread_cond_timedwait(pthread_cond_t *__restrict cond, 345 pthread_mutex_t *__restrict mutex, 346 const struct timespec *__restrict time) 347 { 348 NOT_IMPLEMENTED; 349 return _sys_pthread_funcs.f_pthread_cond_timedwait(cond, mutex, time); 350 } 351 352 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) 353 { 354 if (override) { 355 pthread_mutex_unlock(mutex); 356 int rv = lthread_cond_wait(*(struct lthread_cond **)cond, 0); 357 358 pthread_mutex_lock(mutex); 359 return rv; 360 } 361 return _sys_pthread_funcs.f_pthread_cond_wait(cond, mutex); 362 } 363 364 int 365 pthread_create(pthread_t *__restrict tid, 366 const pthread_attr_t *__restrict attr, 367 lthread_func_t func, 368 void *__restrict arg) 369 { 370 if (override) { 371 int lcore = -1; 372 373 if (attr != NULL) { 374 /* determine CPU being requested */ 375 rte_cpuset_t cpuset; 376 377 CPU_ZERO(&cpuset); 378 pthread_attr_getaffinity_np(attr, 379 sizeof(rte_cpuset_t), 380 &cpuset); 381 382 if (CPU_COUNT(&cpuset) != 1) 383 return POSIX_ERRNO(EINVAL); 384 385 for (lcore = 0; lcore < LTHREAD_MAX_LCORES; lcore++) { 386 if (!CPU_ISSET(lcore, &cpuset)) 387 continue; 388 break; 389 } 390 } 391 return lthread_create((struct lthread **)tid, lcore, 392 func, arg); 393 } 394 return _sys_pthread_funcs.f_pthread_create(tid, attr, func, arg); 395 } 396 397 int pthread_detach(pthread_t tid) 398 { 399 if (override) { 400 struct lthread *lt = (struct lthread *)tid; 401 402 if (lt == lthread_current()) { 403 lthread_detach(); 404 return 0; 405 } 406 NOT_IMPLEMENTED; 407 } 408 return _sys_pthread_funcs.f_pthread_detach(tid); 409 } 410 411 int pthread_equal(pthread_t a, pthread_t b) 412 { 413 NOT_IMPLEMENTED; 414 return _sys_pthread_funcs.f_pthread_equal(a, b); 415 } 416 417 void pthread_exit_override(void *v) 418 { 419 if (override) { 420 lthread_exit(v); 421 return; 422 } 423 _sys_pthread_funcs.f_pthread_exit(v); 424 } 425 426 void 427 *pthread_getspecific(pthread_key_t key) 428 { 429 if (override) 430 return lthread_getspecific((unsigned int) key); 431 return _sys_pthread_funcs.f_pthread_getspecific(key); 432 } 433 434 int pthread_getcpuclockid(pthread_t a, clockid_t *b) 435 { 436 NOT_IMPLEMENTED; 437 return _sys_pthread_funcs.f_pthread_getcpuclockid(a, b); 438 } 439 440 int pthread_join(pthread_t tid, void **val) 441 { 442 if (override) 443 return lthread_join((struct lthread *)tid, val); 444 return _sys_pthread_funcs.f_pthread_join(tid, val); 445 } 446 447 int pthread_key_create(pthread_key_t *keyptr, void (*dtor) (void *)) 448 { 449 if (override) 450 return lthread_key_create((unsigned int *)keyptr, dtor); 451 return _sys_pthread_funcs.f_pthread_key_create(keyptr, dtor); 452 } 453 454 int pthread_key_delete(pthread_key_t key) 455 { 456 if (override) { 457 lthread_key_delete((unsigned int) key); 458 return 0; 459 } 460 return _sys_pthread_funcs.f_pthread_key_delete(key); 461 } 462 463 464 int 465 pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) 466 { 467 if (override) 468 return lthread_mutex_init(NULL, 469 (struct lthread_mutex **)mutex, 470 (const struct lthread_mutexattr *)attr); 471 return _sys_pthread_funcs.f_pthread_mutex_init(mutex, attr); 472 } 473 474 int pthread_mutex_lock(pthread_mutex_t *mutex) 475 { 476 if (override) 477 return lthread_mutex_lock(*(struct lthread_mutex **)mutex); 478 return _sys_pthread_funcs.f_pthread_mutex_lock(mutex); 479 } 480 481 int pthread_mutex_trylock(pthread_mutex_t *mutex) 482 { 483 if (override) 484 return lthread_mutex_trylock(*(struct lthread_mutex **)mutex); 485 return _sys_pthread_funcs.f_pthread_mutex_trylock(mutex); 486 } 487 488 int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *b) 489 { 490 NOT_IMPLEMENTED; 491 return _sys_pthread_funcs.f_pthread_mutex_timedlock(mutex, b); 492 } 493 494 int pthread_mutex_unlock(pthread_mutex_t *mutex) 495 { 496 if (override) 497 return lthread_mutex_unlock(*(struct lthread_mutex **)mutex); 498 return _sys_pthread_funcs.f_pthread_mutex_unlock(mutex); 499 } 500 501 int pthread_once(pthread_once_t *a, void (b) (void)) 502 { 503 NOT_IMPLEMENTED; 504 return _sys_pthread_funcs.f_pthread_once(a, b); 505 } 506 507 int pthread_rwlock_destroy(pthread_rwlock_t *a) 508 { 509 NOT_IMPLEMENTED; 510 return _sys_pthread_funcs.f_pthread_rwlock_destroy(a); 511 } 512 513 int pthread_rwlock_init(pthread_rwlock_t *a, const pthread_rwlockattr_t *b) 514 { 515 NOT_IMPLEMENTED; 516 return _sys_pthread_funcs.f_pthread_rwlock_init(a, b); 517 } 518 519 int pthread_rwlock_rdlock(pthread_rwlock_t *a) 520 { 521 NOT_IMPLEMENTED; 522 return _sys_pthread_funcs.f_pthread_rwlock_rdlock(a); 523 } 524 525 int pthread_rwlock_timedrdlock(pthread_rwlock_t *a, const struct timespec *b) 526 { 527 NOT_IMPLEMENTED; 528 return _sys_pthread_funcs.f_pthread_rwlock_timedrdlock(a, b); 529 } 530 531 int pthread_rwlock_timedwrlock(pthread_rwlock_t *a, const struct timespec *b) 532 { 533 NOT_IMPLEMENTED; 534 return _sys_pthread_funcs.f_pthread_rwlock_timedwrlock(a, b); 535 } 536 537 int pthread_rwlock_tryrdlock(pthread_rwlock_t *a) 538 { 539 NOT_IMPLEMENTED; 540 return _sys_pthread_funcs.f_pthread_rwlock_tryrdlock(a); 541 } 542 543 int pthread_rwlock_trywrlock(pthread_rwlock_t *a) 544 { 545 NOT_IMPLEMENTED; 546 return _sys_pthread_funcs.f_pthread_rwlock_trywrlock(a); 547 } 548 549 int pthread_rwlock_unlock(pthread_rwlock_t *a) 550 { 551 NOT_IMPLEMENTED; 552 return _sys_pthread_funcs.f_pthread_rwlock_unlock(a); 553 } 554 555 int pthread_rwlock_wrlock(pthread_rwlock_t *a) 556 { 557 NOT_IMPLEMENTED; 558 return _sys_pthread_funcs.f_pthread_rwlock_wrlock(a); 559 } 560 561 #ifdef RTE_EXEC_ENV_LINUXAPP 562 int 563 pthread_yield(void) 564 { 565 if (override) { 566 lthread_yield(); 567 return 0; 568 } 569 return _sys_pthread_funcs.f_pthread_yield(); 570 } 571 #else 572 void 573 pthread_yield(void) 574 { 575 if (override) 576 lthread_yield(); 577 else 578 _sys_pthread_funcs.f_pthread_yield(); 579 } 580 #endif 581 582 pthread_t pthread_self(void) 583 { 584 if (override) 585 return (pthread_t) lthread_current(); 586 return _sys_pthread_funcs.f_pthread_self(); 587 } 588 589 int pthread_setspecific(pthread_key_t key, const void *data) 590 { 591 if (override) { 592 int rv = lthread_setspecific((unsigned int)key, data); 593 return rv; 594 } 595 return _sys_pthread_funcs.f_pthread_setspecific(key, data); 596 } 597 598 int pthread_spin_init(pthread_spinlock_t *a, int b) 599 { 600 NOT_IMPLEMENTED; 601 return _sys_pthread_funcs.f_pthread_spin_init(a, b); 602 } 603 604 int pthread_spin_destroy(pthread_spinlock_t *a) 605 { 606 NOT_IMPLEMENTED; 607 return _sys_pthread_funcs.f_pthread_spin_destroy(a); 608 } 609 610 int pthread_spin_lock(pthread_spinlock_t *a) 611 { 612 NOT_IMPLEMENTED; 613 return _sys_pthread_funcs.f_pthread_spin_lock(a); 614 } 615 616 int pthread_spin_trylock(pthread_spinlock_t *a) 617 { 618 NOT_IMPLEMENTED; 619 return _sys_pthread_funcs.f_pthread_spin_trylock(a); 620 } 621 622 int pthread_spin_unlock(pthread_spinlock_t *a) 623 { 624 NOT_IMPLEMENTED; 625 return _sys_pthread_funcs.f_pthread_spin_unlock(a); 626 } 627 628 int pthread_cancel(pthread_t tid) 629 { 630 if (override) { 631 lthread_cancel(*(struct lthread **)tid); 632 return 0; 633 } 634 return _sys_pthread_funcs.f_pthread_cancel(tid); 635 } 636 637 int pthread_setcancelstate(int a, int *b) 638 { 639 NOT_IMPLEMENTED; 640 return _sys_pthread_funcs.f_pthread_setcancelstate(a, b); 641 } 642 643 int pthread_setcanceltype(int a, int *b) 644 { 645 NOT_IMPLEMENTED; 646 return _sys_pthread_funcs.f_pthread_setcanceltype(a, b); 647 } 648 649 void pthread_testcancel(void) 650 { 651 NOT_IMPLEMENTED; 652 return _sys_pthread_funcs.f_pthread_testcancel(); 653 } 654 655 656 int pthread_getschedparam(pthread_t tid, int *a, struct sched_param *b) 657 { 658 NOT_IMPLEMENTED; 659 return _sys_pthread_funcs.f_pthread_getschedparam(tid, a, b); 660 } 661 662 int pthread_setschedparam(pthread_t a, int b, const struct sched_param *c) 663 { 664 NOT_IMPLEMENTED; 665 return _sys_pthread_funcs.f_pthread_setschedparam(a, b, c); 666 } 667 668 669 int nanosleep(const struct timespec *req, struct timespec *rem) 670 { 671 if (override) { 672 uint64_t ns = req->tv_sec * 1000000000 + req->tv_nsec; 673 674 lthread_sleep(ns); 675 return 0; 676 } 677 return _sys_pthread_funcs.f_nanosleep(req, rem); 678 } 679 680 int 681 pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, 682 const rte_cpuset_t *cpuset) 683 { 684 if (override) { 685 /* we only allow affinity with a single CPU */ 686 if (CPU_COUNT(cpuset) != 1) 687 return POSIX_ERRNO(EINVAL); 688 689 /* we only allow the current thread to sets its own affinity */ 690 struct lthread *lt = (struct lthread *)thread; 691 692 if (lthread_current() != lt) 693 return POSIX_ERRNO(EINVAL); 694 695 /* determine the CPU being requested */ 696 int i; 697 698 for (i = 0; i < LTHREAD_MAX_LCORES; i++) { 699 if (!CPU_ISSET(i, cpuset)) 700 continue; 701 break; 702 } 703 /* check requested core is allowed */ 704 if (i == LTHREAD_MAX_LCORES) 705 return POSIX_ERRNO(EINVAL); 706 707 /* finally we can set affinity to the requested lcore */ 708 lthread_set_affinity(i); 709 return 0; 710 } 711 return _sys_pthread_funcs.f_pthread_setaffinity_np(thread, cpusetsize, 712 cpuset); 713 } 714