Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1606349 > unrolled thread
| Started by | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| First post | 2017-03-22 11:50 +0100 |
| Last post | 2017-03-24 02:50 +0100 |
| Articles | 8 on this page of 28 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH -v6 00/13] The arduous story of FUTEX_UNLOCK_PI Peter Zijlstra <peterz@infradead.org> - 2017-03-22 11:50 +0100
[PATCH -v6 10/13] futex,rt_mutex: Restructure rt_mutex_finish_proxy_lock() Peter Zijlstra <peterz@infradead.org> - 2017-03-22 11:50 +0100
[tip:locking/core] futex,rt_mutex: Restructure rt_mutex_finish_proxy_lock() tip-bot for Peter Zijlstra <tipbot@zytor.com> - 2017-03-23 19:30 +0100
[PATCH -v6 07/13] futex: Rework inconsistent rt_mutex/futex_q state Peter Zijlstra <peterz@infradead.org> - 2017-03-22 11:50 +0100
[tip:locking/core] futex: Rework inconsistent rt_mutex/futex_q state tip-bot for Peter Zijlstra <tipbot@zytor.com> - 2017-03-23 19:30 +0100
[PATCH -v6 09/13] futex,rt_mutex: Introduce rt_mutex_init_waiter() Peter Zijlstra <peterz@infradead.org> - 2017-03-22 11:50 +0100
[tip:locking/core] futex,rt_mutex: Introduce rt_mutex_init_waiter() tip-bot for Peter Zijlstra <tipbot@zytor.com> - 2017-03-23 19:30 +0100
[PATCH -v6 05/13] futex: Change locking rules Peter Zijlstra <peterz@infradead.org> - 2017-03-22 11:50 +0100
[tip:locking/core] futex: Change locking rules tip-bot for Peter Zijlstra <tipbot@zytor.com> - 2017-03-23 19:30 +0100
[PATCH -v6 11/13] futex: Rework futex_lock_pi() to use rt_mutex_*_proxy_lock() Peter Zijlstra <peterz@infradead.org> - 2017-03-22 11:50 +0100
[tip:locking/core] futex: Rework futex_lock_pi() to use rt_mutex_*_proxy_lock() tip-bot for Peter Zijlstra <tipbot@zytor.com> - 2017-03-23 19:30 +0100
[PATCH -v6 13/13] futex: futex_lock_pi() vs PREEMPT_RT_FULL Peter Zijlstra <peterz@infradead.org> - 2017-03-22 11:50 +0100
[tip:locking/core] futex: Drop hb->lock before enqueueing on the rtmutex tip-bot for Peter Zijlstra <tipbot@zytor.com> - 2017-03-23 19:30 +0100
[PATCH -v6 03/13] futex: Remove rt_mutex_deadlock_account_*() Peter Zijlstra <peterz@infradead.org> - 2017-03-22 11:50 +0100
[tip:locking/core] futex: Remove rt_mutex_deadlock_account_*() tip-bot for Peter Zijlstra <tipbot@zytor.com> - 2017-03-23 19:30 +0100
Re: [PATCH -v6 03/13] futex: Remove rt_mutex_deadlock_account_*() Darren Hart <dvhart@infradead.org> - 2017-03-24 22:30 +0100
Re: [PATCH -v6 03/13] futex: Remove rt_mutex_deadlock_account_*() Darren Hart <dvhart@infradead.org> - 2017-03-24 22:40 +0100
[PATCH -v6 12/13] futex: futex_unlock_pi() determinism Peter Zijlstra <peterz@infradead.org> - 2017-03-22 11:50 +0100
[tip:locking/core] futex: Futex_unlock_pi() determinism tip-bot for Peter Zijlstra <tipbot@zytor.com> - 2017-03-23 19:30 +0100
[PATCH -v6 06/13] futex: Cleanup refcounting Peter Zijlstra <peterz@infradead.org> - 2017-03-22 11:50 +0100
[tip:locking/core] futex: Cleanup refcounting tip-bot for Peter Zijlstra <tipbot@zytor.com> - 2017-03-23 19:30 +0100
[PATCH -v6 04/13] futex,rt_mutex: Provide futex specific rt_mutex API Peter Zijlstra <peterz@infradead.org> - 2017-03-22 11:50 +0100
[tip:locking/core] futex,rt_mutex: Provide futex specific rt_mutex API tip-bot for Peter Zijlstra <tipbot@zytor.com> - 2017-03-23 19:30 +0100
Re: [PATCH -v6 04/13] futex,rt_mutex: Provide futex specific rt_mutex API Darren Hart <dvhart@infradead.org> - 2017-03-25 01:40 +0100
[PATCH -v6 02/13] futex: Use smp_store_release() in mark_wake_futex() Peter Zijlstra <peterz@infradead.org> - 2017-03-22 11:50 +0100
[tip:locking/core] futex: Use smp_store_release() in mark_wake_futex() tip-bot for Peter Zijlstra <tipbot@zytor.com> - 2017-03-23 19:30 +0100
Re: [PATCH -v6 02/13] futex: Use smp_store_release() in mark_wake_futex() Darren Hart <dvhart@infradead.org> - 2017-03-24 22:20 +0100
Re: [PATCH -v6 00/13] The arduous story of FUTEX_UNLOCK_PI Darren Hart <dvhart@infradead.org> - 2017-03-24 02:50 +0100
Page 2 of 2 — ← Prev page 1 [2]
| From | tip-bot for Peter Zijlstra <tipbot@zytor.com> |
|---|---|
| Date | 2017-03-23 19:30 +0100 |
| Subject | [tip:locking/core] futex: Cleanup refcounting |
| Message-ID | <tofEK-666-33@gated-at.bofh.it> |
| In reply to | #1606359 |
Commit-ID: bf92cf3a5100f5a0d5f9834787b130159397cb22
Gitweb: http://git.kernel.org/tip/bf92cf3a5100f5a0d5f9834787b130159397cb22
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Wed, 22 Mar 2017 11:35:53 +0100
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitDate: Thu, 23 Mar 2017 19:10:08 +0100
futex: Cleanup refcounting
Add a put_pit_state() as counterpart for get_pi_state() so the refcounting
becomes consistent.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: juri.lelli@arm.com
Cc: bigeasy@linutronix.de
Cc: xlpang@redhat.com
Cc: rostedt@goodmis.org
Cc: mathieu.desnoyers@efficios.com
Cc: jdesfossez@efficios.com
Cc: dvhart@infradead.org
Cc: bristot@redhat.com
Link: http://lkml.kernel.org/r/20170322104151.801778516@infradead.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/futex.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/kernel/futex.c b/kernel/futex.c
index 3e71d66..3b6dbee 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -802,7 +802,7 @@ static int refill_pi_state_cache(void)
return 0;
}
-static struct futex_pi_state * alloc_pi_state(void)
+static struct futex_pi_state *alloc_pi_state(void)
{
struct futex_pi_state *pi_state = current->pi_state_cache;
@@ -812,6 +812,11 @@ static struct futex_pi_state * alloc_pi_state(void)
return pi_state;
}
+static void get_pi_state(struct futex_pi_state *pi_state)
+{
+ WARN_ON_ONCE(!atomic_inc_not_zero(&pi_state->refcount));
+}
+
/*
* Drops a reference to the pi_state object and frees or caches it
* when the last reference is gone.
@@ -856,7 +861,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)
* Look up the task based on what TID userspace gave us.
* We dont trust it.
*/
-static struct task_struct * futex_find_get_task(pid_t pid)
+static struct task_struct *futex_find_get_task(pid_t pid)
{
struct task_struct *p;
@@ -1103,7 +1108,7 @@ static int attach_to_pi_state(u32 __user *uaddr, u32 uval,
goto out_einval;
out_attach:
- atomic_inc(&pi_state->refcount);
+ get_pi_state(pi_state);
raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
*ps = pi_state;
return 0;
@@ -1990,7 +1995,7 @@ retry_private:
* refcount on the pi_state and store the pointer in
* the futex_q object of the waiter.
*/
- atomic_inc(&pi_state->refcount);
+ get_pi_state(pi_state);
this->pi_state = pi_state;
ret = rt_mutex_start_proxy_lock(&pi_state->pi_mutex,
this->rt_waiter,
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-03-22 11:50 +0100 |
| Subject | [PATCH -v6 04/13] futex,rt_mutex: Provide futex specific rt_mutex API |
| Message-ID | <tnM03-11I-47@gated-at.bofh.it> |
| In reply to | #1606349 |
Part of what makes futex_unlock_pi() intricate is that
rt_mutex_futex_unlock() -> rt_mutex_slowunlock() can drop
rt_mutex::wait_lock.
This means we cannot rely on the atomicy of wait_lock, which we would
like to do in order to not rely on hb->lock so much.
The reason rt_mutex_slowunlock() needs to drop wait_lock is because it
can race with the rt_mutex fastpath, however futexes have their own
fast path.
Since futexes already have a bunch of separate rt_mutex accessors,
complete that set and implement a rt_mutex variant without fastpath
for them.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
kernel/futex.c | 30 ++++++++++-----------
kernel/locking/rtmutex.c | 55 +++++++++++++++++++++++++++++-----------
kernel/locking/rtmutex_common.h | 9 +++++-
3 files changed, 62 insertions(+), 32 deletions(-)
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -916,7 +916,7 @@ void exit_pi_state_list(struct task_stru
pi_state->owner = NULL;
raw_spin_unlock_irq(&curr->pi_lock);
- rt_mutex_unlock(&pi_state->pi_mutex);
+ rt_mutex_futex_unlock(&pi_state->pi_mutex);
spin_unlock(&hb->lock);
@@ -1364,20 +1364,18 @@ static int wake_futex_pi(u32 __user *uad
pi_state->owner = new_owner;
raw_spin_unlock(&new_owner->pi_lock);
- raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
-
- deboost = rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q);
-
/*
- * First unlock HB so the waiter does not spin on it once he got woken
- * up. Second wake up the waiter before the priority is adjusted. If we
- * deboost first (and lose our higher priority), then the task might get
- * scheduled away before the wake up can take place.
+ * We've updated the uservalue, this unlock cannot fail.
*/
+ deboost = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q);
+
+ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
spin_unlock(&hb->lock);
- wake_up_q(&wake_q);
- if (deboost)
+
+ if (deboost) {
+ wake_up_q(&wake_q);
rt_mutex_adjust_prio(current);
+ }
return 0;
}
@@ -2253,7 +2251,7 @@ static int fixup_owner(u32 __user *uaddr
* task acquired the rt_mutex after we removed ourself from the
* rt_mutex waiters list.
*/
- if (rt_mutex_trylock(&q->pi_state->pi_mutex)) {
+ if (rt_mutex_futex_trylock(&q->pi_state->pi_mutex)) {
locked = 1;
goto out;
}
@@ -2568,7 +2566,7 @@ static int futex_lock_pi(u32 __user *uad
if (!trylock) {
ret = rt_mutex_timed_futex_lock(&q.pi_state->pi_mutex, to);
} else {
- ret = rt_mutex_trylock(&q.pi_state->pi_mutex);
+ ret = rt_mutex_futex_trylock(&q.pi_state->pi_mutex);
/* Fixup the trylock return value: */
ret = ret ? 0 : -EWOULDBLOCK;
}
@@ -2591,7 +2589,7 @@ static int futex_lock_pi(u32 __user *uad
* it and return the fault to userspace.
*/
if (ret && (rt_mutex_owner(&q.pi_state->pi_mutex) == current))
- rt_mutex_unlock(&q.pi_state->pi_mutex);
+ rt_mutex_futex_unlock(&q.pi_state->pi_mutex);
/* Unqueue and drop the lock */
unqueue_me_pi(&q);
@@ -2898,7 +2896,7 @@ static int futex_wait_requeue_pi(u32 __u
spin_lock(q.lock_ptr);
ret = fixup_pi_state_owner(uaddr2, &q, current);
if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current)
- rt_mutex_unlock(&q.pi_state->pi_mutex);
+ rt_mutex_futex_unlock(&q.pi_state->pi_mutex);
/*
* Drop the reference to the pi state which
* the requeue_pi() code acquired for us.
@@ -2938,7 +2936,7 @@ static int futex_wait_requeue_pi(u32 __u
* userspace.
*/
if (ret && rt_mutex_owner(pi_mutex) == current)
- rt_mutex_unlock(pi_mutex);
+ rt_mutex_futex_unlock(pi_mutex);
/* Unqueue and drop the lock. */
unqueue_me_pi(&q);
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1488,15 +1488,23 @@ EXPORT_SYMBOL_GPL(rt_mutex_lock_interrup
/*
* Futex variant with full deadlock detection.
+ * Futex variants must not use the fast-path, see __rt_mutex_futex_unlock().
*/
-int rt_mutex_timed_futex_lock(struct rt_mutex *lock,
+int __sched rt_mutex_timed_futex_lock(struct rt_mutex *lock,
struct hrtimer_sleeper *timeout)
{
might_sleep();
- return rt_mutex_timed_fastlock(lock, TASK_INTERRUPTIBLE, timeout,
- RT_MUTEX_FULL_CHAINWALK,
- rt_mutex_slowlock);
+ return rt_mutex_slowlock(lock, TASK_INTERRUPTIBLE,
+ timeout, RT_MUTEX_FULL_CHAINWALK);
+}
+
+/*
+ * Futex variant, must not use fastpath.
+ */
+int __sched rt_mutex_futex_trylock(struct rt_mutex *lock)
+{
+ return rt_mutex_slowtrylock(lock);
}
/**
@@ -1555,19 +1563,38 @@ void __sched rt_mutex_unlock(struct rt_m
EXPORT_SYMBOL_GPL(rt_mutex_unlock);
/**
- * rt_mutex_futex_unlock - Futex variant of rt_mutex_unlock
- * @lock: the rt_mutex to be unlocked
- *
- * Returns: true/false indicating whether priority adjustment is
- * required or not.
+ * Futex variant, that since futex variants do not use the fast-path, can be
+ * simple and will not need to retry.
*/
-bool __sched rt_mutex_futex_unlock(struct rt_mutex *lock,
- struct wake_q_head *wqh)
+bool __sched __rt_mutex_futex_unlock(struct rt_mutex *lock,
+ struct wake_q_head *wake_q)
+{
+ lockdep_assert_held(&lock->wait_lock);
+
+ debug_rt_mutex_unlock(lock);
+
+ if (!rt_mutex_has_waiters(lock)) {
+ lock->owner = NULL;
+ return false; /* done */
+ }
+
+ mark_wakeup_next_waiter(wake_q, lock);
+ return true; /* deboost and wakeups */
+}
+
+void __sched rt_mutex_futex_unlock(struct rt_mutex *lock)
{
- if (likely(rt_mutex_cmpxchg_release(lock, current, NULL)))
- return false;
+ DEFINE_WAKE_Q(wake_q);
+ bool deboost;
- return rt_mutex_slowunlock(lock, wqh);
+ raw_spin_lock_irq(&lock->wait_lock);
+ deboost = __rt_mutex_futex_unlock(lock, &wake_q);
+ raw_spin_unlock_irq(&lock->wait_lock);
+
+ if (deboost) {
+ wake_up_q(&wake_q);
+ rt_mutex_adjust_prio(current);
+ }
}
/**
--- a/kernel/locking/rtmutex_common.h
+++ b/kernel/locking/rtmutex_common.h
@@ -109,9 +109,14 @@ extern int rt_mutex_start_proxy_lock(str
extern int rt_mutex_finish_proxy_lock(struct rt_mutex *lock,
struct hrtimer_sleeper *to,
struct rt_mutex_waiter *waiter);
+
extern int rt_mutex_timed_futex_lock(struct rt_mutex *l, struct hrtimer_sleeper *to);
-extern bool rt_mutex_futex_unlock(struct rt_mutex *lock,
- struct wake_q_head *wqh);
+extern int rt_mutex_futex_trylock(struct rt_mutex *l);
+
+extern void rt_mutex_futex_unlock(struct rt_mutex *lock);
+extern bool __rt_mutex_futex_unlock(struct rt_mutex *lock,
+ struct wake_q_head *wqh);
+
extern void rt_mutex_adjust_prio(struct task_struct *task);
#ifdef CONFIG_DEBUG_RT_MUTEXES
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Peter Zijlstra <tipbot@zytor.com> |
|---|---|
| Date | 2017-03-23 19:30 +0100 |
| Subject | [tip:locking/core] futex,rt_mutex: Provide futex specific rt_mutex API |
| Message-ID | <tofEK-666-15@gated-at.bofh.it> |
| In reply to | #1606360 |
Commit-ID: 5293c2efda37775346885c7e924d4ef7018ea60b
Gitweb: http://git.kernel.org/tip/5293c2efda37775346885c7e924d4ef7018ea60b
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Wed, 22 Mar 2017 11:35:51 +0100
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitDate: Thu, 23 Mar 2017 19:10:07 +0100
futex,rt_mutex: Provide futex specific rt_mutex API
Part of what makes futex_unlock_pi() intricate is that
rt_mutex_futex_unlock() -> rt_mutex_slowunlock() can drop
rt_mutex::wait_lock.
This means it cannot rely on the atomicy of wait_lock, which would be
preferred in order to not rely on hb->lock so much.
The reason rt_mutex_slowunlock() needs to drop wait_lock is because it can
race with the rt_mutex fastpath, however futexes have their own fast path.
Since futexes already have a bunch of separate rt_mutex accessors, complete
that set and implement a rt_mutex variant without fastpath for them.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: juri.lelli@arm.com
Cc: bigeasy@linutronix.de
Cc: xlpang@redhat.com
Cc: rostedt@goodmis.org
Cc: mathieu.desnoyers@efficios.com
Cc: jdesfossez@efficios.com
Cc: dvhart@infradead.org
Cc: bristot@redhat.com
Link: http://lkml.kernel.org/r/20170322104151.702962446@infradead.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/futex.c | 30 +++++++++++-----------
kernel/locking/rtmutex.c | 55 ++++++++++++++++++++++++++++++-----------
kernel/locking/rtmutex_common.h | 9 +++++--
3 files changed, 62 insertions(+), 32 deletions(-)
diff --git a/kernel/futex.c b/kernel/futex.c
index cc10340..af02291 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -916,7 +916,7 @@ void exit_pi_state_list(struct task_struct *curr)
pi_state->owner = NULL;
raw_spin_unlock_irq(&curr->pi_lock);
- rt_mutex_unlock(&pi_state->pi_mutex);
+ rt_mutex_futex_unlock(&pi_state->pi_mutex);
spin_unlock(&hb->lock);
@@ -1364,20 +1364,18 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *top_waiter
pi_state->owner = new_owner;
raw_spin_unlock(&new_owner->pi_lock);
- raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
-
- deboost = rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q);
-
/*
- * First unlock HB so the waiter does not spin on it once he got woken
- * up. Second wake up the waiter before the priority is adjusted. If we
- * deboost first (and lose our higher priority), then the task might get
- * scheduled away before the wake up can take place.
+ * We've updated the uservalue, this unlock cannot fail.
*/
+ deboost = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q);
+
+ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
spin_unlock(&hb->lock);
- wake_up_q(&wake_q);
- if (deboost)
+
+ if (deboost) {
+ wake_up_q(&wake_q);
rt_mutex_adjust_prio(current);
+ }
return 0;
}
@@ -2253,7 +2251,7 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
* task acquired the rt_mutex after we removed ourself from the
* rt_mutex waiters list.
*/
- if (rt_mutex_trylock(&q->pi_state->pi_mutex)) {
+ if (rt_mutex_futex_trylock(&q->pi_state->pi_mutex)) {
locked = 1;
goto out;
}
@@ -2568,7 +2566,7 @@ retry_private:
if (!trylock) {
ret = rt_mutex_timed_futex_lock(&q.pi_state->pi_mutex, to);
} else {
- ret = rt_mutex_trylock(&q.pi_state->pi_mutex);
+ ret = rt_mutex_futex_trylock(&q.pi_state->pi_mutex);
/* Fixup the trylock return value: */
ret = ret ? 0 : -EWOULDBLOCK;
}
@@ -2591,7 +2589,7 @@ retry_private:
* it and return the fault to userspace.
*/
if (ret && (rt_mutex_owner(&q.pi_state->pi_mutex) == current))
- rt_mutex_unlock(&q.pi_state->pi_mutex);
+ rt_mutex_futex_unlock(&q.pi_state->pi_mutex);
/* Unqueue and drop the lock */
unqueue_me_pi(&q);
@@ -2898,7 +2896,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
spin_lock(q.lock_ptr);
ret = fixup_pi_state_owner(uaddr2, &q, current);
if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current)
- rt_mutex_unlock(&q.pi_state->pi_mutex);
+ rt_mutex_futex_unlock(&q.pi_state->pi_mutex);
/*
* Drop the reference to the pi state which
* the requeue_pi() code acquired for us.
@@ -2938,7 +2936,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
* userspace.
*/
if (ret && rt_mutex_owner(pi_mutex) == current)
- rt_mutex_unlock(pi_mutex);
+ rt_mutex_futex_unlock(pi_mutex);
/* Unqueue and drop the lock. */
unqueue_me_pi(&q);
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index bab66cb..7d63bc5 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1488,15 +1488,23 @@ EXPORT_SYMBOL_GPL(rt_mutex_lock_interruptible);
/*
* Futex variant with full deadlock detection.
+ * Futex variants must not use the fast-path, see __rt_mutex_futex_unlock().
*/
-int rt_mutex_timed_futex_lock(struct rt_mutex *lock,
+int __sched rt_mutex_timed_futex_lock(struct rt_mutex *lock,
struct hrtimer_sleeper *timeout)
{
might_sleep();
- return rt_mutex_timed_fastlock(lock, TASK_INTERRUPTIBLE, timeout,
- RT_MUTEX_FULL_CHAINWALK,
- rt_mutex_slowlock);
+ return rt_mutex_slowlock(lock, TASK_INTERRUPTIBLE,
+ timeout, RT_MUTEX_FULL_CHAINWALK);
+}
+
+/*
+ * Futex variant, must not use fastpath.
+ */
+int __sched rt_mutex_futex_trylock(struct rt_mutex *lock)
+{
+ return rt_mutex_slowtrylock(lock);
}
/**
@@ -1555,19 +1563,38 @@ void __sched rt_mutex_unlock(struct rt_mutex *lock)
EXPORT_SYMBOL_GPL(rt_mutex_unlock);
/**
- * rt_mutex_futex_unlock - Futex variant of rt_mutex_unlock
- * @lock: the rt_mutex to be unlocked
- *
- * Returns: true/false indicating whether priority adjustment is
- * required or not.
+ * Futex variant, that since futex variants do not use the fast-path, can be
+ * simple and will not need to retry.
*/
-bool __sched rt_mutex_futex_unlock(struct rt_mutex *lock,
- struct wake_q_head *wqh)
+bool __sched __rt_mutex_futex_unlock(struct rt_mutex *lock,
+ struct wake_q_head *wake_q)
{
- if (likely(rt_mutex_cmpxchg_release(lock, current, NULL)))
- return false;
+ lockdep_assert_held(&lock->wait_lock);
+
+ debug_rt_mutex_unlock(lock);
+
+ if (!rt_mutex_has_waiters(lock)) {
+ lock->owner = NULL;
+ return false; /* done */
+ }
+
+ mark_wakeup_next_waiter(wake_q, lock);
+ return true; /* deboost and wakeups */
+}
- return rt_mutex_slowunlock(lock, wqh);
+void __sched rt_mutex_futex_unlock(struct rt_mutex *lock)
+{
+ DEFINE_WAKE_Q(wake_q);
+ bool deboost;
+
+ raw_spin_lock_irq(&lock->wait_lock);
+ deboost = __rt_mutex_futex_unlock(lock, &wake_q);
+ raw_spin_unlock_irq(&lock->wait_lock);
+
+ if (deboost) {
+ wake_up_q(&wake_q);
+ rt_mutex_adjust_prio(current);
+ }
}
/**
diff --git a/kernel/locking/rtmutex_common.h b/kernel/locking/rtmutex_common.h
index 856dfff..af667f6 100644
--- a/kernel/locking/rtmutex_common.h
+++ b/kernel/locking/rtmutex_common.h
@@ -109,9 +109,14 @@ extern int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
extern int rt_mutex_finish_proxy_lock(struct rt_mutex *lock,
struct hrtimer_sleeper *to,
struct rt_mutex_waiter *waiter);
+
extern int rt_mutex_timed_futex_lock(struct rt_mutex *l, struct hrtimer_sleeper *to);
-extern bool rt_mutex_futex_unlock(struct rt_mutex *lock,
- struct wake_q_head *wqh);
+extern int rt_mutex_futex_trylock(struct rt_mutex *l);
+
+extern void rt_mutex_futex_unlock(struct rt_mutex *lock);
+extern bool __rt_mutex_futex_unlock(struct rt_mutex *lock,
+ struct wake_q_head *wqh);
+
extern void rt_mutex_adjust_prio(struct task_struct *task);
#ifdef CONFIG_DEBUG_RT_MUTEXES
[toc] | [prev] | [next] | [standalone]
| From | Darren Hart <dvhart@infradead.org> |
|---|---|
| Date | 2017-03-25 01:40 +0100 |
| Subject | Re: [PATCH -v6 04/13] futex,rt_mutex: Provide futex specific rt_mutex API |
| Message-ID | <toHUl-1bA-3@gated-at.bofh.it> |
| In reply to | #1606360 |
On Wed, Mar 22, 2017 at 11:35:51AM +0100, Peter Zijlstra wrote: > Part of what makes futex_unlock_pi() intricate is that > rt_mutex_futex_unlock() -> rt_mutex_slowunlock() can drop > rt_mutex::wait_lock. > > This means we cannot rely on the atomicy of wait_lock, which we would > like to do in order to not rely on hb->lock so much. > > The reason rt_mutex_slowunlock() needs to drop wait_lock is because it > can race with the rt_mutex fastpath, however futexes have their own > fast path. > > Since futexes already have a bunch of separate rt_mutex accessors, > complete that set and implement a rt_mutex variant without fastpath > for them. > > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Got to here and tried to get some testing going while I was reviewing... to find that some of the existing pi test suites LTP/realtime, are not building either. Got a fix, got it into CI, some CI issues, but no obvious fallout from this. So, review will continue... But, Peter are you testing this with anything in particular? -- Darren Hart VMware Open Source Technology Center
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-03-22 11:50 +0100 |
| Subject | [PATCH -v6 02/13] futex: Use smp_store_release() in mark_wake_futex() |
| Message-ID | <tnM03-11I-41@gated-at.bofh.it> |
| In reply to | #1606349 |
Since the futex_q can dissapear the instruction after assigning NULL, this really should be a RELEASE barrier. That stops loads from hitting dead memory too. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> --- kernel/futex.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1288,8 +1288,7 @@ static void mark_wake_futex(struct wake_ * memory barrier is required here to prevent the following * store to lock_ptr from getting ahead of the plist_del. */ - smp_wmb(); - q->lock_ptr = NULL; + smp_store_release(&q->lock_ptr, NULL); } static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *top_waiter,
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Peter Zijlstra <tipbot@zytor.com> |
|---|---|
| Date | 2017-03-23 19:30 +0100 |
| Subject | [tip:locking/core] futex: Use smp_store_release() in mark_wake_futex() |
| Message-ID | <tofEL-666-37@gated-at.bofh.it> |
| In reply to | #1606361 |
Commit-ID: 1b367ece0d7e696cab1c8501bab282cc6a538b3f Gitweb: http://git.kernel.org/tip/1b367ece0d7e696cab1c8501bab282cc6a538b3f Author: Peter Zijlstra <peterz@infradead.org> AuthorDate: Wed, 22 Mar 2017 11:35:49 +0100 Committer: Thomas Gleixner <tglx@linutronix.de> CommitDate: Thu, 23 Mar 2017 19:10:06 +0100 futex: Use smp_store_release() in mark_wake_futex() Since the futex_q can dissapear the instruction after assigning NULL, this really should be a RELEASE barrier. That stops loads from hitting dead memory too. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: juri.lelli@arm.com Cc: bigeasy@linutronix.de Cc: xlpang@redhat.com Cc: rostedt@goodmis.org Cc: mathieu.desnoyers@efficios.com Cc: jdesfossez@efficios.com Cc: dvhart@infradead.org Cc: bristot@redhat.com Link: http://lkml.kernel.org/r/20170322104151.604296452@infradead.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- kernel/futex.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index 1531cc4..cc10340 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1290,8 +1290,7 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q) * memory barrier is required here to prevent the following * store to lock_ptr from getting ahead of the plist_del. */ - smp_wmb(); - q->lock_ptr = NULL; + smp_store_release(&q->lock_ptr, NULL); } static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *top_waiter,
[toc] | [prev] | [next] | [standalone]
| From | Darren Hart <dvhart@infradead.org> |
|---|---|
| Date | 2017-03-24 22:20 +0100 |
| Subject | Re: [PATCH -v6 02/13] futex: Use smp_store_release() in mark_wake_futex() |
| Message-ID | <toEMN-7q1-9@gated-at.bofh.it> |
| In reply to | #1606361 |
On Wed, Mar 22, 2017 at 11:35:49AM +0100, Peter Zijlstra wrote: > Since the futex_q can dissapear the instruction after assigning NULL, > this really should be a RELEASE barrier. That stops loads from hitting > dead memory too. > > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> I reviewed this carefully in the previous thread, confirming that despite the move to wake queues, spurious wakeups can still lead to the situration Peter describes. As such: Reviewed-by: Darren Hart (VMware) <dvhart@infradead.org> My only suggestion would be to clarify the language in the preceding comment to make that obvious, as well as clarify which plist_del it is referring to since it has been moved under the __unqueue_futex. I can do that as a follow-on though. > --- > kernel/futex.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > --- a/kernel/futex.c > +++ b/kernel/futex.c > @@ -1288,8 +1288,7 @@ static void mark_wake_futex(struct wake_ > * memory barrier is required here to prevent the following > * store to lock_ptr from getting ahead of the plist_del. > */ > - smp_wmb(); > - q->lock_ptr = NULL; > + smp_store_release(&q->lock_ptr, NULL); > } > > static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *top_waiter, > > > -- Darren Hart VMware Open Source Technology Center
[toc] | [prev] | [next] | [standalone]
| From | Darren Hart <dvhart@infradead.org> |
|---|---|
| Date | 2017-03-24 02:50 +0100 |
| Message-ID | <tomwx-2zj-11@gated-at.bofh.it> |
| In reply to | #1606349 |
On Wed, Mar 22, 2017 at 11:35:47AM +0100, Peter Zijlstra wrote:
> Hi all,
>
> Another installment of the futex patches that give you nightmares ;-)
>
> This version sports updated comments and Changelogs as requested last
> time around. It also includes two fixes, both reported by Sebastian
> who was kind enough to stick this in his RT tree for some testing.
>
> The last patch is RT specific, but I figure we can merge it anyway.
>
> Again; I sincerely hope this to be the very last version.
Step 1: Apply to tree, kick off automated Futex tests.
Step 2: Fix Makefile for futex selftests that's been broken since November
(sad face)
Step 3: Pick this up in the morning...
--
Darren Hart
VMware Open Source Technology Center
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | linux.kernel
csiph-web