diff options
author | Shaohua Li <shli@fb.com> | 2015-02-05 15:55:32 -0800 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-02-18 17:01:45 +0100 |
commit | 6a694a607a97d58c042fb7fbd60ef1caea26950c (patch) | |
tree | 37647025d7f1eff5b16703c442e901e084008b4a /kernel/events | |
parent | 72f669c0086fbbbbebc92ce7390125722c4c0ec5 (diff) | |
download | linux-stable-6a694a607a97d58c042fb7fbd60ef1caea26950c.tar.gz linux-stable-6a694a607a97d58c042fb7fbd60ef1caea26950c.tar.bz2 linux-stable-6a694a607a97d58c042fb7fbd60ef1caea26950c.zip |
perf: Update userspace page info for software event
For hardware events, the userspace page of the event gets updated in
context switches, so if we read the timestamp in the page, we get
fresh info.
For software events, this is missing currently. This patch makes the
behavior consistent.
With this patch, we can implement clock_gettime(THREAD_CPUTIME) with
PERF_COUNT_SW_DUMMY in userspace as suggested by Andy and Peter. Code
like this:
if (pc->cap_user_time) {
do {
seq = pc->lock;
barrier();
running = pc->time_running;
cyc = rdtsc();
time_mult = pc->time_mult;
time_shift = pc->time_shift;
time_offset = pc->time_offset;
barrier();
} while (pc->lock != seq);
quot = (cyc >> time_shift);
rem = cyc & ((1 << time_shift) - 1);
delta = time_offset + quot * time_mult +
((rem * time_mult) >> time_shift);
running += delta;
return running;
}
I tried it on a busy system, the userspace page updating doesn't
have noticeable overhead.
Signed-off-by: Shaohua Li <shli@fb.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/aa2dd2e4f1e9f2225758be5ba00f14d6909a8ce1.1423180257.git.shli@fb.com
[ Improved the changelog. ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/events')
-rw-r--r-- | kernel/events/core.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c index e580e0f41ac6..fef45b4bb5f8 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -6123,6 +6123,7 @@ static int perf_swevent_add(struct perf_event *event, int flags) } hlist_add_head_rcu(&event->hlist_entry, head); + perf_event_update_userpage(event); return 0; } @@ -6592,6 +6593,7 @@ static int cpu_clock_event_add(struct perf_event *event, int flags) { if (flags & PERF_EF_START) cpu_clock_event_start(event, flags); + perf_event_update_userpage(event); return 0; } @@ -6666,6 +6668,7 @@ static int task_clock_event_add(struct perf_event *event, int flags) { if (flags & PERF_EF_START) task_clock_event_start(event, flags); + perf_event_update_userpage(event); return 0; } |