diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/futex.c | 30 | ||||
-rw-r--r-- | kernel/locking/rtmutex.c | 49 | ||||
-rw-r--r-- | kernel/locking/rtmutex_common.h | 3 |
3 files changed, 52 insertions, 30 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index 4cdc603b00c3..628be42296eb 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -2654,20 +2654,33 @@ retry_private: | |||
2654 | goto no_block; | 2654 | goto no_block; |
2655 | } | 2655 | } |
2656 | 2656 | ||
2657 | rt_mutex_init_waiter(&rt_waiter); | ||
2658 | |||
2657 | /* | 2659 | /* |
2658 | * We must add ourselves to the rt_mutex waitlist while holding hb->lock | 2660 | * On PREEMPT_RT_FULL, when hb->lock becomes an rt_mutex, we must not |
2659 | * such that the hb and rt_mutex wait lists match. | 2661 | * hold it while doing rt_mutex_start_proxy(), because then it will |
2662 | * include hb->lock in the blocking chain, even through we'll not in | ||
2663 | * fact hold it while blocking. This will lead it to report -EDEADLK | ||
2664 | * and BUG when futex_unlock_pi() interleaves with this. | ||
2665 | * | ||
2666 | * Therefore acquire wait_lock while holding hb->lock, but drop the | ||
2667 | * latter before calling rt_mutex_start_proxy_lock(). This still fully | ||
2668 | * serializes against futex_unlock_pi() as that does the exact same | ||
2669 | * lock handoff sequence. | ||
2660 | */ | 2670 | */ |
2661 | rt_mutex_init_waiter(&rt_waiter); | 2671 | raw_spin_lock_irq(&q.pi_state->pi_mutex.wait_lock); |
2662 | ret = rt_mutex_start_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter, current); | 2672 | spin_unlock(q.lock_ptr); |
2673 | ret = __rt_mutex_start_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter, current); | ||
2674 | raw_spin_unlock_irq(&q.pi_state->pi_mutex.wait_lock); | ||
2675 | |||
2663 | if (ret) { | 2676 | if (ret) { |
2664 | if (ret == 1) | 2677 | if (ret == 1) |
2665 | ret = 0; | 2678 | ret = 0; |
2666 | 2679 | ||
2680 | spin_lock(q.lock_ptr); | ||
2667 | goto no_block; | 2681 | goto no_block; |
2668 | } | 2682 | } |
2669 | 2683 | ||
2670 | spin_unlock(q.lock_ptr); | ||
2671 | 2684 | ||
2672 | if (unlikely(to)) | 2685 | if (unlikely(to)) |
2673 | hrtimer_start_expires(&to->timer, HRTIMER_MODE_ABS); | 2686 | hrtimer_start_expires(&to->timer, HRTIMER_MODE_ABS); |
@@ -2680,6 +2693,9 @@ retry_private: | |||
2680 | * first acquire the hb->lock before removing the lock from the | 2693 | * first acquire the hb->lock before removing the lock from the |
2681 | * rt_mutex waitqueue, such that we can keep the hb and rt_mutex | 2694 | * rt_mutex waitqueue, such that we can keep the hb and rt_mutex |
2682 | * wait lists consistent. | 2695 | * wait lists consistent. |
2696 | * | ||
2697 | * In particular; it is important that futex_unlock_pi() can not | ||
2698 | * observe this inconsistency. | ||
2683 | */ | 2699 | */ |
2684 | if (ret && !rt_mutex_cleanup_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter)) | 2700 | if (ret && !rt_mutex_cleanup_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter)) |
2685 | ret = 0; | 2701 | ret = 0; |
@@ -2791,10 +2807,6 @@ retry: | |||
2791 | 2807 | ||
2792 | get_pi_state(pi_state); | 2808 | get_pi_state(pi_state); |
2793 | /* | 2809 | /* |
2794 | * Since modifying the wait_list is done while holding both | ||
2795 | * hb->lock and wait_lock, holding either is sufficient to | ||
2796 | * observe it. | ||
2797 | * | ||
2798 | * By taking wait_lock while still holding hb->lock, we ensure | 2810 | * By taking wait_lock while still holding hb->lock, we ensure |
2799 | * there is no point where we hold neither; and therefore | 2811 | * there is no point where we hold neither; and therefore |
2800 | * wake_futex_pi() must observe a state consistent with what we | 2812 | * wake_futex_pi() must observe a state consistent with what we |
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c index 48418a1733b8..dd103124166b 100644 --- a/kernel/locking/rtmutex.c +++ b/kernel/locking/rtmutex.c | |||
@@ -1669,31 +1669,14 @@ void rt_mutex_proxy_unlock(struct rt_mutex *lock, | |||
1669 | rt_mutex_set_owner(lock, NULL); | 1669 | rt_mutex_set_owner(lock, NULL); |
1670 | } | 1670 | } |
1671 | 1671 | ||
1672 | /** | 1672 | int __rt_mutex_start_proxy_lock(struct rt_mutex *lock, |
1673 | * rt_mutex_start_proxy_lock() - Start lock acquisition for another task | ||
1674 | * @lock: the rt_mutex to take | ||
1675 | * @waiter: the pre-initialized rt_mutex_waiter | ||
1676 | * @task: the task to prepare | ||
1677 | * | ||
1678 | * Returns: | ||
1679 | * 0 - task blocked on lock | ||
1680 | * 1 - acquired the lock for task, caller should wake it up | ||
1681 | * <0 - error | ||
1682 | * | ||
1683 | * Special API call for FUTEX_REQUEUE_PI support. | ||
1684 | */ | ||
1685 | int rt_mutex_start_proxy_lock(struct rt_mutex *lock, | ||
1686 | struct rt_mutex_waiter *waiter, | 1673 | struct rt_mutex_waiter *waiter, |
1687 | struct task_struct *task) | 1674 | struct task_struct *task) |
1688 | { | 1675 | { |
1689 | int ret; | 1676 | int ret; |
1690 | 1677 | ||
1691 | raw_spin_lock_irq(&lock->wait_lock); | 1678 | if (try_to_take_rt_mutex(lock, task, NULL)) |
1692 | |||
1693 | if (try_to_take_rt_mutex(lock, task, NULL)) { | ||
1694 | raw_spin_unlock_irq(&lock->wait_lock); | ||
1695 | return 1; | 1679 | return 1; |
1696 | } | ||
1697 | 1680 | ||
1698 | /* We enforce deadlock detection for futexes */ | 1681 | /* We enforce deadlock detection for futexes */ |
1699 | ret = task_blocks_on_rt_mutex(lock, waiter, task, | 1682 | ret = task_blocks_on_rt_mutex(lock, waiter, task, |
@@ -1712,14 +1695,38 @@ int rt_mutex_start_proxy_lock(struct rt_mutex *lock, | |||
1712 | if (unlikely(ret)) | 1695 | if (unlikely(ret)) |
1713 | remove_waiter(lock, waiter); | 1696 | remove_waiter(lock, waiter); |
1714 | 1697 | ||
1715 | raw_spin_unlock_irq(&lock->wait_lock); | ||
1716 | |||
1717 | debug_rt_mutex_print_deadlock(waiter); | 1698 | debug_rt_mutex_print_deadlock(waiter); |
1718 | 1699 | ||
1719 | return ret; | 1700 | return ret; |
1720 | } | 1701 | } |
1721 | 1702 | ||
1722 | /** | 1703 | /** |
1704 | * rt_mutex_start_proxy_lock() - Start lock acquisition for another task | ||
1705 | * @lock: the rt_mutex to take | ||
1706 | * @waiter: the pre-initialized rt_mutex_waiter | ||
1707 | * @task: the task to prepare | ||
1708 | * | ||
1709 | * Returns: | ||
1710 | * 0 - task blocked on lock | ||
1711 | * 1 - acquired the lock for task, caller should wake it up | ||
1712 | * <0 - error | ||
1713 | * | ||
1714 | * Special API call for FUTEX_REQUEUE_PI support. | ||
1715 | */ | ||
1716 | int rt_mutex_start_proxy_lock(struct rt_mutex *lock, | ||
1717 | struct rt_mutex_waiter *waiter, | ||
1718 | struct task_struct *task) | ||
1719 | { | ||
1720 | int ret; | ||
1721 | |||
1722 | raw_spin_lock_irq(&lock->wait_lock); | ||
1723 | ret = __rt_mutex_start_proxy_lock(lock, waiter, task); | ||
1724 | raw_spin_unlock_irq(&lock->wait_lock); | ||
1725 | |||
1726 | return ret; | ||
1727 | } | ||
1728 | |||
1729 | /** | ||
1723 | * rt_mutex_next_owner - return the next owner of the lock | 1730 | * rt_mutex_next_owner - return the next owner of the lock |
1724 | * | 1731 | * |
1725 | * @lock: the rt lock query | 1732 | * @lock: the rt lock query |
diff --git a/kernel/locking/rtmutex_common.h b/kernel/locking/rtmutex_common.h index 1e93e15a0e45..b1ccfea2effe 100644 --- a/kernel/locking/rtmutex_common.h +++ b/kernel/locking/rtmutex_common.h | |||
@@ -104,6 +104,9 @@ extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock, | |||
104 | extern void rt_mutex_proxy_unlock(struct rt_mutex *lock, | 104 | extern void rt_mutex_proxy_unlock(struct rt_mutex *lock, |
105 | struct task_struct *proxy_owner); | 105 | struct task_struct *proxy_owner); |
106 | extern void rt_mutex_init_waiter(struct rt_mutex_waiter *waiter); | 106 | extern void rt_mutex_init_waiter(struct rt_mutex_waiter *waiter); |
107 | extern int __rt_mutex_start_proxy_lock(struct rt_mutex *lock, | ||
108 | struct rt_mutex_waiter *waiter, | ||
109 | struct task_struct *task); | ||
107 | extern int rt_mutex_start_proxy_lock(struct rt_mutex *lock, | 110 | extern int rt_mutex_start_proxy_lock(struct rt_mutex *lock, |
108 | struct rt_mutex_waiter *waiter, | 111 | struct rt_mutex_waiter *waiter, |
109 | struct task_struct *task); | 112 | struct task_struct *task); |