| From 8a26b15b3b4b77376634639b5c8127899732a9d5 Mon Sep 17 00:00:00 2001 |
| From: Luis Claudio R. Goncalves <lgoncalv@redhat.com> |
| 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 <lgoncalv@redhat.com> |
| Signed-off-by: Ingo Molnar <mingo@elte.hu> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c |
| index 00f768f..1bd8ff3 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.1.1 |
| |