Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > media > main-src > by-pkgid > d0a35cd31c1125e2132804d68547073d > files > 3810

kernel-2.6.18-194.26.1.el5.src.rpm

From: Ulrich Obergfell <uobergfe@redhat.com>
Date: Wed, 1 Sep 2010 16:26:51 -0400
Subject: [time] initialize tick_nsec based on kernel parameters
Message-id: <690369250.684331283358411819.JavaMail.root@zmail07.collab.prod.int.phx2.redhat.com>
Patchwork-id: 27995
O-Subject: [RHEL5.6 PATCH 2/3 BZ586285] initialize 'tick_nsec' depending on
	'divider' and 'pmtimer_fine_grained' kernel parameters
Bugzilla: 586285
RH-Acked-by: Glauber Costa <glommer@redhat.com>

RH-Bugzilla: 586285
RH-Upstream-status: N/A

This is the third part of a four-part message. Please refer to first part:
http://post-office.corp.redhat.com/archives/rhkernel-list/2010-September/msg00037.html

Patch part 2 of 3
-----------------

Signed-off-by: Jarod Wilson <jarod@redhat.com>

diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index f953710..d9dbe32 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -1385,6 +1385,25 @@ void __init time_init(void)
 {
 	unsigned int hypervisor_khz;
 
+	/*
+	 * 'tick_nsec' is set to TICK_NSEC at compile time. The value of
+	 * TICK_NSEC depends on HZ. The kernel parameter 'tick_divider'
+	 * allows to change REAL_HZ at boottime, so 'tick_nsec' needs to
+	 * be adjusted to REAL_HZ. Otherwise time will drift backwards.
+	 *
+	 * For example, with HZ=1000 the initial value of 'tick_nsec'
+	 * is 999848 and with HZ=100 the initial value of 'tick_nsec'
+	 * is 10000000. Therefore, with 'tick_divider=10' the value of
+	 * 'tick_nsec' needs to be adjusted to 10000000 / 10 = 1000000.
+	 * Otherwise time drifts backwards by 1000000 - 999848 = 152 ns
+	 * per logical tick. This accumulates to 152 * 1000 * 3600 =
+	 * 547200000 ns = 0.5472 seconds per hour.
+	 */
+	if (tick_divider > 1 && pmtimer_fine_grained) {
+		unsigned long acthz = SH_DIV(CLOCK_TICK_RATE, LATCH, 8);
+		tick_nsec = SH_DIV(NSEC_PER_SEC, acthz, 8) / tick_divider;
+	}
+
 	if (nohpet)
 		vxtime.hpet_address = 0;