Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1422738AbaKNVPa (ORCPT ); Fri, 14 Nov 2014 16:15:30 -0500 Received: from mail-wi0-f176.google.com ([209.85.212.176]:62728 "EHLO mail-wi0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1161890AbaKNVPZ (ORCPT ); Fri, 14 Nov 2014 16:15:25 -0500 From: Matt Fleming To: Peter Zijlstra , Ingo Molnar , Jiri Olsa , Arnaldo Carvalho de Melo , Andi Kleen Cc: Thomas Gleixner , linux-kernel@vger.kernel.org, "H. Peter Anvin" , Kanaka Juvva , Matt Fleming , Arnaldo Carvalho de Melo Subject: [PATCH 04/11] perf: Add ->count() function to read per-package counters Date: Fri, 14 Nov 2014 21:15:05 +0000 Message-Id: <1415999712-5850-5-git-send-email-matt@console-pimps.org> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1415999712-5850-1-git-send-email-matt@console-pimps.org> References: <1415999712-5850-1-git-send-email-matt@console-pimps.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Matt Fleming For PMU drivers that record per-package counters, the ->count variable cannot be used to record an accurate aggregated value, since it's not possible to perform SMP cross-calls to cpus on other packages from the context in which we update ->count. Introduce a new optional ->count() accessor function that can be used to customize how values are collected. If a PMU driver doesn't provide a ->count() function, we fallback to the existing code. There is necessarily a window of staleness with this approach because the task that generated the counter value may not have been scheduled by the cpu recently. An alternative and more complex approach would be to use a hrtimer to periodically refresh the values from a more permissive scheduling context. So, we're trading off complexity for accuracy. Cc: Jiri Olsa Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Signed-off-by: Matt Fleming --- include/linux/perf_event.h | 10 ++++++++++ kernel/events/core.c | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 1a4e2846d6fb..1bf06b6fd5dc 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -264,6 +264,11 @@ struct pmu { * flush branch stack on context-switches (needed in cpu-wide mode) */ void (*flush_branch_stack) (void); + + /* + * Return the count value for a counter. + */ + u64 (*count) (struct perf_event *event); /*optional*/ }; /** @@ -743,6 +748,11 @@ static inline void perf_event_task_sched_out(struct task_struct *prev, __perf_event_task_sched_out(prev, next); } +static inline u64 __perf_event_count(struct perf_event *event) +{ + return local64_read(&event->count) + atomic64_read(&event->child_count); +} + extern void perf_event_mmap(struct vm_area_struct *vma); extern struct perf_guest_info_callbacks *perf_guest_cbs; extern int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks); diff --git a/kernel/events/core.c b/kernel/events/core.c index a65f4c47eb56..a2ea4a52dbbf 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3074,7 +3074,10 @@ static void __perf_event_read(void *info) static inline u64 perf_event_count(struct perf_event *event) { - return local64_read(&event->count) + atomic64_read(&event->child_count); + if (event->pmu->count) + return event->pmu->count(event); + + return __perf_event_count(event); } static u64 perf_event_read(struct perf_event *event) -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/