From 09d06f7fb7fa54e1ca27569c754a81f085cb5f8c Mon Sep 17 00:00:00 2001 From: Luis Claudio R. Goncalves Date: Fri, 3 Jul 2009 08:44:18 -0500 Subject: [PATCH] x86: GTOD optimize further commit 46a97d3a1630f6ea1e03d322b366734d34e812f0 in tip. This patch offers this resolution for the clocksources that have a vread() function, such as tsc and hpet. Otherwise it keeps uses the read() function offered by the clocksource, that may be costly. [PG: 33rt deletes the extra vread() call from tip original changeset] Signed-off-by: Luis Claudio R. Goncalves Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner Signed-off-by: Paul Gortmaker --- arch/x86/kernel/vsyscall_64.c | 35 ++++++++++++++++++++++++++++++++--- 1 files changed, 32 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index 01ecd14..f82bcde 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c @@ -79,14 +79,41 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, unsigned long flags; write_raw_seqlock_irqsave(&vsyscall_gtod_data.lock, flags); + + if (likely(vsyscall_gtod_data.sysctl_enabled == 2)) { + struct timespec tmp = *(wall_time); + cycle_t (*vread)(void); + cycle_t now; + + vread = vsyscall_gtod_data.clock.vread; + if (likely(vread)) + now = vread(); + else + now = clock->read(clock); + + /* calculate interval: */ + now = (now - clock->cycle_last) & clock->mask; + /* convert to nsecs: */ + tmp.tv_nsec += ( now * clock->mult) >> clock->shift; + + while (tmp.tv_nsec >= NSEC_PER_SEC) { + tmp.tv_sec += 1; + tmp.tv_nsec -= NSEC_PER_SEC; + } + + vsyscall_gtod_data.wall_time_sec = tmp.tv_sec; + vsyscall_gtod_data.wall_time_nsec = tmp.tv_nsec; + } else { + vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec; + vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec; + } + /* copy vsyscall data */ vsyscall_gtod_data.clock.vread = clock->vread; vsyscall_gtod_data.clock.cycle_last = clock->cycle_last; vsyscall_gtod_data.clock.mask = clock->mask; vsyscall_gtod_data.clock.mult = mult; vsyscall_gtod_data.clock.shift = clock->shift; - vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec; - vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec; vsyscall_gtod_data.wall_to_monotonic = wall_to_monotonic; vsyscall_gtod_data.wall_time_coarse = __current_kernel_time(); write_raw_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags); @@ -140,7 +167,8 @@ static __always_inline void do_vgettimeofday(struct timeval * tv) } while (tmp.tv_usec != tv->tv_usec || tmp.tv_sec != tv->tv_sec); - tv->tv_usec /= NSEC_PER_USEC; + tv->tv_usec /= NSEC_PER_MSEC; + tv->tv_usec *= USEC_PER_MSEC; return; } @@ -154,6 +182,7 @@ static __always_inline void do_vgettimeofday(struct timeval * tv) } now = vread(); + base = __vsyscall_gtod_data.clock.cycle_last; mask = __vsyscall_gtod_data.clock.mask; mult = __vsyscall_gtod_data.clock.mult; -- 1.7.0.4