(click on the above link to download; 40K)
(or build it yourself from the source; 128K)
I happened to notice that for some time now my Windows system couldn't keep time worth crap.
It was constantly losing time, anywhere from several seconds per hour or so to many minutes per day (sometimes as much as 15 minutes or more in a single day!)
I couldn't figure out why it was happening and just figured either my RTC circuitry was bad or the battery was low or something.
I even went so far as to install a little freeware clock synchronization program that syncs up your computer clock to one of the many atomic clock time servers out there on the Internet, and wrote a little batch program to log the results.
For several months I simply made note of the fact that my clock was very frequently very out-of-sync with the rest of the world and made adjustments to how often I would have to resync to one of the atomic clocks in order to maintain a reasonably accurate time-of-day clock, until eventually I had to resync every few hours.
Eventually, though, I began to notice a definite pattern.
I noticed that whenever I would get heavily involved in program development, doing frequent compiles and links of whatever program I happen to be developing, the clock would get out of sync more quickly than otherwise. I found this to be especially true (especially noticeable) when I did cross-platform development under Cygwin, using the GNU make and gcc compiler and other tools. I also noticed that during such Cygwin builds, my mouse would be slightly jerky and somewhat on the sluggish side.
This eventually caused me to suspect that the reason my clock was becoming more and more out of sync was because clock interrupts were being lost, gradually causing the Windows clock to get further and further behind (i.e. to lose time).
A few hours of investigation doing various searches on the web and a few searches of Microsoft's own support database confirmed my suspicion.
However, as what may come to no surprise to some, the various suggested work-arounds failed to resolve the problem. My clock was still getting out of sync rather quickly whenever I did some heavy duty program development.
Eventually I decided enough was enough and sat down and wrote ClockMon™, a handy little program that periodically reads the hardware (BIOS or CMOS) Real Time Clock (RTC) and compares it with the Windows operating system clock, resetting the Windows clock whenever it notices the two are out of sync.
ClockMon™ reads the Real Time Clock by doing direct I/O to port 70, which is not normally allowed under the Windows NT/2K/XP security model.
But ClockMon™ is nonetheless able to run on Windows NT, Windows 2000 and Windows XP systems too thanks to a free device driver called giveio.
The tiny little giveio device driver simply gives any program (that properly asks for it) the necessary privileges to do direct port I/O.
Just do a web search for "giveio" and you should find several places where you can download it from. It also comes with its own complete set of source code just like ClockMon™ so you can build it for yourself if you want to.
ClockMon™ comes with a pre-built version of the giveio device driver (as well as the source code too in case you want to build it for yourself) which is automatically installed the first time you run ClockMon™ (if you don't already have it installed on your system of course).
You see, the Windows operating system clock starts out with the same value as the Real Time Clock whenever you reboot your computer, but from then on, it is updated completely independently of the RTC via periodic clock interrupts. Thus, over time (i.e. as the system runs), it is possible for the Windows operating system clock to get out of sync with the actual hardware RTC clock (i.e. the actual "wall clock" time).
This happens because as the system runs, certain software and operating system functions sometimes have to disable all interrupts causing the operating system to sometimes miss a clock interrupt. Most software that disable all interrupts (including the Windows operating system) don't keep interrupts disabled for very long (it's usually only for a VERY short period of time -- usually only a few microseconds (millionths of a second) at most), but because they DO disable all interrupts from time to time, clock ticks ARE unfortunately periodically lost, and over time, add up, causing the Windows operating system clock to sometimes differ considerably from the actual "wall clock" time (sometimes by several minutes or more, depending on system load and the variety and type of software programs running during the time period in question).
When ClockMon™ notices the Windows operating system clock differs from the actual hardware Real Time Clock by more than a predefined amount (but less than 30 minutes), it resets the minutes and seconds portion of the Windows system clock to that of the RTC, thereby eliminating this annoying "Windows Clock Drift" problem and ensuring a more accurate Windows clock value (since the BIOS/CMOS hardware RTC circuitry operates independently from the underlying operating system and should under normal circumstances always be relatively accurate since it doesn't have to worry about missing an interrupt).
Clicking the close box or the minimize box simply hides the main window so that it doesn't clutter your screen or taskbar. To actually exit the program, you must select the "Exit" function from the "File" menu.
Once hidden, you can easily cause the main window to be redisplayed again by simply double-clicking on its icon in the System Tray area. Right-clicking on the tray icon displays a context menu virtually identical to the menus that are available from the main window.
Also, if specified, an optional log file named "ClockMon.log" is created and written to as the program runs which logs the current operating system time, the RTC time, and the difference between the two. You have the option of either logging every time sample the program makes, or only the samples that cause the system clock to actually be reset.
The log file entries look like this:
An "**" following the calculated difference between the two times indicates the system clock was reset for that log entry. If the "**" is not present, then the system clock was not reset for that sample. An "!!" indicates that ClockMon™ discovered an unusual occurrence: that the system clock was found to be ahead of the RTC time rather than behind it as normally expected (i.e. that the Windows system clock appears to be running faster than the Real Time Clock rather than slower as is normally expected). As far as I know, this is only an issue on Windows NT/2K/XP systems and not on Win9x/Me systems.11/06/02 18:54:36 RTC=54:37.000 SYS=54:36.994 DIF=00:00.006 11/06/02 18:54:39 RTC=54:40.000 SYS=54:39.989 DIF=00:00.011 ** 11/06/02 18:54:41 RTC=54:41.000 SYS=54:41.001 !! DIF=00:00.001
All ClockMon™ configuration settings can be entered via the Options dialog or specified via command-line arguments. Whatever values you specify (either via the Options dialog or via command-line arguments) are saved and used the next time ClockMon™ runs:
ClockMon™ Command Line Arguments ----------------------------------- /hide show the main window initially hidden /nohide show the main window initially visible /log record the clock drift to the log file /nolog do NOT record the clock drift to the log file /logall record ALL time samplings to the log file (ignored if /log not specified) /nologall only record samples causing the system clock to be reset (ignored if /log not specified) /sync reset the Windows system clock when it's out-of-sync /nosync do NOT reset the Windows system clock; just monitor it /back do backward syncs too (ignored if /sync not specified) /noback only do forward syncs (ignored if /sync not specified) /nn monitor and/or set clock every this many minutes (where 'nn' is a number from 1 - 1440) /nnnn reset system time whenever it differs from the RTC time by more than this many milliseconds (where 'nn' is a number from 10 - 9999) Note: to specify this value, you must specify the /nn sampling interval first. The first number is always interpretted as the sampling interval and only the second subsequent number is interpretted as the desired accuracy in milliseconds. /sec0 force synchronization on RTC seconds update boundary (see discussion further below for details) /nosec0 do NOT force seconds update boundary synchronization /clear clear the log file to empty before starting /noclear do NOT clear the log file to empty before starting filename use "filename" as the name of the log file (if the name contains blanks, surround it with double quotes)
The "sec0" option forces ClockMon™ to retrieve the RTC time as close as possible to when the Real Time Clock circuitry actually updates its 'seconds' register. Doing so ensures the RTC time value it uses to synchronize the Windows system clock with is as accurate as possible (i.e. is as close to the actual RTC time as possible). Not specifying this option causes ClockMon™ to use whatever time value was returned by the Real Time Clock at the moment it read it, thereby allowing it to be off by up to one second. (The Real Time Clock only returns hours, minutes and seconds (as well as the date of course, but ClockMon™ doesn't use it), but not milliseconds. Thus, if the "actual" time was, for example, 14:41:53.997 whenever ClockMon™ goes to read the RTC, the value that is returned to it (and the value that is uses to synchronize with) is only "14:41:53" (the Real Time Clock circuitry does not "round" the seconds value that it returns to you; it can only report what second it actually is "right now"). If ClockMon™ were to then reset the Windows system clock to that value, the Windows system clock would then be off by 997 milliseconds. Specifying "sec0" however, causes ClockMon™ to wait until the Real Time Clock reports that it is updating its seconds before reading the RTC time value, thus ensuring the RTC time it uses to synchronize the Windows system clock with is as close as possible to the actual "true" time.
With the 'sec0' option specified, ClockMon™ is able to achieve, on average, better than 10 millisecond accuracy!
NOTE: After starting ClockMon™ for the first time, you must manually configure it before it will begin resyncing your Windows clock.
The default settings are to simply monitor the clock but not to reset (resync) it. If you want ClockMon™ to sync your Windows clock, you must specifically tell it to do that. (The reason the default is specifically to not resync your clock is to prevent unintended system modifications. Not everyone may want to use ClockMon™ to resync their clock. Some people may simply want to monitor the inaccuracy of their Windows clock and not resync it, so if you want ClockMon™ to actually resync your Windows clock, you need to specifically enable that option).
Since writing this handy little program and adding it to my Startup folder, my Windows clock is rarely ever out of sync by more than a few milliseconds or so, and I discovered that I don't even need to resync to any of the Internet atomic clock time servers anymore since, apparently, my Real Time Clock (RTC) is quite accurate! (Or at least accurate enough for me; individual results may vary of course.)
So, if you're currently frustrated with having your Windows clock being constantly out of sync, give ClockMon™ a try, and enjoy having an accurate and reliable clock again. :)
"Fish" (David B. Trout)
"Programming today is a race between
software engineers striving to build bigger
and better idiot-proof programs, and the
Universe trying to produce bigger and better
idiots. So far, the Universe is winning."
- Rich Cook