RTC No Sync

Introduction
One routine that potentially takes a long time during kernel startup is get_cmos_time. This routine is used to read the value of the external real-time clock (RTC) when the kernel boots. Currently, this routine delays until the edge of the next second rollover, in order to ensure that the time value in the kernel is accurate with respect to the RTC.

However, this operation can take up to one full second to complete, and thus introduces up to 1 second of variability in the total bootup time.

The synchronization in this routine is easy to remove. It can be eliminated by removing the first two loops in the function get_cmos_time, which is located in include/asm-i386/mach-default/mach_time.h for the i386 architecture. Similar routines are present in the kernel source tree for other architectures.

One tradeoff in making this modification is that the time stored by the Linux kernel is no longer completely synchronized (to the boundary of a second) with the time in the machine's realtime clock hardware. Some systems save the system time back out to the hardware clock on system shutdown. After numerous bootups and shutdowns, this lack of synchronization will cause the realtime clock value to drift from the correct time value.

Since the amount of un-synchronization is up to a second per boot cycle, this drift can be significant. However, for some embedded applications, this drift is unimportant. Also, in some situations the system time may be synchronized with an external source anyway, so the drift, if any, is corrected under normal circumstances soon after booting.

LKML discussion
The RTC synchronization was discussed on LKML in May (with even Linus himself commenting) That thread is available here.

Rationale
The RTC edge synchronization can take up to 1 second, and takes .5 seconds on average.

Patch

 * [Patch for CELF version XXXXXX is *here*]
 * [Patch for 2.4.xx is *here*]
 * Patch for 2.6.7 (only for i386 architecture): rtc-nosynch-3.patch
 * Patch for 2.6.10 for PPC architecture: attachment:rtcnosync-ppc-2.6.10.patch

You might also want to check the Patch Archive

Utility programs
None

How To Use
Apply the patch to your Linux kernel. Then reconfigure your kernel so that "CONFIG_RTC_NO_SYNC_ON_READ" is enabled.

The option will be found under "General Setup", "Fast boot options" labeled as "No SYNC on read of Real Time Clock".

case 1
Tim Bird measured the effect of eliminating this synchronization on an HP xw4100 workstation. The machine had a Pentium 4 processor running at 3 GHz. With the synchronization, the time to perform get_cmos_time varied from 150 milliseconds to 900 milliseconds. Without the synchronization, the time to perform get_cmos_time was under 1 millisecond.

case 2
Richard Griffiths measured the effect of eliminating the synchronization on a 1GHZ Pentium III based desktop. With synchronization executing get_cmos_time took from 200 milliseconds to a full second. Without the synchronization, the time to perform get_cmos_time was under 1 millisecond.

case 3
Tim Bird measured the RTC read synchronization cost for a PowerPC board. The platform was a PPC440GP (ebony) board, using a Dallas Semiconductor DS1743 RTC.

The RTC read routine is in arch/ppc/syslib/todc_time.c:todc_get_rtc_time. The loop to synchronize with the seconds edge is in arch/ppc/kernel/time.h:time_init.

I measured the time for synchronizing the clock edge several times:
 * 105 ms, 139 ms, 313 ms, 572 ms, 213 ms, 626 ms, 753 ms, 426 ms, 535 ms, 163 ms

Note that for PPC, the synchronization code is outside the RTC read routine, instead of inside the routine (as for i386).

Status
Fixed in mainline.

Matt Mackall submitted a large patch set to fix this problem, in March 2006. See http://lkml.org/lkml/2006/3/17/340. These patches were mainlined in the Linux kernel in version 2.6.16. See http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=63732c2f37093d63102d53e70866cf87bf0c0479

Previous mainline attempts
A patch was eventually submitted to LKML for consideration (in Nov, 2004). The thread is here

There was no response.

Future Work
Here is a list of things that could be worked on for this feature: "'There is hwclock that will read or write the CMOS clock, and it synchronizes. So if one wants to synchronize with the CMOS clock (rather than, say, with an external clock), and wants the better-than-1-sec accuracy,   then that can be done in a boot script.'"
 * In an earlier thread on LKML, it was suggested that some background method of synchronizing the system clock and hardware clock could be used to avoid the clock drift problem.
 * one idea is: "you could check the cmos time in the timer interrupt during boot, and correct it there rather than busy-waiting"
 * Another person notes:


 * We need to check if hwclock uses get_cmos_time to read the clock. If so, this method of synchronizing the clock edge after booting won't work (once the get_cmos_time synch is disabled.)