Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 288620
b: refs/heads/master
c: e3f3541
h: refs/heads/master
v: v3
  • Loading branch information
Peter Zijlstra authored and Ingo Molnar committed Dec 21, 2011
1 parent fa16a9f commit 4339228
Show file tree
Hide file tree
Showing 4 changed files with 32 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: 0c9d42ed4cee2aa1dfc3a260b741baae8615744f
refs/heads/master: e3f3541c19c89a4daae39300defba68943301949
14 changes: 14 additions & 0 deletions trunk/arch/x86/kernel/cpu/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <asm/compat.h>
#include <asm/smp.h>
#include <asm/alternative.h>
#include <asm/timer.h>

#include "perf_event.h"

Expand Down Expand Up @@ -1627,6 +1628,19 @@ static struct pmu pmu = {
.event_idx = x86_pmu_event_idx,
};

void perf_update_user_clock(struct perf_event_mmap_page *userpg, u64 now)
{
if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
return;

if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
return;

userpg->time_mult = this_cpu_read(cyc2ns);
userpg->time_shift = CYC2NS_SCALE_FACTOR;
userpg->time_offset = this_cpu_read(cyc2ns_offset) - now;
}

/*
* callchain support
*/
Expand Down
4 changes: 3 additions & 1 deletion trunk/include/linux/perf_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,14 @@ struct perf_event_mmap_page {
__s64 offset; /* add to hardware event value */
__u64 time_enabled; /* time event active */
__u64 time_running; /* time event on cpu */
__u32 time_mult, time_shift;
__u64 time_offset;

/*
* Hole for extension of the self monitor capabilities
*/

__u64 __reserved[123]; /* align to 1k */
__u64 __reserved[121]; /* align to 1k */

/*
* Control data for the mmap() data buffer.
Expand Down
21 changes: 14 additions & 7 deletions trunk/kernel/events/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -3220,17 +3220,22 @@ static int perf_event_index(struct perf_event *event)
}

static void calc_timer_values(struct perf_event *event,
u64 *now,
u64 *enabled,
u64 *running)
{
u64 now, ctx_time;
u64 ctx_time;

now = perf_clock();
ctx_time = event->shadow_ctx_time + now;
*now = perf_clock();
ctx_time = event->shadow_ctx_time + *now;
*enabled = ctx_time - event->tstamp_enabled;
*running = ctx_time - event->tstamp_running;
}

void __weak perf_update_user_clock(struct perf_event_mmap_page *userpg, u64 now)
{
}

/*
* Callers need to ensure there can be no nesting of this function, otherwise
* the seqlock logic goes bad. We can not serialize this because the arch
Expand All @@ -3240,7 +3245,7 @@ void perf_event_update_userpage(struct perf_event *event)
{
struct perf_event_mmap_page *userpg;
struct ring_buffer *rb;
u64 enabled, running;
u64 enabled, running, now;

rcu_read_lock();
/*
Expand All @@ -3252,7 +3257,7 @@ void perf_event_update_userpage(struct perf_event *event)
* because of locking issue as we can be called in
* NMI context
*/
calc_timer_values(event, &enabled, &running);
calc_timer_values(event, &now, &enabled, &running);
rb = rcu_dereference(event->rb);
if (!rb)
goto unlock;
Expand All @@ -3277,6 +3282,8 @@ void perf_event_update_userpage(struct perf_event *event)
userpg->time_running = running +
atomic64_read(&event->child_total_time_running);

perf_update_user_clock(userpg, now);

barrier();
++userpg->lock;
preempt_enable();
Expand Down Expand Up @@ -3763,7 +3770,7 @@ static void perf_output_read_group(struct perf_output_handle *handle,
static void perf_output_read(struct perf_output_handle *handle,
struct perf_event *event)
{
u64 enabled = 0, running = 0;
u64 enabled = 0, running = 0, now;
u64 read_format = event->attr.read_format;

/*
Expand All @@ -3776,7 +3783,7 @@ static void perf_output_read(struct perf_output_handle *handle,
* NMI context
*/
if (read_format & PERF_FORMAT_TOTAL_TIMES)
calc_timer_values(event, &enabled, &running);
calc_timer_values(event, &now, &enabled, &running);

if (event->attr.read_format & PERF_FORMAT_GROUP)
perf_output_read_group(handle, event, enabled, running);
Expand Down

0 comments on commit 4339228

Please sign in to comment.