uncore doing kfree() from CPU_{STARTING,DYING}
Subsystems (2)
Peter Zijlstra
maintainerHi Zheng,
Can you have a look at 7fdba1ca and do a similar patch for uncore? Thomas is sad because uncore breaks -rt, the problem (as described in that patch) is that kfree() must schedule on -rt while CPU_{STARTING,DYING} really are atomic.
~ Peter
---
commit 7fdba1ca10462f42ad2246b918fe6368f5ce488e
Author: Peter Zijlstra <[email protected]> Date: Fri Jul 22 13:41:54 2011 +0200
perf, x86: Avoid kfree() in CPU_STARTING
On -rt kfree() can schedule, but CPU_STARTING is before the CPU is fully up and running. These are contradictory, so avoid it. Instead push the kfree() to CPU_ONLINE where we're free to schedule.
Reported-by Thomas Gleixner <[email protected]>
Signed-off-by Peter Zijlstra <[email protected]>
Signed-off-by Ingo Molnar <[email protected]>
arch/x86/kernel/cpu/perf_event.c +8 -0
@@ -129,6 +129,8 @@ struct cpu_hw_events {* AMD specific bits */ struct amd_nb *amd_nb; + +void *kfree_on_online; };#define __EVENT_CONSTRAINT (c, n, m, w) {\
@@ -1466,10 +1468,12 @@ static int __cpuinit x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (long)hcpu; +struct cpu_hw_events *cpuc = &per_cpu (cpu_hw_events, cpu);int ret =NOTIFY_OK ;switch (action & ~CPU_TASKS_FROZEN ) {case CPU_UP_PREPARE : + cpuc->kfree_on_online =NULL ;if (x86_pmu.cpu_prepare) ret = x86_pmu.cpu_prepare (cpu);break ;
@@ -1479,6 +1483,10 @@ x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) x86_pmu.cpu_starting (cpu);break ; +case CPU_ONLINE : +kfree (cpuc->kfree_on_online); +break ; +case CPU_DYING :if (x86_pmu.cpu_dying) x86_pmu.cpu_dying (cpu);
arch/x86/kernel/cpu/perf_event_amd.c +1 -1
@@ -350,7 +350,7 @@ static void amd_pmu_cpu_starting(int cpu)continue ;if (nb->nb_id == nb_id) { -kfree (cpuc->amd_nb); + cpuc->kfree_on_online = cpuc->amd_nb; cpuc->amd_nb = nb;break ; }
arch/x86/kernel/cpu/perf_event_intel.c +1 -1
@@ -1362,7 +1362,7 @@ static void intel_pmu_cpu_starting(int cpu) pc =per_cpu (cpu_hw_events, i).shared_regs;if (pc && pc->core_id == core_id) { -kfree (cpuc->shared_regs); + cpuc->kfree_on_online = cpuc->shared_regs; cpuc->shared_regs = pc;break ; }