Messages in this thread | | | Date | Mon, 4 Sep 2017 17:58:23 +0200 | From | Peter Zijlstra <> | Subject | Re: [RFC][PATCH] perf: Rewrite enabled/running timekeeping |
| |
On Mon, Sep 04, 2017 at 05:41:45PM +0200, Peter Zijlstra wrote:
> > >> U - allocation, A - ACTIVE, I - INACTIVE, O - OFF, > > >> E - ERROR, X - EXIT, D - DEAD, > > > > > > Not sure we care about the different <0 values, they're all effectively > > > OFF. > > > > We still need to care about proper initial state of timings when moving above >=0 state. > > Very true. I'm not sure I fully covered that, let me see if there's > something sensible to do for that.
So given this:
static __always_inline enum perf_event_state __perf_effective_state(struct perf_event *event) { struct perf_event *leader = event->group_leader;
if (leader->state <= PERF_EVENT_STATE_OFF) return leader->state;
return event->state; }
static __always_inline void __perf_update_times(struct perf_event *event, u64 now, u64 *enabled, u64 *running) { enum perf_event_state state = __perf_effective_state(event); u64 delta = now - event->tstamp;
*enabled = event->total_time_enabled; if (state >= PERF_EVENT_STATE_INACTIVE) *enabled += delta;
*running = event->total_time_running; if (state >= PERF_EVENT_STATE_ACTIVE) *running += delta; }
static void perf_event_update_time(struct perf_event *event) { u64 now = perf_event_time(event);
__perf_update_times(event, now, &event->total_time_enabled, &event->total_time_running); event->tstamp = now; }
static void perf_event_update_sibling_time(struct perf_event *leader) { struct perf_event *sibling;
list_for_each_entry(sibling, &leader->sibling_list, group_entry) perf_event_update_time(sibling); }
static void perf_event_set_state(struct perf_event *event, enum perf_event_state state) { if (event->state == state) return;
perf_event_update_time(event); /* * If a group leader gets enabled/disabled all its siblings * are affected too. */ if ((event->state < 0) ^ (state < 0)) perf_event_update_sibling_time(event);
WRITE_ONCE(event->state, state); }
If event->state < 0, and we do perf_event_set_state(event, INACTIVE) then perf_event_update_time() will not add to enabled, not add to running, but set ->tstamp = now.
So I think it DTRT.
| |