Skip to content

Commit 62b8563

Browse files
Stephane EranianIngo Molnar
authored andcommitted
perf: Add sysfs entry to adjust multiplexing interval per PMU
This patch adds /sys/device/xxx/perf_event_mux_interval_ms to ajust the multiplexing interval per PMU. The unit is milliseconds. Value has to be >= 1. In the 4th version, we renamed the sysfs file to be more consistent with the other /proc/sys/kernel entries for perf_events. In the 5th version, we handle the reprogramming of the hrtimer using hrtimer_forward_now(). That way, we sync up to new timer value quickly (suggested by Jiri Olsa). Signed-off-by: Stephane Eranian <[email protected]> Signed-off-by: Peter Zijlstra <[email protected]> Cc: Frederic Weisbecker <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 9e63020 commit 62b8563

File tree

2 files changed

+60
-4
lines changed

2 files changed

+60
-4
lines changed

include/linux/perf_event.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ struct pmu {
194194
int * __percpu pmu_disable_count;
195195
struct perf_cpu_context * __percpu pmu_cpu_context;
196196
int task_ctx_nr;
197+
int hrtimer_interval_ms;
197198

198199
/*
199200
* Fully disable/enable this PMU, can be used to protect from the PMI

kernel/events/core.c

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -723,13 +723,21 @@ static void __perf_cpu_hrtimer_init(struct perf_cpu_context *cpuctx, int cpu)
723723
{
724724
struct hrtimer *hr = &cpuctx->hrtimer;
725725
struct pmu *pmu = cpuctx->ctx.pmu;
726+
int timer;
726727

727728
/* no multiplexing needed for SW PMU */
728729
if (pmu->task_ctx_nr == perf_sw_context)
729730
return;
730731

731-
cpuctx->hrtimer_interval =
732-
ns_to_ktime(NSEC_PER_MSEC * PERF_CPU_HRTIMER);
732+
/*
733+
* check default is sane, if not set then force to
734+
* default interval (1/tick)
735+
*/
736+
timer = pmu->hrtimer_interval_ms;
737+
if (timer < 1)
738+
timer = pmu->hrtimer_interval_ms = PERF_CPU_HRTIMER;
739+
740+
cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * timer);
733741

734742
hrtimer_init(hr, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
735743
hr->function = perf_cpu_hrtimer_handler;
@@ -6001,9 +6009,56 @@ type_show(struct device *dev, struct device_attribute *attr, char *page)
60016009
return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->type);
60026010
}
60036011

6012+
static ssize_t
6013+
perf_event_mux_interval_ms_show(struct device *dev,
6014+
struct device_attribute *attr,
6015+
char *page)
6016+
{
6017+
struct pmu *pmu = dev_get_drvdata(dev);
6018+
6019+
return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->hrtimer_interval_ms);
6020+
}
6021+
6022+
static ssize_t
6023+
perf_event_mux_interval_ms_store(struct device *dev,
6024+
struct device_attribute *attr,
6025+
const char *buf, size_t count)
6026+
{
6027+
struct pmu *pmu = dev_get_drvdata(dev);
6028+
int timer, cpu, ret;
6029+
6030+
ret = kstrtoint(buf, 0, &timer);
6031+
if (ret)
6032+
return ret;
6033+
6034+
if (timer < 1)
6035+
return -EINVAL;
6036+
6037+
/* same value, noting to do */
6038+
if (timer == pmu->hrtimer_interval_ms)
6039+
return count;
6040+
6041+
pmu->hrtimer_interval_ms = timer;
6042+
6043+
/* update all cpuctx for this PMU */
6044+
for_each_possible_cpu(cpu) {
6045+
struct perf_cpu_context *cpuctx;
6046+
cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
6047+
cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * timer);
6048+
6049+
if (hrtimer_active(&cpuctx->hrtimer))
6050+
hrtimer_forward_now(&cpuctx->hrtimer, cpuctx->hrtimer_interval);
6051+
}
6052+
6053+
return count;
6054+
}
6055+
6056+
#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store)
6057+
60046058
static struct device_attribute pmu_dev_attrs[] = {
6005-
__ATTR_RO(type),
6006-
__ATTR_NULL,
6059+
__ATTR_RO(type),
6060+
__ATTR_RW(perf_event_mux_interval_ms),
6061+
__ATTR_NULL,
60076062
};
60086063

60096064
static int pmu_bus_running;

0 commit comments

Comments
 (0)