Page 1 of 1
100ns resolution clock
Posted: Thu Oct 06, 2016 11:48 am
by poby
I want to implement a clock with 100ns resolution for file timestamping etc and have been thinking of the most optimal way to do it. I'm using lapic/ioapic and hpet in legacy mode. This is what I've come up with:
1. Setup a periodic timer in HPET to trigger at rollover.
2. During HPET initialisation, wait to enable it until the RTC updates. i.e. Poll the RTC status until it updates, then start the HPET with the main counter at zero.
3. Convert the RTC datetime to a 64 bit number being the nanoseconds since year 2000. Store this.
4. When the HPET timer triggers, add the HPET count to the stored count as nanoseconds.
Now when I want the current datetime in ns, I read the stored value, and add the current main counter value (after converting to ns).
Is this a reasonably efficient way to do it? I want to avoid expensive io ports in favor of reading the MMIO of the HPET main counter. Is there a better way?
Re: 100ns resolution clock
Posted: Thu Oct 06, 2016 3:37 pm
by Brendan
Hi,
poby wrote:Now when I want the current datetime in ns, I read the stored value, and add the current main counter value (after converting to ns).
Is this a reasonably efficient way to do it? I want to avoid expensive io ports in favor of reading the MMIO of the HPET main counter. Is there a better way?
I'd use the CPU's time stamp counter to avoid MMIO where possible, with HPET only used to keep TSC in sync and/or if TSC can't be used (e.g. CPU in deep sleep). Note that for access times RAM is slow compared to CPU (and CPU's caches) and MMIO is slow compared to RAM (and IO ports are slow compared to MMIO).
I'd also go for 1 ns precision (which doesn't imply 1 ns accuracy), partly because it's possible to get better than 1 ns precision (and better than 1 ns accuracy) from modern TSC anyway; and partly because I'd use the same "nanoseconds since 2000" for everything (including "nanosleep()", accounting for how much time tasks consumed, etc).
Note: "unsigned 64-bit nanoseconds since 2000" is enough to cover dates/times from 2000 to 2584.
Cheers,
Brendan
Re: 100ns resolution clock
Posted: Fri Oct 07, 2016 3:00 am
by MichaelFarthing
And how do you record actvity within a leap second?
[Only joking!]
Re: 100ns resolution clock
Posted: Fri Oct 07, 2016 7:51 am
by poby
Brendan wrote:Hi,
I'd use the CPU's time stamp counter to avoid MMIO where possible, with HPET only used to keep TSC in sync and/or if TSC can't be used (e.g. CPU in deep sleep). Note that for access times RAM is slow compared to CPU (and CPU's caches) and MMIO is slow compared to RAM (and IO ports are slow compared to MMIO).
I'd also go for 1 ns precision (which doesn't imply 1 ns accuracy), partly because it's possible to get better than 1 ns precision (and better than 1 ns accuracy) from modern TSC anyway; and partly because I'd use the same "nanoseconds since 2000" for everything (including "nanosleep()", accounting for how much time tasks consumed, etc). Note: "unsigned 64-bit nanoseconds since 2000" is enough to cover dates/times from 2000 to 2584.
Thanks a bunch! I was under the impression the TSC could vary but after reading your response I did some checking and quickly discovered modern processors have an invariant TSC. I've followed your suggestion and implemented a 1 ns resolution timestamp using the TSC and it's way better than using the HPET of course. After synchronising at startup, any time I need a ns resolution time, it's only a few instructions needed and no MMIO reads.