blob: 9d837f5a6fd3a2e754af3ba3a4810eb8daca7bf1 [file] [log] [blame]
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