perf/x86/intel/uncore: Fix minor race in box set up
authorAndi Kleen <ak@linux.intel.com>
Mon, 22 Sep 2014 22:27:06 +0000 (15:27 -0700)
committerIngo Molnar <mingo@kernel.org>
Fri, 3 Oct 2014 04:02:49 +0000 (06:02 +0200)
I was looking for the trinity oops cause in the uncore driver.
(so far didn't found it)

However I found this tiny race: when a box is set up two threads on the
same CPU, they may be setting up the box in parallel (e.g. with kernel
preemption). This could lead to the reference count being increasing
too much. Always recheck there is no existing cpu reference inside the lock.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: eranian@google.com
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Link: http://lkml.kernel.org/r/1411424826-15629-1-git-send-email-andi@firstfloor.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/kernel/cpu/perf_event_intel_uncore.c

index 42d00e53175dd21e46379772553af91e1393004b..9762dbd9f3f7d7a4e11f040aa19b21e31fe62667 100644 (file)
@@ -42,6 +42,9 @@ struct intel_uncore_box *uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu
                return box;
 
        raw_spin_lock(&uncore_box_lock);
+       /* Recheck in lock to handle races. */
+       if (*per_cpu_ptr(pmu->box, cpu))
+               goto out;
        list_for_each_entry(box, &pmu->box_list, list) {
                if (box->phys_id == topology_physical_package_id(cpu)) {
                        atomic_inc(&box->refcnt);
@@ -49,6 +52,7 @@ struct intel_uncore_box *uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu
                        break;
                }
        }
+out:
        raw_spin_unlock(&uncore_box_lock);
 
        return *per_cpu_ptr(pmu->box, cpu);