Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 221810
b: refs/heads/master
c: eed0152
h: refs/heads/master
v: v3
  • Loading branch information
Stephane Eranian authored and Ingo Molnar committed Nov 10, 2010
1 parent 0139461 commit c521d4c
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7e55055e5bb00085051ca59c570c83a820e1e0ee
refs/heads/master: eed01528a45dc4138e9a08064b4b6cc1a9426899
10 changes: 10 additions & 0 deletions trunk/include/linux/perf_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,16 @@ struct perf_event {
u64 tstamp_running;
u64 tstamp_stopped;

/*
* timestamp shadows the actual context timing but it can
* be safely used in NMI interrupt context. It reflects the
* context time as it was when the event was last scheduled in.
*
* ctx_time already accounts for ctx->timestamp. Therefore to
* compute ctx_time for a sample, simply add perf_clock().
*/
u64 shadow_ctx_time;

struct perf_event_attr attr;
struct hw_perf_event hw;

Expand Down
42 changes: 34 additions & 8 deletions trunk/kernel/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,8 @@ event_sched_in(struct perf_event *event,

event->tstamp_running += ctx->time - event->tstamp_stopped;

event->shadow_ctx_time = ctx->time - ctx->timestamp;

if (!is_software_event(event))
cpuctx->active_oncpu++;
ctx->nr_active++;
Expand Down Expand Up @@ -3396,19 +3398,20 @@ static u32 perf_event_tid(struct perf_event *event, struct task_struct *p)
}

static void perf_output_read_one(struct perf_output_handle *handle,
struct perf_event *event)
struct perf_event *event,
u64 enabled, u64 running)
{
u64 read_format = event->attr.read_format;
u64 values[4];
int n = 0;

values[n++] = perf_event_count(event);
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
values[n++] = event->total_time_enabled +
values[n++] = enabled +
atomic64_read(&event->child_total_time_enabled);
}
if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
values[n++] = event->total_time_running +
values[n++] = running +
atomic64_read(&event->child_total_time_running);
}
if (read_format & PERF_FORMAT_ID)
Expand All @@ -3421,7 +3424,8 @@ static void perf_output_read_one(struct perf_output_handle *handle,
* XXX PERF_FORMAT_GROUP vs inherited events seems difficult.
*/
static void perf_output_read_group(struct perf_output_handle *handle,
struct perf_event *event)
struct perf_event *event,
u64 enabled, u64 running)
{
struct perf_event *leader = event->group_leader, *sub;
u64 read_format = event->attr.read_format;
Expand All @@ -3431,10 +3435,10 @@ static void perf_output_read_group(struct perf_output_handle *handle,
values[n++] = 1 + leader->nr_siblings;

if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
values[n++] = leader->total_time_enabled;
values[n++] = enabled;

if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
values[n++] = leader->total_time_running;
values[n++] = running;

if (leader != event)
leader->pmu->read(leader);
Expand All @@ -3459,13 +3463,35 @@ static void perf_output_read_group(struct perf_output_handle *handle,
}
}

#define PERF_FORMAT_TOTAL_TIMES (PERF_FORMAT_TOTAL_TIME_ENABLED|\
PERF_FORMAT_TOTAL_TIME_RUNNING)

static void perf_output_read(struct perf_output_handle *handle,
struct perf_event *event)
{
u64 enabled = 0, running = 0, now, ctx_time;
u64 read_format = event->attr.read_format;

/*
* compute total_time_enabled, total_time_running
* based on snapshot values taken when the event
* was last scheduled in.
*
* we cannot simply called update_context_time()
* because of locking issue as we are called in
* NMI context
*/
if (read_format & PERF_FORMAT_TOTAL_TIMES) {
now = perf_clock();
ctx_time = event->shadow_ctx_time + now;
enabled = ctx_time - event->tstamp_enabled;
running = ctx_time - event->tstamp_running;
}

if (event->attr.read_format & PERF_FORMAT_GROUP)
perf_output_read_group(handle, event);
perf_output_read_group(handle, event, enabled, running);
else
perf_output_read_one(handle, event);
perf_output_read_one(handle, event, enabled, running);
}

void perf_output_sample(struct perf_output_handle *handle,
Expand Down

0 comments on commit c521d4c

Please sign in to comment.