From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org,
linux-rt-users <linux-rt-users@vger.kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>,
Carsten Emde <C.Emde@osadl.org>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
John Kacur <jkacur@redhat.com>,
Paul Gortmaker <paul.gortmaker@windriver.com>,
Julia Cartwright <julia@ni.com>, Daniel Wagner <wagi@monom.org>,
tom.zanussi@linux.intel.com
Subject: [PATCH RT 14/16] futex: Delay deallocation of pi_state
Date: Fri, 19 Jul 2019 17:49:45 -0400 [thread overview]
Message-ID: <20190719214958.251355108@goodmis.org> (raw)
In-Reply-To: 20190719214931.700049248@goodmis.org
4.19.59-rt24-rc1 stable review patch.
If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner <tglx@linutronix.de>
[ Upstream commit d7c7cf8cb68b7df17e6e50be1f25f35d83e686c7 ]
On -RT we can't invoke kfree() in a non-preemptible context.
Defer the deallocation of pi_state to preemptible context.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
kernel/futex.c | 55 ++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 44 insertions(+), 11 deletions(-)
diff --git a/kernel/futex.c b/kernel/futex.c
index b02d9969330b..688b6fcb79cb 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -822,13 +822,13 @@ static void get_pi_state(struct futex_pi_state *pi_state)
* Drops a reference to the pi_state object and frees or caches it
* when the last reference is gone.
*/
-static void put_pi_state(struct futex_pi_state *pi_state)
+static struct futex_pi_state *__put_pi_state(struct futex_pi_state *pi_state)
{
if (!pi_state)
- return;
+ return NULL;
if (!atomic_dec_and_test(&pi_state->refcount))
- return;
+ return NULL;
/*
* If pi_state->owner is NULL, the owner is most probably dying
@@ -848,9 +848,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)
raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
}
- if (current->pi_state_cache) {
- kfree(pi_state);
- } else {
+ if (!current->pi_state_cache) {
/*
* pi_state->list is already empty.
* clear pi_state->owner.
@@ -859,6 +857,30 @@ static void put_pi_state(struct futex_pi_state *pi_state)
pi_state->owner = NULL;
atomic_set(&pi_state->refcount, 1);
current->pi_state_cache = pi_state;
+ pi_state = NULL;
+ }
+ return pi_state;
+}
+
+static void put_pi_state(struct futex_pi_state *pi_state)
+{
+ kfree(__put_pi_state(pi_state));
+}
+
+static void put_pi_state_atomic(struct futex_pi_state *pi_state,
+ struct list_head *to_free)
+{
+ if (__put_pi_state(pi_state))
+ list_add(&pi_state->list, to_free);
+}
+
+static void free_pi_state_list(struct list_head *to_free)
+{
+ struct futex_pi_state *p, *next;
+
+ list_for_each_entry_safe(p, next, to_free, list) {
+ list_del(&p->list);
+ kfree(p);
}
}
@@ -875,6 +897,7 @@ void exit_pi_state_list(struct task_struct *curr)
struct futex_pi_state *pi_state;
struct futex_hash_bucket *hb;
union futex_key key = FUTEX_KEY_INIT;
+ LIST_HEAD(to_free);
if (!futex_cmpxchg_enabled)
return;
@@ -919,7 +942,7 @@ void exit_pi_state_list(struct task_struct *curr)
/* retain curr->pi_lock for the loop invariant */
raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
raw_spin_unlock(&hb->lock);
- put_pi_state(pi_state);
+ put_pi_state_atomic(pi_state, &to_free);
continue;
}
@@ -938,6 +961,8 @@ void exit_pi_state_list(struct task_struct *curr)
raw_spin_lock_irq(&curr->pi_lock);
}
raw_spin_unlock_irq(&curr->pi_lock);
+
+ free_pi_state_list(&to_free);
}
#endif
@@ -1920,6 +1945,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
struct futex_hash_bucket *hb1, *hb2;
struct futex_q *this, *next;
DEFINE_WAKE_Q(wake_q);
+ LIST_HEAD(to_free);
if (nr_wake < 0 || nr_requeue < 0)
return -EINVAL;
@@ -2157,7 +2183,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
* object.
*/
this->pi_state = NULL;
- put_pi_state(pi_state);
+ put_pi_state_atomic(pi_state, &to_free);
/*
* We stop queueing more waiters and let user
* space deal with the mess.
@@ -2174,7 +2200,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
* in futex_proxy_trylock_atomic() or in lookup_pi_state(). We
* need to drop it here again.
*/
- put_pi_state(pi_state);
+ put_pi_state_atomic(pi_state, &to_free);
out_unlock:
double_unlock_hb(hb1, hb2);
@@ -2195,6 +2221,7 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
out_put_key1:
put_futex_key(&key1);
out:
+ free_pi_state_list(&to_free);
return ret ? ret : task_count;
}
@@ -2331,13 +2358,16 @@ static int unqueue_me(struct futex_q *q)
static void unqueue_me_pi(struct futex_q *q)
__releases(q->lock_ptr)
{
+ struct futex_pi_state *ps;
+
__unqueue_futex(q);
BUG_ON(!q->pi_state);
- put_pi_state(q->pi_state);
+ ps = __put_pi_state(q->pi_state);
q->pi_state = NULL;
raw_spin_unlock(q->lock_ptr);
+ kfree(ps);
}
static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
@@ -3286,6 +3316,8 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
* did a lock-steal - fix up the PI-state in that case.
*/
if (q.pi_state && (q.pi_state->owner != current)) {
+ struct futex_pi_state *ps_free;
+
raw_spin_lock(q.lock_ptr);
ret = fixup_pi_state_owner(uaddr2, &q, current);
if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current) {
@@ -3296,8 +3328,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
* Drop the reference to the pi state which
* the requeue_pi() code acquired for us.
*/
- put_pi_state(q.pi_state);
+ ps_free = __put_pi_state(q.pi_state);
raw_spin_unlock(q.lock_ptr);
+ kfree(ps_free);
}
} else {
struct rt_mutex *pi_mutex;
--
2.20.1
next prev parent reply other threads:[~2019-07-19 21:50 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-07-19 21:49 [PATCH RT 00/16] Linux 4.19.59-rt24-rc1 Steven Rostedt
2019-07-19 21:49 ` [PATCH RT 01/16] kthread: add a global worker thread Steven Rostedt
2019-07-22 8:30 ` Juri Lelli
2019-07-23 18:54 ` Steven Rostedt
2019-07-19 21:49 ` [PATCH RT 02/16] genirq: Do not invoke the affinity callback via a workqueue on RT Steven Rostedt
2019-07-19 21:49 ` [PATCH RT 03/16] genirq: Handle missing work_struct in irq_set_affinity_notifier() Steven Rostedt
2019-07-19 21:49 ` [PATCH RT 04/16] arm: imx6: cpuidle: Use raw_spinlock_t Steven Rostedt
2019-07-19 21:49 ` [PATCH RT 05/16] rcu: Dont allow to change rcu_normal_after_boot on RT Steven Rostedt
2019-07-19 21:49 ` [PATCH RT 06/16] pci/switchtec: fix stream_open.cocci warnings Steven Rostedt
2019-07-19 21:49 ` [PATCH RT 07/16] sched/core: Drop a preempt_disable_rt() statement Steven Rostedt
2019-07-19 21:49 ` [PATCH RT 08/16] timers: Redo the notification of canceling timers on -RT Steven Rostedt
2019-07-19 21:49 ` [PATCH RT 09/16] Revert "futex: Ensure lock/unlock symetry versus pi_lock and hash bucket lock" Steven Rostedt
2019-07-19 21:49 ` [PATCH RT 10/16] Revert "futex: Fix bug on when a requeued RT task times out" Steven Rostedt
2019-07-19 21:49 ` [PATCH RT 11/16] Revert "rtmutex: Handle the various new futex race conditions" Steven Rostedt
2019-07-19 21:49 ` [PATCH RT 12/16] Revert "futex: workaround migrate_disable/enable in different context" Steven Rostedt
2019-07-19 21:49 ` [PATCH RT 13/16] futex: Make the futex_hash_bucket lock raw Steven Rostedt
2019-07-19 21:49 ` Steven Rostedt [this message]
2019-07-19 21:49 ` [PATCH RT 15/16] mm/zswap: Do not disable preemption in zswap_frontswap_store() Steven Rostedt
2019-07-19 21:49 ` [PATCH RT 16/16] Linux 4.19.59-rt24-rc1 Steven Rostedt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190719214958.251355108@goodmis.org \
--to=rostedt@goodmis.org \
--cc=C.Emde@osadl.org \
--cc=bigeasy@linutronix.de \
--cc=jkacur@redhat.com \
--cc=julia@ni.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-users@vger.kernel.org \
--cc=paul.gortmaker@windriver.com \
--cc=tglx@linutronix.de \
--cc=tom.zanussi@linux.intel.com \
--cc=wagi@monom.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).