* @brief Wait on a futex if its value matches the expected value. * * @param[in] futex The futex to wait on * @param[in] lwp Lightweight process structure * @param[in] uaddr User-space address of futex value * @param[in] value Expected value to compare against * @param[in] timeout Optional timeout specification * @param[in] op_flags Operation flags (e.g. FUTEX_PRIVATE) * * @return int Ret
| 533 | * - EAGAIN if value does not match |
| 534 | */ |
| 535 | static int _futex_wait(rt_futex_t futex, struct rt_lwp *lwp, int *uaddr, |
| 536 | int value, const struct timespec *timeout, int op_flags) |
| 537 | { |
| 538 | rt_tick_t to; |
| 539 | rt_thread_t thread; |
| 540 | rt_err_t rc = -RT_EINTR; |
| 541 | |
| 542 | /** |
| 543 | * Brief: Remove current thread from scheduler, besides appends it to |
| 544 | * the waiting thread list of the futex. If the timeout is specified |
| 545 | * a timer will be setup for current thread |
| 546 | * |
| 547 | * Note: Critical Section |
| 548 | * - futex.waiting (RW; Protected by lwp_lock) |
| 549 | * - the local cpu |
| 550 | */ |
| 551 | _futex_lock(lwp, op_flags); |
| 552 | if (*uaddr == value) |
| 553 | { |
| 554 | thread = rt_thread_self(); |
| 555 | |
| 556 | if (timeout) |
| 557 | { |
| 558 | to = timeout->tv_sec * RT_TICK_PER_SECOND; |
| 559 | to += |
| 560 | (timeout->tv_nsec * RT_TICK_PER_SECOND) / NANOSECOND_PER_SECOND; |
| 561 | |
| 562 | if (to < 0) |
| 563 | { |
| 564 | rc = -EINVAL; |
| 565 | _futex_unlock(lwp, op_flags); |
| 566 | } |
| 567 | else |
| 568 | { |
| 569 | rt_enter_critical(); |
| 570 | rc = _suspend_thread_timeout_locked(thread, futex, to); |
| 571 | _futex_unlock(lwp, op_flags); |
| 572 | rt_exit_critical(); |
| 573 | } |
| 574 | } |
| 575 | else |
| 576 | { |
| 577 | rt_enter_critical(); |
| 578 | rc = _suspend_thread_locked(thread, futex); |
| 579 | _futex_unlock(lwp, op_flags); |
| 580 | rt_exit_critical(); |
| 581 | } |
| 582 | |
| 583 | if (rc == RT_EOK) |
| 584 | { |
| 585 | /* do schedule */ |
| 586 | rt_schedule(); |
| 587 | /* check errno */ |
| 588 | rc = rt_get_errno(); |
| 589 | rc = rc > 0 ? -rc : rc; |
| 590 | } |
| 591 | } |
| 592 | else |
no test coverage detected