@@ -151,11 +151,15 @@ const MeterClass* const Platform_meterTypes[] = {
151151 NULL
152152};
153153
154+ static uint64_t Platform_nanosecondsPerMachTickNumer = 1 ;
155+ static uint64_t Platform_nanosecondsPerMachTickDenom = 1 ;
156+
154157static double Platform_nanosecondsPerSchedulerTick = -1 ;
155158
156159static mach_port_t iokit_port ; // the mach port used to initiate communication with IOKit
157160
158161bool Platform_init (void ) {
162+ Platform_calculateNanosecondsPerMachTick (& Platform_nanosecondsPerMachTickNumer , & Platform_nanosecondsPerMachTickDenom );
159163
160164 // Determine the number of scheduler clock ticks per second
161165 errno = 0 ;
@@ -171,6 +175,21 @@ bool Platform_init(void) {
171175 return true;
172176}
173177
178+ // Converts ticks in the Mach "timebase" to nanoseconds.
179+ // See `mach_timebase_info`, as used to define the `Platform_nanosecondsPerMachTick` constant.
180+ uint64_t Platform_machTicksToNanoseconds (uint64_t mach_ticks ) {
181+ uint64_t ticks_quot = mach_ticks / Platform_nanosecondsPerMachTickDenom ;
182+ uint64_t ticks_rem = mach_ticks % Platform_nanosecondsPerMachTickDenom ;
183+
184+ uint64_t part1 = ticks_quot * Platform_nanosecondsPerMachTickNumer ;
185+
186+ // When Platform_nanosecondsPerMachTickDenom * Platform_nanosecondsPerMachTickNumer is less than 2^64, ticks_rem *
187+ // Platform_nanosecondsPerMachTickNumer will be less than 2^64 as well, i.e. never overflows.
188+ uint64_t part2 = (ticks_rem * Platform_nanosecondsPerMachTickNumer ) / Platform_nanosecondsPerMachTickDenom ;
189+
190+ return part1 + part2 ;
191+ }
192+
174193// Converts "scheduler ticks" to nanoseconds.
175194// See `sysconf(_SC_CLK_TCK)`, as used to define the `Platform_nanosecondsPerSchedulerTick` constant.
176195double Platform_schedulerTicksToNanoseconds (const double scheduler_ticks ) {
0 commit comments