Delta time sources (x86-64)

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
AndrewAPrice
Member
Member
Posts: 2300
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Delta time sources (x86-64)

Post by AndrewAPrice »

My operating system targets x86-64 and is a microkernel.

I'm looking for timer source that I can read relatively quickly from user-space in an event loop. For example, measure the delta time since the last frame update so I can update the UI animations.

I read through https://wiki.osdev.org/Time_And_Date and also about PIT and HPET. I'm leaning towards HPET since I believe I can read it from user-code vs. having to query an IO port (which means I'll have to RPC to a driver to do it).

What do you all use?
My OS is Perception.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Delta time sources (x86-64)

Post by Octocontrabass »

AndrewAPrice wrote: Fri Jul 19, 2024 3:17 pmI'm looking for timer source that I can read relatively quickly from user-space in an event loop. For example, measure the delta time since the last frame update so I can update the UI animations.
Why poll the timer when the timer could send interrupts to you?

If you really need a timer that's easy to poll and doesn't have RPC overhead, you could use the TSC. On some older CPUs, it's not very accurate as a time source, so you might also need a fallback.
AndrewAPrice wrote: Fri Jul 19, 2024 3:17 pmI'm leaning towards HPET
Some (old?) x86-64 PCs don't support HPET.
AndrewAPrice wrote: Fri Jul 19, 2024 3:17 pmsince I believe I can read it from user-code vs. having to query an IO port (which means I'll have to RPC to a driver to do it).
You can set up the IOPB to access IO ports from ring 3, if you really need that.
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: Delta time sources (x86-64)

Post by nullplan »

AndrewAPrice wrote: Fri Jul 19, 2024 3:17 pm I'm looking for timer source that I can read relatively quickly from user-space in an event loop. For example, measure the delta time since the last frame update so I can update the UI animations.
An overview of time sources is available here: https://wiki.osdev.org/Timer_Interrupt_Sources

You should probably use the TSC if possible. However, sometimes it is not possible. You will have to read the multi-processor configuration, but the TSC is initialized from the same value only across the CPU package. IIRC, if your system has more than one CPU package, you can't use the TSC since they will be out of sync. There is also a flag in CPUID somewhere telling you if the TSC will keep its frequency at low-power modes. Obviously, it isn't useful as a timepiece if it ticks at different rates over time.

HPET is next in line, but of course not always available. Reading it is done with one MMIO read. How you wish to expose that to userspace is your business, but I won't give all userspace processes access to all of address space, so a driver is still required to at least get at the address with the counter. If it exists, HPET can give a highly accurate and stable counter from which to derive the system clock.

The ACPI PM timer is basically unusable for having only a 24- or 32-bit register and no interrupt on terminal count so you cannot extend it.

PIT should be the fallback. It does not provide a counter, but you can set it up to interrupt you regularly, and the timer interrupt can increase a value in software. That value can be as large as you like. Of course, this is the worst possible solution for energy consumption. You get to choose between precision and battery life. But if life gives you lemons...
Octocontrabass wrote: Fri Jul 19, 2024 5:47 pm Why poll the timer when the timer could send interrupts to you?
I think he was interrupted and now wants to know how much time passed between last and current iteration.
Carpe diem!
User avatar
AndrewAPrice
Member
Member
Posts: 2300
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: Delta time sources (x86-64)

Post by AndrewAPrice »

nullplan wrote: Fri Jul 19, 2024 9:56 pm An overview of time sources is available here: https://wiki.osdev.org/Timer_Interrupt_Sources

You should probably use the TSC if possible. However, sometimes it is not possible. You will have to read the multi-processor configuration, but the TSC is initialized from the same value only across the CPU package. IIRC, if your system has more than one CPU package, you can't use the TSC since they will be out of sync. There is also a flag in CPUID somewhere telling you if the TSC will keep its frequency at low-power modes. Obviously, it isn't useful as a timepiece if it ticks at different rates over time.
The TSC seems like my best bet, specifically, rdtscp, which returns the IA32_TSC_AUX to identify the processor.

Then, I just need an API that can query some driver (or the kernel) for processor => {ticks per second, 0 epoch offset}, then I'd have everything I need to convert the TSC to seconds.

The next question is how I can accurately get the number of ticks per second.
My OS is Perception.
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: Delta time sources (x86-64)

Post by nullplan »

AndrewAPrice wrote: Then, I just need an API that can query some driver (or the kernel) for processor => {ticks per second, 0 epoch offset}, then I'd have everything I need to convert the TSC to seconds.
Linux does this by writing the required values into a data page that is shared with all processes (the VVAR page) and not writable for user programs. It also solves the problem of hardware abstraction by hiding all of this in the VDSO implementation of clock_gettime(), so users don't need to know anything about the TSC, the HPET, or anything, really.
AndrewAPrice wrote: Sat Jul 20, 2024 3:37 pm The next question is how I can accurately get the number of ticks per second.
The common solution for this is to use a timer you do know the frequency of. Specifically, the PIT. Program the PIT to interrupt you in 100ms and calculate the TSC difference in that time.
Carpe diem!
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Delta time sources (x86-64)

Post by Octocontrabass »

nullplan wrote: Fri Jul 19, 2024 9:56 pmI think he was interrupted and now wants to know how much time passed between last and current iteration.
Wouldn't the interrupt itself provide that information?
AndrewAPrice wrote: Sat Jul 20, 2024 3:37 pmThe next question is how I can accurately get the number of ticks per second.
Newer Intel CPUs report the TSC frequency via CPUID. Otherwise, you need to measure the TSC frequency using a timer with a known frequency (PIT, HPET, ACPI power management timer). SMM can add unexpected delays, so you need to measure more than once to make sure your measurement is accurate. The TSC frequency isn't constant on some CPUs, so you should check CPUID before you try to measure.
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: Delta time sources (x86-64)

Post by nullplan »

Octocontrabass wrote: Sun Jul 21, 2024 7:49 pm Wouldn't the interrupt itself provide that information?
How would it do that? Last time the program ran because of the mouse driver, this time it's because of a keyboard event, and next time it might be because of network activity. It doesn't have to be because of some timer.
Carpe diem!
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Delta time sources (x86-64)

Post by Octocontrabass »

nullplan wrote: Sun Jul 21, 2024 11:50 pmIt doesn't have to be because of some timer.
But it does have to receive periodic timer interrupts, since none of those other interrupts are guaranteed to arrive often enough to properly animate the UI.
Post Reply