|
@@ -3969,6 +3969,42 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void perf_swevent_start_hrtimer(struct perf_event *event)
|
|
|
|
+{
|
|
|
|
+ struct hw_perf_event *hwc = &event->hw;
|
|
|
|
+
|
|
|
|
+ hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
|
|
|
+ hwc->hrtimer.function = perf_swevent_hrtimer;
|
|
|
|
+ if (hwc->sample_period) {
|
|
|
|
+ u64 period;
|
|
|
|
+
|
|
|
|
+ if (hwc->remaining) {
|
|
|
|
+ if (hwc->remaining < 0)
|
|
|
|
+ period = 10000;
|
|
|
|
+ else
|
|
|
|
+ period = hwc->remaining;
|
|
|
|
+ hwc->remaining = 0;
|
|
|
|
+ } else {
|
|
|
|
+ period = max_t(u64, 10000, hwc->sample_period);
|
|
|
|
+ }
|
|
|
|
+ __hrtimer_start_range_ns(&hwc->hrtimer,
|
|
|
|
+ ns_to_ktime(period), 0,
|
|
|
|
+ HRTIMER_MODE_REL, 0);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void perf_swevent_cancel_hrtimer(struct perf_event *event)
|
|
|
|
+{
|
|
|
|
+ struct hw_perf_event *hwc = &event->hw;
|
|
|
|
+
|
|
|
|
+ if (hwc->sample_period) {
|
|
|
|
+ ktime_t remaining = hrtimer_get_remaining(&hwc->hrtimer);
|
|
|
|
+ hwc->remaining = ktime_to_ns(remaining);
|
|
|
|
+
|
|
|
|
+ hrtimer_cancel(&hwc->hrtimer);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Software event: cpu wall time clock
|
|
* Software event: cpu wall time clock
|
|
*/
|
|
*/
|
|
@@ -3991,22 +4027,14 @@ static int cpu_clock_perf_event_enable(struct perf_event *event)
|
|
int cpu = raw_smp_processor_id();
|
|
int cpu = raw_smp_processor_id();
|
|
|
|
|
|
atomic64_set(&hwc->prev_count, cpu_clock(cpu));
|
|
atomic64_set(&hwc->prev_count, cpu_clock(cpu));
|
|
- hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
|
|
|
- hwc->hrtimer.function = perf_swevent_hrtimer;
|
|
|
|
- if (hwc->sample_period) {
|
|
|
|
- u64 period = max_t(u64, 10000, hwc->sample_period);
|
|
|
|
- __hrtimer_start_range_ns(&hwc->hrtimer,
|
|
|
|
- ns_to_ktime(period), 0,
|
|
|
|
- HRTIMER_MODE_REL, 0);
|
|
|
|
- }
|
|
|
|
|
|
+ perf_swevent_start_hrtimer(event);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
static void cpu_clock_perf_event_disable(struct perf_event *event)
|
|
static void cpu_clock_perf_event_disable(struct perf_event *event)
|
|
{
|
|
{
|
|
- if (event->hw.sample_period)
|
|
|
|
- hrtimer_cancel(&event->hw.hrtimer);
|
|
|
|
|
|
+ perf_swevent_cancel_hrtimer(event);
|
|
cpu_clock_perf_event_update(event);
|
|
cpu_clock_perf_event_update(event);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -4043,22 +4071,15 @@ static int task_clock_perf_event_enable(struct perf_event *event)
|
|
now = event->ctx->time;
|
|
now = event->ctx->time;
|
|
|
|
|
|
atomic64_set(&hwc->prev_count, now);
|
|
atomic64_set(&hwc->prev_count, now);
|
|
- hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
|
|
|
- hwc->hrtimer.function = perf_swevent_hrtimer;
|
|
|
|
- if (hwc->sample_period) {
|
|
|
|
- u64 period = max_t(u64, 10000, hwc->sample_period);
|
|
|
|
- __hrtimer_start_range_ns(&hwc->hrtimer,
|
|
|
|
- ns_to_ktime(period), 0,
|
|
|
|
- HRTIMER_MODE_REL, 0);
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ perf_swevent_start_hrtimer(event);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
static void task_clock_perf_event_disable(struct perf_event *event)
|
|
static void task_clock_perf_event_disable(struct perf_event *event)
|
|
{
|
|
{
|
|
- if (event->hw.sample_period)
|
|
|
|
- hrtimer_cancel(&event->hw.hrtimer);
|
|
|
|
|
|
+ perf_swevent_cancel_hrtimer(event);
|
|
task_clock_perf_event_update(event, event->ctx->time);
|
|
task_clock_perf_event_update(event, event->ctx->time);
|
|
|
|
|
|
}
|
|
}
|