[ntp:questions] ntpd wedged again

Chuck Swiger cswiger at mac.com
Sat Feb 11 22:16:55 UTC 2012

On Feb 11, 2012, at 11:58 AM, Dave Hart wrote:
> On Sat, Feb 11, 2012 at 17:17, Chuck Swiger <cswiger at mac.com> wrote:
>>> Have you tried to time the minimum clock reading time with RDTSC
>>> or GetPerformance* counter calls?
>>> I wrote a tiny test program on my Win7-64 laptop, it got:
>>> Reading the system clock 10000000 times, minimum reading time =
>>> 24 clock cycles,
>>> minimum OS step = 0 ticks, maximum OS step = 10000 ticks
>>> The clock frequency is 2.7 GHz or so, the FileTime ticks should be
>>> 100 ns each, so my OS clock is making 1 ms steps, while the clock
>>> reading time is down to less than 10 ns!
>> Well, the code above is not reading a clock; you're reading the
>> stored value of what time it was when the kernel's scheduler last
>> updated that value.  When the OS scheduler ticks, it reads a clock,
>> then trims down the precision to the scheduler quantum (ie, 1ms
>> for HZ=1000), and stores in a "commpage", which is mapped RO
>> into userland processes.
> Terje's code is reading the only clock available on Windows.

Terje's GetSystemTimeAsFTime() was exactly what I described above: a userland function which looks up a pre-stored value which gets updated periodically by the kernel, but is not actually calling a real clock which will return the time as seen when the clock is read *right* *then*.

> It may not be what you think of as reading a clock based on your
> understanding of other operating systems, but Windows isn't
> necessarily the same as other operating systems.

A clock isn't a stored value on a memory page, even if that value gets periodically updated within the system scheduler on per HZ interrupt, via the Windows multimedia timer, or whatever.

A clock is an oscillator and a counter.  (Go read VMWare's "Timekeeping-In-VirtualMachines.pdf" or PHK's "timecounter.pdf" for considerably more detailed description and examples if this is unclear.)

> 15 years ago, most POSIX-style OSes used a simple tick-based system clock like Windows
> that was very fast to read, though typically not as fast as Windows'
> because the current time wasn't mapped into unprivileged memory of
> each process, so the time to read the clock was dominated by the
> system call overhead of transitioning to and from kernel mode/code,
> probably a couple of orders of magnitude more expensive than actually
> reading the stored current clock value in the kernel.

[ ...followed by a long disagreement based on your assessment of 
     my experience with "POSIX-style OSes"... ]

The use of a "commpage" (that's a Mac term, the Linux equivalent appears to be "vsyscall page") to store a low-resolution approximation to "now" was used in pre-OSX MacOS and in Linux, but it isn't being used under FreeBSD.  And "Windows Services for Unix" claims to be POSIX-compliant or at least "POSIXy" for NT/Win2k/XP/etc, so the distinction you're drawing just doesn't appear to make sense.

Look, I admire the notion of quibbling over details, but not when it is used to obscure the central point rather than help resolve it.

>> Also please note that you can't just call rdtsc by itself and get
>> good results.  At the very least, you want to put a serializing
>> instruction like cpuid first, and secondly, you really want to call
>> rdtsc three times, and verify that t1 <= t2 <= t3, otherwise you
>> have a chance of getting bogus time results due to your thread
>> switching to another processor core between calls, CPU power-
>> state changes, chipset bugs, interference from SMC interrupts,
>> and PHK knows what else.  :-)
> Not on modern AMDs, or any Intel, as far as my admittedly sub-PHK
> understanding goes.  AMD really screwed the pooch by allowing the TSC
> to vary between processors and vary with power state, causing all
> sorts of headaches for all sorts of software.  Even on buggy systems,
> reading TSC once is enough if you've locked the thread to a single
> logical processor.

See http://en.wikipedia.org/wiki/Time_Stamp_Counter and references.

>> To resurrect timings of various clock-sources taken from 2005:
>>                 TSC             ACPI-fast       HPET            i8254
>> dual Xeon:      580 nsec        1429 nsec       1120 nsec       3980 nsec
>> dual Opteron:   212 nsec        1270 nsec       1760 nsec       4420 nsec
> This table is great for those using Linux or FreeBSD or other systems
> where one can choose the system clock source.  That is irrelevant to
> Windows, where the clock source is whatever the HAL decides it is,
> period.  Changing HALs is typically not an option.

I included the table because Terje asked "Have you tried to time the minimum clock reading time with RDTSC or GetPerformance* counter calls?" and is probably more useful than figuring out how to adjust what Windows HAL choses.

That being said, you can generally choose to enable or disable HPET either in the BIOS or by disabling that portion of the chipset driver.  I can recall older boxes where you could even disable ACPI, although I'm not convinced that doing so would be helpful with a modern OS.


More information about the questions mailing list