[PATCH 09/10] perf/cputime: Don't stop idle tick if there's live cputime event

From: Jiri Olsa
Date: Wed Jun 06 2018 - 18:16:17 EST


Disable stopping of the idle tick when having live cputime
event. When the tick is disabled, the idle counts are out
of date until next tick/update and perf cputime PMU provides
misleading counts.

Signed-off-by: Jiri Olsa <jolsa@xxxxxxxxxx>
---
include/linux/perf_event.h | 1 +
kernel/events/cputime.c | 13 +++++++++++++
kernel/time/tick-sched.c | 4 ++++
3 files changed, 18 insertions(+)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index aa9eaab370be..ba61d2f9602a 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1407,4 +1407,5 @@ int perf_event_exit_cpu(unsigned int cpu);
#define perf_event_exit_cpu NULL
#endif

+bool has_cputime_event(int cpu);
#endif /* _LINUX_PERF_EVENT_H */
diff --git a/kernel/events/cputime.c b/kernel/events/cputime.c
index efad24543f13..32d3cde0047e 100644
--- a/kernel/events/cputime.c
+++ b/kernel/events/cputime.c
@@ -1,6 +1,7 @@
#include <linux/kernel_stat.h>
#include <linux/sched.h>
#include <linux/perf_event.h>
+#include <linux/tick.h>

enum perf_cputime_id {
PERF_CPUTIME_USER,
@@ -16,6 +17,13 @@ enum perf_cputime_id {
PERF_CPUTIME_MAX,
};

+static DEFINE_PER_CPU(int, has_cputime);
+
+bool has_cputime_event(int cpu)
+{
+ return per_cpu(has_cputime, cpu) != 0;
+}
+
static enum cpu_usage_stat map[PERF_CPUTIME_MAX] = {
[PERF_CPUTIME_USER] = CPUTIME_USER,
[PERF_CPUTIME_NICE] = CPUTIME_NICE,
@@ -143,12 +151,17 @@ static int cputime_event_add(struct perf_event *event, int flags)
if (flags & PERF_EF_START)
cputime_event_start(event, flags);

+ if (event->hw.config == PERF_CPUTIME_IDLE)
+ tick_nohz_idle_restart_tick();
+
+ this_cpu_inc(has_cputime);
return 0;
}

static void cputime_event_del(struct perf_event *event, int flags)
{
cputime_event_stop(event, PERF_EF_UPDATE);
+ this_cpu_dec(has_cputime);
}

static void perf_cputime_read(struct perf_event *event)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index da9455a6b42b..1c105bc2a92e 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -28,6 +28,7 @@
#include <linux/posix-timers.h>
#include <linux/context_tracking.h>
#include <linux/mm.h>
+#include <linux/perf_event.h>

#include <asm/irq_regs.h>

@@ -912,6 +913,9 @@ static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
return false;
}

+ if (has_cputime_event(cpu))
+ return false;
+
return true;
}

--
2.13.6