* @brief Lock a futex with priority inheritance (PI) * * @param[in] futex Futex object to lock * @param[in] lwp Lightweight process structure * @param[in] uaddr User-space address of futex value * @param[in] timeout Optional timeout specification (CLOCK_REALTIME) * @param[in] op_flags Operation flags (e.g. FUTEX_PRIVATE) * @param[in] trylock If true, performs non-blocking trylock operation
| 747 | * - Uses mutex with priority inheritance for waiting |
| 748 | */ |
| 749 | static long _futex_lock_pi(rt_futex_t futex, struct rt_lwp *lwp, int *uaddr, |
| 750 | const struct timespec *timeout, int op_flags, |
| 751 | rt_bool_t trylock) |
| 752 | { |
| 753 | int word = 0, nword, cword; |
| 754 | int tid = 0; |
| 755 | rt_err_t err = 0; |
| 756 | rt_thread_t thread = RT_NULL, current_thread = RT_NULL; |
| 757 | rt_tick_t to = RT_WAITING_FOREVER; |
| 758 | |
| 759 | if (!lwp_user_accessable((void *)uaddr, sizeof(*uaddr))) |
| 760 | { |
| 761 | return -EFAULT; |
| 762 | } |
| 763 | |
| 764 | current_thread = rt_thread_self(); |
| 765 | |
| 766 | _futex_lock(lwp, op_flags); |
| 767 | |
| 768 | lwp_get_from_user(&word, (void *)uaddr, sizeof(int)); |
| 769 | tid = word & FUTEX_TID_MASK; |
| 770 | if (word == 0) |
| 771 | { |
| 772 | /* If the value is 0, then the kernel tries |
| 773 | to atomically set the futex value to the caller's TID. */ |
| 774 | nword = current_thread->tid; |
| 775 | if (_futex_cmpxchg_value(&cword, uaddr, word, nword)) |
| 776 | { |
| 777 | _futex_unlock(lwp, op_flags); |
| 778 | return -EAGAIN; |
| 779 | } |
| 780 | _futex_unlock(lwp, op_flags); |
| 781 | return 0; |
| 782 | } |
| 783 | else |
| 784 | { |
| 785 | thread = lwp_tid_get_thread_and_inc_ref(tid); |
| 786 | if (thread == RT_NULL) |
| 787 | { |
| 788 | _futex_unlock(lwp, op_flags); |
| 789 | return -ESRCH; |
| 790 | } |
| 791 | lwp_tid_dec_ref(thread); |
| 792 | |
| 793 | nword = |
| 794 | word | FUTEX_WAITERS; |
| 795 | if (_futex_cmpxchg_value(&cword, uaddr, word, nword)) |
| 796 | { |
| 797 | _futex_unlock(lwp, op_flags); |
| 798 | return -EAGAIN; |
| 799 | } |
| 800 | word = nword; |
| 801 | } |
| 802 | |
| 803 | if (futex->mutex == RT_NULL) |
| 804 | { |
| 805 | futex->mutex = rt_mutex_create("futexpi", RT_IPC_FLAG_PRIO); |
| 806 | if (futex->mutex == RT_NULL) |
no test coverage detected