aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/perf_event.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/perf_event.c')
-rw-r--r--kernel/perf_event.c42
1 files changed, 34 insertions, 8 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 517d827f4982..cb6c0d2af68f 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -674,6 +674,8 @@ event_sched_in(struct perf_event *event,
674 674
675 event->tstamp_running += ctx->time - event->tstamp_stopped; 675 event->tstamp_running += ctx->time - event->tstamp_stopped;
676 676
677 event->shadow_ctx_time = ctx->time - ctx->timestamp;
678
677 if (!is_software_event(event)) 679 if (!is_software_event(event))
678 cpuctx->active_oncpu++; 680 cpuctx->active_oncpu++;
679 ctx->nr_active++; 681 ctx->nr_active++;
@@ -3396,7 +3398,8 @@ static u32 perf_event_tid(struct perf_event *event, struct task_struct *p)
3396} 3398}
3397 3399
3398static void perf_output_read_one(struct perf_output_handle *handle, 3400static void perf_output_read_one(struct perf_output_handle *handle,
3399 struct perf_event *event) 3401 struct perf_event *event,
3402 u64 enabled, u64 running)
3400{ 3403{
3401 u64 read_format = event->attr.read_format; 3404 u64 read_format = event->attr.read_format;
3402 u64 values[4]; 3405 u64 values[4];
@@ -3404,11 +3407,11 @@ static void perf_output_read_one(struct perf_output_handle *handle,
3404 3407
3405 values[n++] = perf_event_count(event); 3408 values[n++] = perf_event_count(event);
3406 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) { 3409 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
3407 values[n++] = event->total_time_enabled + 3410 values[n++] = enabled +
3408 atomic64_read(&event->child_total_time_enabled); 3411 atomic64_read(&event->child_total_time_enabled);
3409 } 3412 }
3410 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) { 3413 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
3411 values[n++] = event->total_time_running + 3414 values[n++] = running +
3412 atomic64_read(&event->child_total_time_running); 3415 atomic64_read(&event->child_total_time_running);
3413 } 3416 }
3414 if (read_format & PERF_FORMAT_ID) 3417 if (read_format & PERF_FORMAT_ID)
@@ -3421,7 +3424,8 @@ static void perf_output_read_one(struct perf_output_handle *handle,
3421 * XXX PERF_FORMAT_GROUP vs inherited events seems difficult. 3424 * XXX PERF_FORMAT_GROUP vs inherited events seems difficult.
3422 */ 3425 */
3423static void perf_output_read_group(struct perf_output_handle *handle, 3426static void perf_output_read_group(struct perf_output_handle *handle,
3424 struct perf_event *event) 3427 struct perf_event *event,
3428 u64 enabled, u64 running)
3425{ 3429{
3426 struct perf_event *leader = event->group_leader, *sub; 3430 struct perf_event *leader = event->group_leader, *sub;
3427 u64 read_format = event->attr.read_format; 3431 u64 read_format = event->attr.read_format;
@@ -3431,10 +3435,10 @@ static void perf_output_read_group(struct perf_output_handle *handle,
3431 values[n++] = 1 + leader->nr_siblings; 3435 values[n++] = 1 + leader->nr_siblings;
3432 3436
3433 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 3437 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
3434 values[n++] = leader->total_time_enabled; 3438 values[n++] = enabled;
3435 3439
3436 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 3440 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
3437 values[n++] = leader->total_time_running; 3441 values[n++] = running;
3438 3442
3439 if (leader != event) 3443 if (leader != event)
3440 leader->pmu->read(leader); 3444 leader->pmu->read(leader);
@@ -3459,13 +3463,35 @@ static void perf_output_read_group(struct perf_output_handle *handle,
3459 } 3463 }
3460} 3464}
3461 3465
3466#define PERF_FORMAT_TOTAL_TIMES (PERF_FORMAT_TOTAL_TIME_ENABLED|\
3467 PERF_FORMAT_TOTAL_TIME_RUNNING)
3468
3462static void perf_output_read(struct perf_output_handle *handle, 3469static void perf_output_read(struct perf_output_handle *handle,
3463 struct perf_event *event) 3470 struct perf_event *event)
3464{ 3471{
3472 u64 enabled = 0, running = 0, now, ctx_time;
3473 u64 read_format = event->attr.read_format;
3474
3475 /*
3476 * compute total_time_enabled, total_time_running
3477 * based on snapshot values taken when the event
3478 * was last scheduled in.
3479 *
3480 * we cannot simply called update_context_time()
3481 * because of locking issue as we are called in
3482 * NMI context
3483 */
3484 if (read_format & PERF_FORMAT_TOTAL_TIMES) {
3485 now = perf_clock();
3486 ctx_time = event->shadow_ctx_time + now;
3487 enabled = ctx_time - event->tstamp_enabled;
3488 running = ctx_time - event->tstamp_running;
3489 }
3490
3465 if (event->attr.read_format & PERF_FORMAT_GROUP) 3491 if (event->attr.read_format & PERF_FORMAT_GROUP)
3466 perf_output_read_group(handle, event); 3492 perf_output_read_group(handle, event, enabled, running);
3467 else 3493 else
3468 perf_output_read_one(handle, event); 3494 perf_output_read_one(handle, event, enabled, running);
3469} 3495}
3470 3496
3471void perf_output_sample(struct perf_output_handle *handle, 3497void perf_output_sample(struct perf_output_handle *handle,