78 lines
2.1 KiB
Diff
78 lines
2.1 KiB
Diff
From 2dc2a9638acd9ee274781190f210bdff6bce1f4a Mon Sep 17 00:00:00 2001
|
|
From: Thomas Gleixner <tglx@linutronix.de>
|
|
Date: Wed, 11 Jul 2012 22:05:19 +0000
|
|
Subject: [PATCH 271/278] slab: Prevent local lock deadlock
|
|
|
|
On RT we avoid the cross cpu function calls and take the per cpu local
|
|
locks instead. Now the code missed that taking the local lock on the
|
|
cpu which runs the code must use the proper local lock functions and
|
|
not a simple spin_lock(). Otherwise it deadlocks later when trying to
|
|
acquire the local lock with the proper function.
|
|
|
|
Reported-and-tested-by: Chris Pringle <chris.pringle@miranda.com>
|
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
|
|
---
|
|
mm/slab.c | 26 ++++++++++++++++++++++----
|
|
1 file changed, 22 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/mm/slab.c b/mm/slab.c
|
|
index 74d2dd7..411c545 100644
|
|
--- a/mm/slab.c
|
|
+++ b/mm/slab.c
|
|
@@ -739,8 +739,26 @@ slab_on_each_cpu(void (*func)(void *arg, int this_cpu), void *arg)
|
|
{
|
|
unsigned int i;
|
|
|
|
+ get_cpu_light();
|
|
for_each_online_cpu(i)
|
|
func(arg, i);
|
|
+ put_cpu_light();
|
|
+}
|
|
+
|
|
+static void lock_slab_on(unsigned int cpu)
|
|
+{
|
|
+ if (cpu == smp_processor_id())
|
|
+ local_lock_irq(slab_lock);
|
|
+ else
|
|
+ local_spin_lock_irq(slab_lock, &per_cpu(slab_lock, cpu).lock);
|
|
+}
|
|
+
|
|
+static void unlock_slab_on(unsigned int cpu)
|
|
+{
|
|
+ if (cpu == smp_processor_id())
|
|
+ local_unlock_irq(slab_lock);
|
|
+ else
|
|
+ local_spin_unlock_irq(slab_lock, &per_cpu(slab_lock, cpu).lock);
|
|
}
|
|
#endif
|
|
|
|
@@ -2627,10 +2645,10 @@ static void do_drain(void *arg, int cpu)
|
|
{
|
|
LIST_HEAD(tmp);
|
|
|
|
- spin_lock_irq(&per_cpu(slab_lock, cpu).lock);
|
|
+ lock_slab_on(cpu);
|
|
__do_drain(arg, cpu);
|
|
list_splice_init(&per_cpu(slab_free_list, cpu), &tmp);
|
|
- spin_unlock_irq(&per_cpu(slab_lock, cpu).lock);
|
|
+ unlock_slab_on(cpu);
|
|
free_delayed(&tmp);
|
|
}
|
|
#endif
|
|
@@ -4098,9 +4116,9 @@ static void do_ccupdate_local(void *info)
|
|
#else
|
|
static void do_ccupdate_local(void *info, int cpu)
|
|
{
|
|
- spin_lock_irq(&per_cpu(slab_lock, cpu).lock);
|
|
+ lock_slab_on(cpu);
|
|
__do_ccupdate_local(info, cpu);
|
|
- spin_unlock_irq(&per_cpu(slab_lock, cpu).lock);
|
|
+ unlock_slab_on(cpu);
|
|
}
|
|
#endif
|
|
|
|
--
|
|
1.7.10
|
|
|