X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/060df5ea7c632b1ac8cc8aac1fb59758165c2084..refs/heads/master:/osfmk/i386/rtclock.c?ds=sidebyside diff --git a/osfmk/i386/rtclock.c b/osfmk/i386/rtclock.c index 72b1f556f..08aed1af1 100644 --- a/osfmk/i386/rtclock.c +++ b/osfmk/i386/rtclock.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 2000-2010 Apple Inc. All rights reserved. + * Copyright (c) 2000-2012 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,7 +22,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* @@ -39,8 +39,6 @@ * the cpu clock counted by the timestamp MSR. */ -#include -#include #include @@ -52,193 +50,38 @@ #include #include #include -#include +#include #include #include -#include /* for kernel_map */ -#include +#include /* for kernel_map */ #include #include #include #include #include #include +#include #include #include -#include #include #include #include #include #include -#include - -#define UI_CPUFREQ_ROUNDING_FACTOR 10000000 +#include +#define UI_CPUFREQ_ROUNDING_FACTOR 10000000 -int rtclock_config(void); +int rtclock_init(void); -int rtclock_init(void); +uint64_t tsc_rebase_abs_time = 0; -uint64_t tsc_rebase_abs_time = 0; +volatile uint64_t gAcpiLastSleepTscBase = 0; +volatile uint64_t gAcpiLastSleepNanoBase = 0; +volatile uint64_t gAcpiLastWakeTscBase = 0; +volatile uint64_t gAcpiLastWakeNanoBase = 0; -void rtclock_intr(x86_saved_state_t *regs); - -static void rtc_set_timescale(uint64_t cycles); -static uint64_t rtc_export_speed(uint64_t cycles); - -rtc_nanotime_t rtc_nanotime_info = {0,0,0,0,1,0}; - -static uint64_t rtc_decrementer_min; -static uint64_t rtc_decrementer_max; - -static uint64_t -deadline_to_decrementer( - uint64_t deadline, - uint64_t now) -{ - uint64_t delta; - - if (deadline <= now) - return rtc_decrementer_min; - else { - delta = deadline - now; - return MIN(MAX(rtc_decrementer_min,delta),rtc_decrementer_max); - } -} - -static inline uint64_t -_absolutetime_to_tsc(uint64_t ns) -{ - uint32_t generation; - uint64_t tsc; - - do { - generation = rtc_nanotime_info.generation; - tsc = tmrCvt(ns - rtc_nanotime_info.ns_base, tscFCvtn2t) - + rtc_nanotime_info.tsc_base; - } while (generation == 0 || - generation != rtc_nanotime_info.generation); - - return tsc; -} - -/* - * Regular local APIC timer case: - */ -static void -rtc_lapic_config_timer(void) -{ - lapic_config_timer(TRUE, one_shot, divide_by_1); -} -static uint64_t -rtc_lapic_set_timer(uint64_t deadline, uint64_t now) -{ - uint64_t count; - uint64_t set = 0; - - if (deadline > 0) { - /* - * Convert delta to bus ticks - * - time now is not relevant - */ - count = deadline_to_decrementer(deadline, now); - set = now + count; - lapic_set_timer_fast((uint32_t) tmrCvt(count, busFCvtn2t)); - } else { - lapic_set_timer(FALSE, one_shot, divide_by_1, 0); - } - return set; -} - -/* - * TSC-deadline timer case: - */ -static void -rtc_lapic_config_tsc_deadline_timer(void) -{ - lapic_config_tsc_deadline_timer(); -} -static uint64_t -rtc_lapic_set_tsc_deadline_timer(uint64_t deadline, uint64_t now) -{ - uint64_t set = 0; - - if (deadline > 0) { - /* - * Convert to TSC - */ - set = now + deadline_to_decrementer(deadline, now); - lapic_set_tsc_deadline_timer(_absolutetime_to_tsc(set)); - } else { - lapic_set_tsc_deadline_timer(0); - } - return set; -} - -/* - * Definitions for timer operations table - */ -typedef struct { - void (*config)(void); - uint64_t (*set) (uint64_t, uint64_t); -} rtc_timer_t; - -rtc_timer_t rtc_timer_lapic = { - rtc_lapic_config_timer, - rtc_lapic_set_timer -}; - -rtc_timer_t rtc_timer_tsc_deadline = { - rtc_lapic_config_tsc_deadline_timer, - rtc_lapic_set_tsc_deadline_timer -}; - -rtc_timer_t *rtc_timer = &rtc_timer_lapic; /* defaults to LAPIC timer */ - -/* - * rtc_timer_init() is called at startup on the boot processor only. - */ -static void -rtc_timer_init(void) -{ - int TSC_deadline_timer = 0; - - /* See whether we can use the local apic in TSC-deadline mode */ - if ((cpuid_features() & CPUID_FEATURE_TSCTMR)) { - TSC_deadline_timer = 1; - PE_parse_boot_argn("TSC_deadline_timer", &TSC_deadline_timer, - sizeof(TSC_deadline_timer)); - printf("TSC Deadline Timer supported %s enabled\n", - TSC_deadline_timer ? "and" : "but not"); - } - - if (TSC_deadline_timer) { - rtc_timer = &rtc_timer_tsc_deadline; - rtc_decrementer_max = UINT64_MAX; /* effectively none */ - /* - * The min could be as low as 1nsec, - * but we're being conservative for now and making it the same - * as for the local apic timer. - */ - rtc_decrementer_min = 1*NSEC_PER_USEC; /* 1 usec */ - } else { - /* - * Compute the longest interval using LAPIC timer. - */ - rtc_decrementer_max = tmrCvt(0x7fffffffULL, busFCvtt2n); - kprintf("maxDec: %lld\n", rtc_decrementer_max); - rtc_decrementer_min = 1*NSEC_PER_USEC; /* 1 usec */ - } - - /* Point LAPIC interrupts to hardclock() */ - lapic_set_timer_func((i386_intr_func_t) rtclock_intr); -} - -static inline uint64_t -rtc_timer_set(uint64_t deadline, uint64_t now) -{ - return rtc_timer->set(deadline, now); -} +static void rtc_set_timescale(uint64_t cycles); +static uint64_t rtc_export_speed(uint64_t cycles); void rtc_timer_start(void) @@ -246,97 +89,27 @@ rtc_timer_start(void) /* * Force a complete re-evaluation of timer deadlines. */ - etimer_resync_deadlines(); -} - -/* - * tsc_to_nanoseconds: - * - * Basic routine to convert a raw 64 bit TSC value to a - * 64 bit nanosecond value. The conversion is implemented - * based on the scale factor and an implicit 32 bit shift. - */ -static inline uint64_t -_tsc_to_nanoseconds(uint64_t value) -{ -#if defined(__i386__) - asm volatile("movl %%edx,%%esi ;" - "mull %%ecx ;" - "movl %%edx,%%edi ;" - "movl %%esi,%%eax ;" - "mull %%ecx ;" - "addl %%edi,%%eax ;" - "adcl $0,%%edx " - : "+A" (value) - : "c" (rtc_nanotime_info.scale) - : "esi", "edi"); -#elif defined(__x86_64__) - asm volatile("mul %%rcx;" - "shrq $32, %%rax;" - "shlq $32, %%rdx;" - "orq %%rdx, %%rax;" - : "=a"(value) - : "a"(value), "c"(rtc_nanotime_info.scale) - : "rdx", "cc" ); -#else -#error Unsupported architecture -#endif - - return (value); + x86_lcpu()->rtcDeadline = EndOfAllTime; + timer_resync_deadlines(); } static inline uint32_t _absolutetime_to_microtime(uint64_t abstime, clock_sec_t *secs, clock_usec_t *microsecs) { uint32_t remain; -#if defined(__i386__) - asm volatile( - "divl %3" - : "=a" (*secs), "=d" (remain) - : "A" (abstime), "r" (NSEC_PER_SEC)); - asm volatile( - "divl %3" - : "=a" (*microsecs) - : "0" (remain), "d" (0), "r" (NSEC_PER_USEC)); -#elif defined(__x86_64__) *secs = abstime / (uint64_t)NSEC_PER_SEC; remain = (uint32_t)(abstime % (uint64_t)NSEC_PER_SEC); *microsecs = remain / NSEC_PER_USEC; -#else -#error Unsupported architecture -#endif return remain; } static inline void _absolutetime_to_nanotime(uint64_t abstime, clock_sec_t *secs, clock_usec_t *nanosecs) { -#if defined(__i386__) - asm volatile( - "divl %3" - : "=a" (*secs), "=d" (*nanosecs) - : "A" (abstime), "r" (NSEC_PER_SEC)); -#elif defined(__x86_64__) *secs = abstime / (uint64_t)NSEC_PER_SEC; *nanosecs = (clock_usec_t)(abstime % (uint64_t)NSEC_PER_SEC); -#else -#error Unsupported architecture -#endif } -/* - * Configure the real-time clock device. Return success (1) - * or failure (0). - */ - -int -rtclock_config(void) -{ - /* nothing to do */ - return (1); -} - - /* * Nanotime/mach_absolutime_time * ----------------------------- @@ -347,19 +120,19 @@ rtclock_config(void) * used to maintain a monotonic clock, adjusted from an outside reference as needed. * * The kernel maintains nanotime information recording: - * - the ratio of tsc to nanoseconds + * - the ratio of tsc to nanoseconds * with this ratio expressed as a 32-bit scale and shift * (power of 2 divider); * - { tsc_base, ns_base } pair of corresponding timestamps. * - * The tuple {tsc_base, ns_base, scale, shift} is exported in the commpage + * The tuple {tsc_base, ns_base, scale, shift} is exported in the commpage * for the userspace nanotime routine to read. * * All of the routines which update the nanotime data are non-reentrant. This must * be guaranteed by the caller. */ static inline void -rtc_nanotime_set_commpage(rtc_nanotime_t *rntp) +rtc_nanotime_set_commpage(pal_rtc_nanotime_t *rntp) { commpage_set_nanotime(rntp->tsc_base, rntp->ns_base, rntp->scale, rntp->shift); } @@ -370,18 +143,25 @@ rtc_nanotime_set_commpage(rtc_nanotime_t *rntp) * Intialize the nanotime info from the base time. */ static inline void -_rtc_nanotime_init(rtc_nanotime_t *rntp, uint64_t base) +_rtc_nanotime_init(pal_rtc_nanotime_t *rntp, uint64_t base) { - uint64_t tsc = rdtsc64(); + uint64_t tsc = rdtsc64(); - _rtc_nanotime_store(tsc, base, rntp->scale, rntp->shift, rntp); + _pal_rtc_nanotime_store(tsc, base, rntp->scale, rntp->shift, rntp); } -static void +void rtc_nanotime_init(uint64_t base) { - _rtc_nanotime_init(&rtc_nanotime_info, base); - rtc_nanotime_set_commpage(&rtc_nanotime_info); + gAcpiLastSleepTscBase = pal_rtc_nanotime_info.tsc_base; + gAcpiLastSleepNanoBase = pal_rtc_nanotime_info.ns_base; + + _rtc_nanotime_init(&pal_rtc_nanotime_info, base); + + gAcpiLastWakeTscBase = pal_rtc_nanotime_info.tsc_base; + gAcpiLastWakeNanoBase = pal_rtc_nanotime_info.ns_base; + + rtc_nanotime_set_commpage(&pal_rtc_nanotime_info); } /* @@ -394,10 +174,9 @@ rtc_nanotime_init(uint64_t base) void rtc_nanotime_init_commpage(void) { - spl_t s = splclock(); - - rtc_nanotime_set_commpage(&rtc_nanotime_info); + spl_t s = splclock(); + rtc_nanotime_set_commpage(&pal_rtc_nanotime_info); splx(s); } @@ -410,13 +189,7 @@ rtc_nanotime_init_commpage(void) static inline uint64_t rtc_nanotime_read(void) { - -#if CONFIG_EMBEDDED - if (gPEClockFrequencyInfo.timebase_frequency_hz > SLOW_TSC_THRESHOLD) - return _rtc_nanotime_read(&rtc_nanotime_info, 1); /* slow processor */ - else -#endif - return _rtc_nanotime_read(&rtc_nanotime_info, 0); /* assume fast processor */ + return _rtc_nanotime_read(&pal_rtc_nanotime_info); } /* @@ -429,74 +202,58 @@ rtc_nanotime_read(void) void rtc_clock_napped(uint64_t base, uint64_t tsc_base) { - rtc_nanotime_t *rntp = &rtc_nanotime_info; - uint64_t oldnsecs; - uint64_t newnsecs; - uint64_t tsc; + pal_rtc_nanotime_t *rntp = &pal_rtc_nanotime_info; + uint64_t oldnsecs; + uint64_t newnsecs; + uint64_t tsc; assert(!ml_get_interrupts_enabled()); tsc = rdtsc64(); - oldnsecs = rntp->ns_base + _tsc_to_nanoseconds(tsc - rntp->tsc_base); - newnsecs = base + _tsc_to_nanoseconds(tsc - tsc_base); - + oldnsecs = rntp->ns_base + _rtc_tsc_to_nanoseconds(tsc - rntp->tsc_base, rntp); + newnsecs = base + _rtc_tsc_to_nanoseconds(tsc - tsc_base, rntp); + /* * Only update the base values if time using the new base values * is later than the time using the old base values. */ if (oldnsecs < newnsecs) { - _rtc_nanotime_store(tsc_base, base, rntp->scale, rntp->shift, rntp); - rtc_nanotime_set_commpage(rntp); + _pal_rtc_nanotime_store(tsc_base, base, rntp->scale, rntp->shift, rntp); + rtc_nanotime_set_commpage(rntp); } } - /* * Invoked from power management to correct the SFLM TSC entry drift problem: - * a small delta is added to the tsc_base. This is equivalent to nudging time - * backwards. We require this of the order of a TSC quantum which won't cause - * callers of mach_absolute_time() to see time going backwards! + * a small delta is added to the tsc_base. This is equivalent to nudgin time + * backwards. We require this to be on the order of a TSC quantum which won't + * cause callers of mach_absolute_time() to see time going backwards! */ void rtc_clock_adjust(uint64_t tsc_base_delta) { - rtc_nanotime_t *rntp = &rtc_nanotime_info; + pal_rtc_nanotime_t *rntp = &pal_rtc_nanotime_info; assert(!ml_get_interrupts_enabled()); - assert(tsc_base_delta < 100ULL); /* i.e. it's small */ + assert(tsc_base_delta < 100ULL); /* i.e. it's small */ _rtc_nanotime_adjust(tsc_base_delta, rntp); rtc_nanotime_set_commpage(rntp); } - -void -rtc_clock_stepping(__unused uint32_t new_frequency, - __unused uint32_t old_frequency) -{ - panic("rtc_clock_stepping unsupported"); -} - -void -rtc_clock_stepped(__unused uint32_t new_frequency, - __unused uint32_t old_frequency) -{ - panic("rtc_clock_stepped unsupported"); -} - /* * rtc_sleep_wakeup: * - * Invoked from power manageent when we have awoken from a sleep (S3) - * and the TSC has been reset. The nanotime data is updated based on - * the passed in value. + * Invoked from power management when we have awoken from a sleep (S3) + * and the TSC has been reset, or from Deep Idle (S0) sleep when the TSC + * has progressed. The nanotime data is updated based on the passed-in value. * * The caller must guarantee non-reentrancy. */ void rtc_sleep_wakeup( - uint64_t base) + uint64_t base) { - /* Set fixed configuration for lapic timers */ - rtc_timer->config(); + /* Set fixed configuration for lapic timers */ + rtc_timer->rtc_config(); /* * Reset nanotime. @@ -506,6 +263,22 @@ rtc_sleep_wakeup( rtc_nanotime_init(base); } +void +rtc_decrementer_configure(void) +{ + rtc_timer->rtc_config(); +} +/* + * rtclock_early_init() is called very early at boot to + * establish mach_absolute_time() and set it to zero. + */ +void +rtclock_early_init(void) +{ + assert(tscFreq); + rtc_set_timescale(tscFreq); +} + /* * Initialize the real-time clock device. * In addition, various variables used to support the clock are initialized. @@ -513,14 +286,12 @@ rtc_sleep_wakeup( int rtclock_init(void) { - uint64_t cycles; + uint64_t cycles; assert(!ml_get_interrupts_enabled()); if (cpu_number() == master_cpu) { - assert(tscFreq); - rtc_set_timescale(tscFreq); /* * Adjust and set the exported cpu speed. @@ -537,32 +308,46 @@ rtclock_init(void) rtc_timer_init(); clock_timebase_init(); ml_init_lock_timeout(); + ml_init_delay_spin_threshold(10); } /* Set fixed configuration for lapic timers */ - rtc_timer->config(); - + rtc_timer->rtc_config(); rtc_timer_start(); - return (1); + return 1; } -// utility routine +// utility routine // Code to calculate how many processor cycles are in a second... static void rtc_set_timescale(uint64_t cycles) { - rtc_nanotime_t *rntp = &rtc_nanotime_info; + pal_rtc_nanotime_t *rntp = &pal_rtc_nanotime_info; + uint32_t shift = 0; + + /* the "scale" factor will overflow unless cycles>SLOW_TSC_THRESHOLD */ + + while (cycles <= SLOW_TSC_THRESHOLD) { + shift++; + cycles <<= 1; + } + rntp->scale = (uint32_t)(((uint64_t)NSEC_PER_SEC << 32) / cycles); - if (cycles <= SLOW_TSC_THRESHOLD) - rntp->shift = (uint32_t)cycles; - else - rntp->shift = 32; + rntp->shift = shift; - if (tsc_rebase_abs_time == 0) - tsc_rebase_abs_time = mach_absolute_time(); + /* + * On some platforms, the TSC is not reset at warm boot. But the + * rebase time must be relative to the current boot so we can't use + * mach_absolute_time(). Instead, we convert the TSC delta since boot + * to nanoseconds. + */ + if (tsc_rebase_abs_time == 0) { + tsc_rebase_abs_time = _rtc_tsc_to_nanoseconds( + rdtsc64() - tsc_at_boot, rntp); + } rtc_nanotime_init(0); } @@ -570,136 +355,127 @@ rtc_set_timescale(uint64_t cycles) static uint64_t rtc_export_speed(uint64_t cyc_per_sec) { - uint64_t cycles; + pal_rtc_nanotime_t *rntp = &pal_rtc_nanotime_info; + uint64_t cycles; + + if (rntp->shift != 0) { + printf("Slow TSC, rtc_nanotime.shift == %d\n", rntp->shift); + } /* Round: */ - cycles = ((cyc_per_sec + (UI_CPUFREQ_ROUNDING_FACTOR/2)) - / UI_CPUFREQ_ROUNDING_FACTOR) - * UI_CPUFREQ_ROUNDING_FACTOR; + cycles = ((cyc_per_sec + (UI_CPUFREQ_ROUNDING_FACTOR / 2)) + / UI_CPUFREQ_ROUNDING_FACTOR) + * UI_CPUFREQ_ROUNDING_FACTOR; /* * Set current measured speed. */ - if (cycles >= 0x100000000ULL) { - gPEClockFrequencyInfo.cpu_clock_rate_hz = 0xFFFFFFFFUL; - } else { - gPEClockFrequencyInfo.cpu_clock_rate_hz = (unsigned long)cycles; - } - gPEClockFrequencyInfo.cpu_frequency_hz = cycles; + if (cycles >= 0x100000000ULL) { + gPEClockFrequencyInfo.cpu_clock_rate_hz = 0xFFFFFFFFUL; + } else { + gPEClockFrequencyInfo.cpu_clock_rate_hz = (unsigned long)cycles; + } + gPEClockFrequencyInfo.cpu_frequency_hz = cycles; kprintf("[RTCLOCK] frequency %llu (%llu)\n", cycles, cyc_per_sec); - return(cycles); + return cycles; } void clock_get_system_microtime( - clock_sec_t *secs, - clock_usec_t *microsecs) + clock_sec_t *secs, + clock_usec_t *microsecs) { - uint64_t now = rtc_nanotime_read(); + uint64_t now = rtc_nanotime_read(); _absolutetime_to_microtime(now, secs, microsecs); } void clock_get_system_nanotime( - clock_sec_t *secs, - clock_nsec_t *nanosecs) + clock_sec_t *secs, + clock_nsec_t *nanosecs) { - uint64_t now = rtc_nanotime_read(); + uint64_t now = rtc_nanotime_read(); _absolutetime_to_nanotime(now, secs, nanosecs); } void -clock_gettimeofday_set_commpage( - uint64_t abstime, - uint64_t epoch, - uint64_t offset, - clock_sec_t *secs, - clock_usec_t *microsecs) +clock_gettimeofday_set_commpage(uint64_t abstime, uint64_t sec, uint64_t frac, uint64_t scale, uint64_t tick_per_sec) { - uint64_t now = abstime + offset; - uint32_t remain; - - remain = _absolutetime_to_microtime(now, secs, microsecs); - - *secs += (clock_sec_t)epoch; - - commpage_set_timestamp(abstime - remain, *secs); + commpage_set_timestamp(abstime, sec, frac, scale, tick_per_sec); } void clock_timebase_info( - mach_timebase_info_t info) + mach_timebase_info_t info) { info->numer = info->denom = 1; -} +} /* * Real-time clock device interrupt. */ void rtclock_intr( - x86_saved_state_t *tregs) + x86_saved_state_t *tregs) { - uint64_t rip; - boolean_t user_mode = FALSE; + uint64_t rip; + boolean_t user_mode = FALSE; assert(get_preemption_level() > 0); assert(!ml_get_interrupts_enabled()); if (is_saved_state64(tregs) == TRUE) { - x86_saved_state64_t *regs; - + x86_saved_state64_t *regs; + regs = saved_state64(tregs); - if (regs->isf.cs & 0x03) + if (regs->isf.cs & 0x03) { user_mode = TRUE; + } rip = regs->isf.rip; } else { - x86_saved_state32_t *regs; + x86_saved_state32_t *regs; regs = saved_state32(tregs); - if (regs->cs & 0x03) - user_mode = TRUE; + if (regs->cs & 0x03) { + user_mode = TRUE; + } rip = regs->eip; } /* call the generic etimer */ - etimer_intr(user_mode, rip); + timer_intr(user_mode, rip); } /* - * Request timer pop from the hardware + * Request timer pop from the hardware */ uint64_t -setPop( - uint64_t time) +setPop(uint64_t time) { - uint64_t now; - uint64_t pop; + uint64_t now; + uint64_t pop; /* 0 and EndOfAllTime are special-cases for "clear the timer" */ if (time == 0 || time == EndOfAllTime) { time = EndOfAllTime; now = 0; - pop = rtc_timer_set(0, 0); + pop = rtc_timer->rtc_set(0, 0); } else { - now = rtc_nanotime_read(); - pop = rtc_timer_set(time, now); + now = rtc_nanotime_read(); /* The time in nanoseconds */ + pop = rtc_timer->rtc_set(time, now); } - /* Record actual deadline set */ + /* Record requested and actual deadlines set */ x86_lcpu()->rtcDeadline = time; - x86_lcpu()->rtcPop = pop; + x86_lcpu()->rtcPop = pop; - /* - * Pass back the delta we set - */ return pop - now; } @@ -709,66 +485,62 @@ mach_absolute_time(void) return rtc_nanotime_read(); } +uint64_t +mach_approximate_time(void) +{ + return rtc_nanotime_read(); +} + void clock_interval_to_absolutetime_interval( - uint32_t interval, - uint32_t scale_factor, - uint64_t *result) + uint32_t interval, + uint32_t scale_factor, + uint64_t *result) { *result = (uint64_t)interval * scale_factor; } void absolutetime_to_microtime( - uint64_t abstime, - clock_sec_t *secs, - clock_usec_t *microsecs) + uint64_t abstime, + clock_sec_t *secs, + clock_usec_t *microsecs) { _absolutetime_to_microtime(abstime, secs, microsecs); } -void -absolutetime_to_nanotime( - uint64_t abstime, - clock_sec_t *secs, - clock_nsec_t *nanosecs) -{ - _absolutetime_to_nanotime(abstime, secs, nanosecs); -} - void nanotime_to_absolutetime( - clock_sec_t secs, - clock_nsec_t nanosecs, - uint64_t *result) + clock_sec_t secs, + clock_nsec_t nanosecs, + uint64_t *result) { *result = ((uint64_t)secs * NSEC_PER_SEC) + nanosecs; } void absolutetime_to_nanoseconds( - uint64_t abstime, - uint64_t *result) + uint64_t abstime, + uint64_t *result) { *result = abstime; } void nanoseconds_to_absolutetime( - uint64_t nanoseconds, - uint64_t *result) + uint64_t nanoseconds, + uint64_t *result) { *result = nanoseconds; } void machine_delay_until( - uint64_t deadline) + uint64_t interval, + uint64_t deadline) { - uint64_t now; - - do { + (void)interval; + while (mach_absolute_time() < deadline) { cpu_pause(); - now = mach_absolute_time(); - } while (now < deadline); + } }