From 8cf7556120a4dc63499fc1cbd2ce461fc2c1a3ba Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Wed, 20 Oct 2010 15:25:01 +0200 Subject: [PATCH] --- yaml --- r: 218637 b: refs/heads/master c: d7842da470f244d258f21c5f72cd8388b3541d04 h: refs/heads/master i: 218635: 8ee63408f8e1592b9d8386197d2d7264794904f8 v: v3 --- [refs] | 2 +- trunk/kernel/perf_event.c | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/[refs] b/[refs] index 8c943d39c08e..1c4b5306d29f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9ffcfa6f1f63eeac15555b745c292eb9f59130f6 +refs/heads/master: d7842da470f244d258f21c5f72cd8388b3541d04 diff --git a/trunk/kernel/perf_event.c b/trunk/kernel/perf_event.c index 39afdb07d758..517d827f4982 100644 --- a/trunk/kernel/perf_event.c +++ b/trunk/kernel/perf_event.c @@ -691,6 +691,8 @@ group_sched_in(struct perf_event *group_event, { struct perf_event *event, *partial_group = NULL; struct pmu *pmu = group_event->pmu; + u64 now = ctx->time; + bool simulate = false; if (group_event->state == PERF_EVENT_STATE_OFF) return 0; @@ -719,11 +721,27 @@ group_sched_in(struct perf_event *group_event, /* * Groups can be scheduled in as one unit only, so undo any * partial group before returning: + * The events up to the failed event are scheduled out normally, + * tstamp_stopped will be updated. + * + * The failed events and the remaining siblings need to have + * their timings updated as if they had gone thru event_sched_in() + * and event_sched_out(). This is required to get consistent timings + * across the group. This also takes care of the case where the group + * could never be scheduled by ensuring tstamp_stopped is set to mark + * the time the event was actually stopped, such that time delta + * calculation in update_event_times() is correct. */ list_for_each_entry(event, &group_event->sibling_list, group_entry) { if (event == partial_group) - break; - event_sched_out(event, cpuctx, ctx); + simulate = true; + + if (simulate) { + event->tstamp_running += now - event->tstamp_stopped; + event->tstamp_stopped = now; + } else { + event_sched_out(event, cpuctx, ctx); + } } event_sched_out(group_event, cpuctx, ctx);