summaryrefslogtreecommitdiffstats
path: root/x86-GTOD-offer-scalable-vgettimeofday.patch
blob: 62a4dc37c1b90941df81f3486fc70f3c853fdee3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
From d0f69516bc88d01e62871d8186afb79f4c900476 Mon Sep 17 00:00:00 2001
From: Ingo Molnar <mingo@elte.hu>
Date: Fri, 3 Jul 2009 08:44:00 -0500
Subject: [PATCH] x86: GTOD: offer scalable vgettimeofday

commit 4b10b24a38155ecba8d585788b846119ae689a1b in tip.

offer scalable vgettimeofday independently of whether the TSC
is synchronous or not. Off by default.

this patch also fixes an SMP bug in sys_vtime(): we should read
__vsyscall_gtod_data.wall_time_tv.tv_sec only once.

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>
---
 arch/x86/kernel/vsyscall_64.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index fd70b0e..01ecd14 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -125,6 +125,25 @@ static __always_inline void do_vgettimeofday(struct timeval * tv)
 	unsigned seq;
 	unsigned long mult, shift, nsec;
 	cycle_t (*vread)(void);
+
+	if (likely(__vsyscall_gtod_data.sysctl_enabled == 2)) {
+		struct timeval tmp;
+
+		do {
+			barrier();
+			tv->tv_sec = __vsyscall_gtod_data.wall_time_sec;
+			tv->tv_usec = __vsyscall_gtod_data.wall_time_nsec;
+			barrier();
+			tmp.tv_sec = __vsyscall_gtod_data.wall_time_sec;
+			tmp.tv_usec = __vsyscall_gtod_data.wall_time_nsec;
+
+		} while (tmp.tv_usec != tv->tv_usec ||
+					tmp.tv_sec != tv->tv_sec);
+
+		tv->tv_usec /= NSEC_PER_USEC;
+		return;
+	}
+
 	do {
 		seq = read_raw_seqbegin(&__vsyscall_gtod_data.lock);
 
-- 
1.7.0.4