|
@@ -752,24 +752,21 @@ perf_cgroup_mark_enabled(struct perf_event *event,
|
|
|
static enum hrtimer_restart perf_mux_hrtimer_handler(struct hrtimer *hr)
|
|
|
{
|
|
|
struct perf_cpu_context *cpuctx;
|
|
|
- enum hrtimer_restart ret = HRTIMER_NORESTART;
|
|
|
int rotations = 0;
|
|
|
|
|
|
WARN_ON(!irqs_disabled());
|
|
|
|
|
|
cpuctx = container_of(hr, struct perf_cpu_context, hrtimer);
|
|
|
-
|
|
|
rotations = perf_rotate_context(cpuctx);
|
|
|
|
|
|
- /*
|
|
|
- * arm timer if needed
|
|
|
- */
|
|
|
- if (rotations) {
|
|
|
+ raw_spin_lock(&cpuctx->hrtimer_lock);
|
|
|
+ if (rotations)
|
|
|
hrtimer_forward_now(hr, cpuctx->hrtimer_interval);
|
|
|
- ret = HRTIMER_RESTART;
|
|
|
- }
|
|
|
+ else
|
|
|
+ cpuctx->hrtimer_active = 0;
|
|
|
+ raw_spin_unlock(&cpuctx->hrtimer_lock);
|
|
|
|
|
|
- return ret;
|
|
|
+ return rotations ? HRTIMER_RESTART : HRTIMER_NORESTART;
|
|
|
}
|
|
|
|
|
|
static void __perf_mux_hrtimer_init(struct perf_cpu_context *cpuctx, int cpu)
|
|
@@ -792,7 +789,8 @@ static void __perf_mux_hrtimer_init(struct perf_cpu_context *cpuctx, int cpu)
|
|
|
|
|
|
cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * interval);
|
|
|
|
|
|
- hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
|
|
|
+ raw_spin_lock_init(&cpuctx->hrtimer_lock);
|
|
|
+ hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
|
|
|
timer->function = perf_mux_hrtimer_handler;
|
|
|
}
|
|
|
|
|
@@ -800,15 +798,20 @@ static int perf_mux_hrtimer_restart(struct perf_cpu_context *cpuctx)
|
|
|
{
|
|
|
struct hrtimer *timer = &cpuctx->hrtimer;
|
|
|
struct pmu *pmu = cpuctx->ctx.pmu;
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
/* not for SW PMU */
|
|
|
if (pmu->task_ctx_nr == perf_sw_context)
|
|
|
return 0;
|
|
|
|
|
|
- if (hrtimer_is_queued(timer))
|
|
|
- return 0;
|
|
|
+ raw_spin_lock_irqsave(&cpuctx->hrtimer_lock, flags);
|
|
|
+ if (!cpuctx->hrtimer_active) {
|
|
|
+ cpuctx->hrtimer_active = 1;
|
|
|
+ hrtimer_forward_now(timer, cpuctx->hrtimer_interval);
|
|
|
+ hrtimer_start_expires(timer, HRTIMER_MODE_ABS_PINNED);
|
|
|
+ }
|
|
|
+ raw_spin_unlock_irqrestore(&cpuctx->hrtimer_lock, flags);
|
|
|
|
|
|
- hrtimer_start(timer, cpuctx->hrtimer_interval, HRTIMER_MODE_REL_PINNED);
|
|
|
return 0;
|
|
|
}
|
|
|
|