Page 1 of 1
Delta time sources (x86-64)
Posted: Fri Jul 19, 2024 3:17 pm
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?
Re: Delta time sources (x86-64)
Posted: Fri Jul 19, 2024 5:47 pm
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.
Re: Delta time sources (x86-64)
Posted: Fri Jul 19, 2024 9:56 pm
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.
Re: Delta time sources (x86-64)
Posted: Sat Jul 20, 2024 3:37 pm
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.
Re: Delta time sources (x86-64)
Posted: Sun Jul 21, 2024 9:45 am
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.
Re: Delta time sources (x86-64)
Posted: Sun Jul 21, 2024 7:49 pm
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.
Re: Delta time sources (x86-64)
Posted: Sun Jul 21, 2024 11:50 pm
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.
Re: Delta time sources (x86-64)
Posted: Mon Jul 22, 2024 9:54 am
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.