X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/a3d08fcd5120d2aa8303b6349ca8b14e3f284af3..4a3eedf9ecc9bbe3f3a5c6ce5e53ad199d639d32:/osfmk/ppc/rtclock.c diff --git a/osfmk/ppc/rtclock.c b/osfmk/ppc/rtclock.c index 9657b74f9..90a5754ae 100644 --- a/osfmk/ppc/rtclock.c +++ b/osfmk/ppc/rtclock.c @@ -1,23 +1,29 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * 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 + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * 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. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * 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, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * 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_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ @@ -35,82 +41,24 @@ #include #include +#include #include #include +#include -#include - -#include /* HZ */ #include #include #include #include - -#include +#include #include -int sysclk_config(void); - -int sysclk_init(void); - -void treqs(uint32_t dec); - -kern_return_t sysclk_gettime( - mach_timespec_t *cur_time); - -kern_return_t sysclk_getattr( - clock_flavor_t flavor, - clock_attr_t attr, - mach_msg_type_number_t *count); - -void sysclk_setalarm( - mach_timespec_t *deadline); - -struct clock_ops sysclk_ops = { - sysclk_config, sysclk_init, - sysclk_gettime, 0, - sysclk_getattr, 0, - sysclk_setalarm, -}; - -int calend_config(void); - -int calend_init(void); - -kern_return_t calend_gettime( - mach_timespec_t *cur_time); +int rtclock_config(void); -kern_return_t calend_getattr( - clock_flavor_t flavor, - clock_attr_t attr, - mach_msg_type_number_t *count); +int rtclock_init(void); -struct clock_ops calend_ops = { - calend_config, calend_init, - calend_gettime, 0, - calend_getattr, 0, - 0, -}; - -/* local data declarations */ - -static struct rtclock_calend { - uint32_t epoch; - uint32_t microepoch; - - uint64_t epoch1; - - int64_t adjtotal; - int32_t adjdelta; -} rtclock_calend; - -static boolean_t rtclock_initialized; - -static uint64_t rtclock_tick_deadline[NCPUS]; - -#define NSEC_PER_HZ (NSEC_PER_SEC / HZ) -static uint32_t rtclock_tick_interval; +#define NSEC_PER_HZ (NSEC_PER_SEC / 100) static uint32_t rtclock_sec_divisor; @@ -118,36 +66,8 @@ static mach_timebase_info_data_t rtclock_timebase_const; static boolean_t rtclock_timebase_initialized; -static struct rtclock_timer { - uint64_t deadline; - uint32_t - /*boolean_t*/ is_set:1, - has_expired:1, - :0; -} rtclock_timer[NCPUS]; - -static clock_timer_func_t rtclock_timer_expire; - -static timer_call_data_t rtclock_alarm_timer; - -static void timespec_to_absolutetime( - mach_timespec_t *ts, - uint64_t *result); - -static int deadline_to_decrementer( - uint64_t deadline, - uint64_t now); - -static void rtclock_alarm_expire( - timer_call_param_t p0, - timer_call_param_t p1); - -/* global data declarations */ - -#define DECREMENTER_MAX 0x7FFFFFFFUL -#define DECREMENTER_MIN 0xAUL - -natural_t rtclock_decrementer_min; +/* XXX this should really be in a header somewhere */ +extern clock_timer_func_t rtclock_timer_expire; decl_simple_lock_data(static,rtclock_lock) @@ -171,12 +91,11 @@ timebase_callback( struct timebase_freq_t *freq) { uint32_t numer, denom; - uint64_t abstime; spl_t s; if ( freq->timebase_den < 1 || freq->timebase_den > 4 || freq->timebase_num < freq->timebase_den ) - panic("rtclock timebase_callback: invalid constant %d / %d", + panic("rtclock timebase_callback: invalid constant %lu / %lu", freq->timebase_num, freq->timebase_den); denom = freq->timebase_num; @@ -184,20 +103,17 @@ timebase_callback( LOCK_RTC(s); if (!rtclock_timebase_initialized) { - commpage_set_timestamp(0,0,0,0); + commpage_set_timestamp(0,0,0); rtclock_timebase_const.numer = numer; rtclock_timebase_const.denom = denom; rtclock_sec_divisor = freq->timebase_num / freq->timebase_den; - nanoseconds_to_absolutetime(NSEC_PER_HZ, &abstime); - rtclock_tick_interval = abstime; - ml_init_lock_timeout(); } else { UNLOCK_RTC(s); - printf("rtclock timebase_callback: late old %d / %d new %d / %d", + printf("rtclock timebase_callback: late old %d / %d new %d / %d\n", rtclock_timebase_const.numer, rtclock_timebase_const.denom, numer, denom); return; @@ -208,17 +124,12 @@ timebase_callback( } /* - * Configure the real-time clock device. + * Configure the system clock device. */ int -sysclk_config(void) +rtclock_config(void) { - if (cpu_number() != master_cpu) - return(1); - - timer_call_setup(&rtclock_alarm_timer, rtclock_alarm_expire, NULL); - - simple_lock_init(&rtclock_lock, ETAP_MISC_RT_CLOCK); + simple_lock_init(&rtclock_lock, 0); PE_register_timebase_callback(timebase_callback); @@ -229,53 +140,13 @@ sysclk_config(void) * Initialize the system clock device. */ int -sysclk_init(void) +rtclock_init(void) { - uint64_t abstime; - int decr, mycpu = cpu_number(); - - if (mycpu != master_cpu) { - if (rtclock_initialized == FALSE) { - panic("sysclk_init on cpu %d, rtc not initialized\n", mycpu); - } - /* Set decrementer and hence our next tick due */ - abstime = mach_absolute_time(); - rtclock_tick_deadline[mycpu] = abstime; - rtclock_tick_deadline[mycpu] += rtclock_tick_interval; - decr = deadline_to_decrementer(rtclock_tick_deadline[mycpu], abstime); - treqs(decr); - - return(1); - } - - /* Set decrementer and our next tick due */ - abstime = mach_absolute_time(); - rtclock_tick_deadline[mycpu] = abstime; - rtclock_tick_deadline[mycpu] += rtclock_tick_interval; - decr = deadline_to_decrementer(rtclock_tick_deadline[mycpu], abstime); - treqs(decr); - - rtclock_initialized = TRUE; + etimer_resync_deadlines(); /* Start the timers going */ return (1); } -kern_return_t -sysclk_gettime( - mach_timespec_t *time) /* OUT */ -{ - uint64_t now, t64; - uint32_t divisor; - - now = mach_absolute_time(); - - time->tv_sec = t64 = now / (divisor = rtclock_sec_divisor); - now -= (t64 * divisor); - time->tv_nsec = (now * NSEC_PER_SEC) / divisor; - - return (KERN_SUCCESS); -} - void clock_get_system_microtime( uint32_t *secs, @@ -306,576 +177,29 @@ clock_get_system_nanotime( *nanosecs = (now * NSEC_PER_SEC) / divisor; } -/* - * Get clock device attributes. - */ -kern_return_t -sysclk_getattr( - clock_flavor_t flavor, - clock_attr_t attr, /* OUT */ - mach_msg_type_number_t *count) /* IN/OUT */ -{ - spl_t s; - - if (*count != 1) - return (KERN_FAILURE); - - switch (flavor) { - - case CLOCK_GET_TIME_RES: /* >0 res */ - case CLOCK_ALARM_CURRES: /* =0 no alarm */ - case CLOCK_ALARM_MINRES: - case CLOCK_ALARM_MAXRES: - LOCK_RTC(s); - *(clock_res_t *) attr = NSEC_PER_HZ; - UNLOCK_RTC(s); - break; - - default: - return (KERN_INVALID_VALUE); - } - - return (KERN_SUCCESS); -} - -/* - * Set deadline for the next alarm on the clock device. This call - * always resets the time to deliver an alarm for the clock. - */ -void -sysclk_setalarm( - mach_timespec_t *deadline) -{ - uint64_t abstime; - - timespec_to_absolutetime(deadline, &abstime); - timer_call_enter(&rtclock_alarm_timer, abstime); -} - -/* - * Configure the calendar clock. - */ -int -calend_config(void) -{ - return (1); -} - -/* - * Initialize the calendar clock. - */ -int -calend_init(void) -{ - if (cpu_number() != master_cpu) - return(1); - - return (1); -} - -/* - * Get the current clock time. - */ -kern_return_t -calend_gettime( - mach_timespec_t *time) /* OUT */ -{ - clock_get_calendar_nanotime( - &time->tv_sec, &time->tv_nsec); - - return (KERN_SUCCESS); -} - -/* - * Get clock device attributes. - */ -kern_return_t -calend_getattr( - clock_flavor_t flavor, - clock_attr_t attr, /* OUT */ - mach_msg_type_number_t *count) /* IN/OUT */ -{ - spl_t s; - - if (*count != 1) - return (KERN_FAILURE); - - switch (flavor) { - - case CLOCK_GET_TIME_RES: /* >0 res */ - LOCK_RTC(s); - *(clock_res_t *) attr = NSEC_PER_HZ; - UNLOCK_RTC(s); - break; - - case CLOCK_ALARM_CURRES: /* =0 no alarm */ - case CLOCK_ALARM_MINRES: - case CLOCK_ALARM_MAXRES: - *(clock_res_t *) attr = 0; - break; - - default: - return (KERN_INVALID_VALUE); - } - - return (KERN_SUCCESS); -} - -void -clock_get_calendar_microtime( - uint32_t *secs, - uint32_t *microsecs) -{ - uint32_t epoch, microepoch; - uint64_t now, t64; - spl_t s = splclock(); - - simple_lock(&rtclock_lock); - - if (rtclock_calend.adjdelta >= 0) { - uint32_t divisor; - - now = mach_absolute_time(); - - epoch = rtclock_calend.epoch; - microepoch = rtclock_calend.microepoch; - - simple_unlock(&rtclock_lock); - - *secs = t64 = now / (divisor = rtclock_sec_divisor); - now -= (t64 * divisor); - *microsecs = (now * USEC_PER_SEC) / divisor; - - if ((*microsecs += microepoch) >= USEC_PER_SEC) { - *microsecs -= USEC_PER_SEC; - epoch += 1; - } - - *secs += epoch; - } - else { - uint32_t delta, t32; - - delta = -rtclock_calend.adjdelta; - - now = mach_absolute_time(); - - *secs = rtclock_calend.epoch; - *microsecs = rtclock_calend.microepoch; - - if (now > rtclock_calend.epoch1) { - t64 = now - rtclock_calend.epoch1; - - t32 = (t64 * USEC_PER_SEC) / rtclock_sec_divisor; - - if (t32 > delta) - *microsecs += (t32 - delta); - - if (*microsecs >= USEC_PER_SEC) { - *microsecs -= USEC_PER_SEC; - *secs += 1; - } - } - - simple_unlock(&rtclock_lock); - } - - splx(s); -} - -/* This is only called from the gettimeofday() syscall. As a side - * effect, it updates the commpage timestamp. Otherwise it is - * identical to clock_get_calendar_microtime(). Because most - * gettimeofday() calls are handled by the commpage in user mode, - * this routine should be infrequently used except when slowing down - * the clock. - */ -void -clock_gettimeofday( - uint32_t *secs_p, - uint32_t *microsecs_p) -{ - uint32_t epoch, microepoch; - uint32_t secs, microsecs; - uint64_t now, t64, secs_64, usec_64; - spl_t s = splclock(); - - simple_lock(&rtclock_lock); - - if (rtclock_calend.adjdelta >= 0) { - now = mach_absolute_time(); - - epoch = rtclock_calend.epoch; - microepoch = rtclock_calend.microepoch; - - secs = secs_64 = now / rtclock_sec_divisor; - t64 = now - (secs_64 * rtclock_sec_divisor); - microsecs = usec_64 = (t64 * USEC_PER_SEC) / rtclock_sec_divisor; - - if ((microsecs += microepoch) >= USEC_PER_SEC) { - microsecs -= USEC_PER_SEC; - epoch += 1; - } - - secs += epoch; - - /* adjust "now" to be absolute time at _start_ of usecond */ - now -= t64 - ((usec_64 * rtclock_sec_divisor) / USEC_PER_SEC); - - commpage_set_timestamp(now,secs,microsecs,rtclock_sec_divisor); - } - else { - uint32_t delta, t32; - - delta = -rtclock_calend.adjdelta; - - now = mach_absolute_time(); - - secs = rtclock_calend.epoch; - microsecs = rtclock_calend.microepoch; - - if (now > rtclock_calend.epoch1) { - t64 = now - rtclock_calend.epoch1; - - t32 = (t64 * USEC_PER_SEC) / rtclock_sec_divisor; - - if (t32 > delta) - microsecs += (t32 - delta); - - if (microsecs >= USEC_PER_SEC) { - microsecs -= USEC_PER_SEC; - secs += 1; - } - } - - /* no need to disable timestamp, it is already off */ - } - - simple_unlock(&rtclock_lock); - splx(s); - - *secs_p = secs; - *microsecs_p = microsecs; -} - void -clock_get_calendar_nanotime( - uint32_t *secs, - uint32_t *nanosecs) +clock_gettimeofday_set_commpage( + uint64_t abstime, + uint64_t epoch, + uint64_t offset, + uint32_t *secs, + uint32_t *microsecs) { - uint32_t epoch, nanoepoch; - uint64_t now, t64; - spl_t s = splclock(); + uint64_t t64, now = abstime; simple_lock(&rtclock_lock); - if (rtclock_calend.adjdelta >= 0) { - uint32_t divisor; - - now = mach_absolute_time(); - - epoch = rtclock_calend.epoch; - nanoepoch = rtclock_calend.microepoch * NSEC_PER_USEC; - - simple_unlock(&rtclock_lock); - - *secs = t64 = now / (divisor = rtclock_sec_divisor); - now -= (t64 * divisor); - *nanosecs = ((now * USEC_PER_SEC) / divisor) * NSEC_PER_USEC; - - if ((*nanosecs += nanoepoch) >= NSEC_PER_SEC) { - *nanosecs -= NSEC_PER_SEC; - epoch += 1; - } - - *secs += epoch; - } - else { - uint32_t delta, t32; - - delta = -rtclock_calend.adjdelta; - - now = mach_absolute_time(); - - *secs = rtclock_calend.epoch; - *nanosecs = rtclock_calend.microepoch * NSEC_PER_USEC; - - if (now > rtclock_calend.epoch1) { - t64 = now - rtclock_calend.epoch1; - - t32 = (t64 * USEC_PER_SEC) / rtclock_sec_divisor; - - if (t32 > delta) - *nanosecs += ((t32 - delta) * NSEC_PER_USEC); - - if (*nanosecs >= NSEC_PER_SEC) { - *nanosecs -= NSEC_PER_SEC; - *secs += 1; - } - } - - simple_unlock(&rtclock_lock); - } - - splx(s); -} - -void -clock_set_calendar_microtime( - uint32_t secs, - uint32_t microsecs) -{ - uint32_t sys, microsys; - uint32_t newsecs; - spl_t s; - - newsecs = (microsecs < 500*USEC_PER_SEC)? - secs: secs + 1; - - LOCK_RTC(s); - commpage_set_timestamp(0,0,0,0); - - clock_get_system_microtime(&sys, µsys); - if ((int32_t)(microsecs -= microsys) < 0) { - microsecs += USEC_PER_SEC; - secs -= 1; - } - - secs -= sys; - - rtclock_calend.epoch = secs; - rtclock_calend.microepoch = microsecs; - rtclock_calend.epoch1 = 0; - rtclock_calend.adjdelta = rtclock_calend.adjtotal = 0; - UNLOCK_RTC(s); - - PESetGMTTimeOfDay(newsecs); - - host_notify_calendar_change(); -} - -#define tickadj (40) /* "standard" skew, us / tick */ -#define bigadj (USEC_PER_SEC) /* use 10x skew above bigadj us */ - -uint32_t -clock_set_calendar_adjtime( - int32_t *secs, - int32_t *microsecs) -{ - int64_t total, ototal; - uint32_t interval = 0; - spl_t s; - - total = (int64_t)*secs * USEC_PER_SEC + *microsecs; - - LOCK_RTC(s); - commpage_set_timestamp(0,0,0,0); - - ototal = rtclock_calend.adjtotal; - - if (rtclock_calend.adjdelta < 0) { - uint64_t now, t64; - uint32_t delta, t32; - uint32_t sys, microsys; - - delta = -rtclock_calend.adjdelta; - - sys = rtclock_calend.epoch; - microsys = rtclock_calend.microepoch; - - now = mach_absolute_time(); - - if (now > rtclock_calend.epoch1) - t64 = now - rtclock_calend.epoch1; - else - t64 = 0; - - t32 = (t64 * USEC_PER_SEC) / rtclock_sec_divisor; - - if (t32 > delta) - microsys += (t32 - delta); - - if (microsys >= USEC_PER_SEC) { - microsys -= USEC_PER_SEC; - sys += 1; - } - - rtclock_calend.epoch = sys; - rtclock_calend.microepoch = microsys; - - sys = t64 = now / rtclock_sec_divisor; - now -= (t64 * rtclock_sec_divisor); - microsys = (now * USEC_PER_SEC) / rtclock_sec_divisor; - - if ((int32_t)(rtclock_calend.microepoch -= microsys) < 0) { - rtclock_calend.microepoch += USEC_PER_SEC; - sys += 1; - } - - rtclock_calend.epoch -= sys; - } - - if (total != 0) { - int32_t delta = tickadj; - - if (total > 0) { - if (total > bigadj) - delta *= 10; - if (delta > total) - delta = total; - - rtclock_calend.epoch1 = 0; - } - else { - uint64_t now, t64; - uint32_t sys, microsys; - - if (total < -bigadj) - delta *= 10; - delta = -delta; - if (delta < total) - delta = total; - - rtclock_calend.epoch1 = now = mach_absolute_time(); - - sys = t64 = now / rtclock_sec_divisor; - now -= (t64 * rtclock_sec_divisor); - microsys = (now * USEC_PER_SEC) / rtclock_sec_divisor; - - if ((rtclock_calend.microepoch += microsys) >= USEC_PER_SEC) { - rtclock_calend.microepoch -= USEC_PER_SEC; - sys += 1; - } - - rtclock_calend.epoch += sys; - } - - rtclock_calend.adjtotal = total; - rtclock_calend.adjdelta = delta; - - interval = rtclock_tick_interval; - } - else { - rtclock_calend.epoch1 = 0; - rtclock_calend.adjdelta = rtclock_calend.adjtotal = 0; - } - - UNLOCK_RTC(s); - - if (ototal == 0) - *secs = *microsecs = 0; - else { - *secs = ototal / USEC_PER_SEC; - *microsecs = ototal % USEC_PER_SEC; - } - - return (interval); -} - -uint32_t -clock_adjust_calendar(void) -{ - uint32_t micronew, interval = 0; - int32_t delta; - spl_t s; + now += offset; - LOCK_RTC(s); - commpage_set_timestamp(0,0,0,0); - - delta = rtclock_calend.adjdelta; - - if (delta > 0) { - micronew = rtclock_calend.microepoch + delta; - if (micronew >= USEC_PER_SEC) { - micronew -= USEC_PER_SEC; - rtclock_calend.epoch += 1; - } - - rtclock_calend.microepoch = micronew; - - rtclock_calend.adjtotal -= delta; - if (delta > rtclock_calend.adjtotal) - rtclock_calend.adjdelta = rtclock_calend.adjtotal; - } - else - if (delta < 0) { - uint64_t now, t64; - uint32_t t32; - - now = mach_absolute_time(); - - if (now > rtclock_calend.epoch1) - t64 = now - rtclock_calend.epoch1; - else - t64 = 0; - - rtclock_calend.epoch1 = now; - - t32 = (t64 * USEC_PER_SEC) / rtclock_sec_divisor; - - micronew = rtclock_calend.microepoch + t32 + delta; - if (micronew >= USEC_PER_SEC) { - micronew -= USEC_PER_SEC; - rtclock_calend.epoch += 1; - } + *secs = t64 = now / rtclock_sec_divisor; + now -= (t64 * rtclock_sec_divisor); + *microsecs = (now * USEC_PER_SEC) / rtclock_sec_divisor; - rtclock_calend.microepoch = micronew; + *secs += epoch; - rtclock_calend.adjtotal -= delta; - if (delta < rtclock_calend.adjtotal) - rtclock_calend.adjdelta = rtclock_calend.adjtotal; + commpage_set_timestamp(abstime - now, *secs, rtclock_sec_divisor); - if (rtclock_calend.adjdelta == 0) { - uint32_t sys, microsys; - - sys = t64 = now / rtclock_sec_divisor; - now -= (t64 * rtclock_sec_divisor); - microsys = (now * USEC_PER_SEC) / rtclock_sec_divisor; - - if ((int32_t)(rtclock_calend.microepoch -= microsys) < 0) { - rtclock_calend.microepoch += USEC_PER_SEC; - sys += 1; - } - - rtclock_calend.epoch -= sys; - - rtclock_calend.epoch1 = 0; - } - } - - if (rtclock_calend.adjdelta != 0) - interval = rtclock_tick_interval; - - UNLOCK_RTC(s); - - return (interval); -} - -void -clock_initialize_calendar(void) -{ - uint32_t sys, microsys; - uint32_t microsecs = 0, secs = PEGetGMTTimeOfDay(); - spl_t s; - - LOCK_RTC(s); - commpage_set_timestamp(0,0,0,0); - - clock_get_system_microtime(&sys, µsys); - if ((int32_t)(microsecs -= microsys) < 0) { - microsecs += USEC_PER_SEC; - secs -= 1; - } - - secs -= sys; - - rtclock_calend.epoch = secs; - rtclock_calend.microepoch = microsecs; - rtclock_calend.epoch1 = 0; - rtclock_calend.adjdelta = rtclock_calend.adjtotal = 0; - UNLOCK_RTC(s); - - host_notify_calendar_change(); + simple_unlock(&rtclock_lock); } void @@ -885,42 +209,11 @@ clock_timebase_info( spl_t s; LOCK_RTC(s); - rtclock_timebase_initialized = TRUE; *info = rtclock_timebase_const; + rtclock_timebase_initialized = TRUE; UNLOCK_RTC(s); } -void -clock_set_timer_deadline( - uint64_t deadline) -{ - uint64_t abstime; - int decr, mycpu; - struct rtclock_timer *mytimer; - spl_t s; - - s = splclock(); - mycpu = cpu_number(); - mytimer = &rtclock_timer[mycpu]; - mytimer->deadline = deadline; - mytimer->is_set = TRUE; - if (!mytimer->has_expired) { - abstime = mach_absolute_time(); - if ( mytimer->deadline < rtclock_tick_deadline[mycpu] ) { - decr = deadline_to_decrementer(mytimer->deadline, abstime); - if ( rtclock_decrementer_min != 0 && - rtclock_decrementer_min < (natural_t)decr ) - decr = rtclock_decrementer_min; - - treqs(decr); - - KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI, 1) - | DBG_FUNC_NONE, decr, 2, 0, 0, 0); - } - } - splx(s); -} - void clock_set_timer_func( clock_timer_func_t func) @@ -933,127 +226,6 @@ clock_set_timer_func( UNLOCK_RTC(s); } -/* - * Reset the clock device. This causes the realtime clock - * device to reload its mode and count value (frequency). - */ -void -rtclock_reset(void) -{ - return; -} - -/* - * Real-time clock device interrupt. - */ -void -rtclock_intr( - int device, - struct savearea *ssp, - spl_t old_spl) -{ - uint64_t abstime; - int decr1, decr2, mycpu = cpu_number(); - struct rtclock_timer *mytimer = &rtclock_timer[mycpu]; - - /* - * We may receive interrupts too early, we must reject them. - */ - if (rtclock_initialized == FALSE) { - treqs(DECREMENTER_MAX); /* Max the decrementer if not init */ - return; - } - - decr1 = decr2 = DECREMENTER_MAX; - - abstime = mach_absolute_time(); - if ( rtclock_tick_deadline[mycpu] <= abstime ) { - clock_deadline_for_periodic_event(rtclock_tick_interval, abstime, - &rtclock_tick_deadline[mycpu]); - hertz_tick(USER_MODE(ssp->save_srr1), ssp->save_srr0); - } - - abstime = mach_absolute_time(); - if ( mytimer->is_set && - mytimer->deadline <= abstime ) { - mytimer->has_expired = TRUE; mytimer->is_set = FALSE; - (*rtclock_timer_expire)(abstime); - mytimer->has_expired = FALSE; - } - - abstime = mach_absolute_time(); - decr1 = deadline_to_decrementer(rtclock_tick_deadline[mycpu], abstime); - - if (mytimer->is_set) - decr2 = deadline_to_decrementer(mytimer->deadline, abstime); - - if (decr1 > decr2) - decr1 = decr2; - - if ( rtclock_decrementer_min != 0 && - rtclock_decrementer_min < (natural_t)decr1 ) - decr1 = rtclock_decrementer_min; - - treqs(decr1); - - KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI, 1) - | DBG_FUNC_NONE, decr1, 3, 0, 0, 0); -} - -static void -rtclock_alarm_expire( - timer_call_param_t p0, - timer_call_param_t p1) -{ - mach_timespec_t timestamp; - - (void) sysclk_gettime(×tamp); - - clock_alarm_intr(SYSTEM_CLOCK, ×tamp); -} - -static int -deadline_to_decrementer( - uint64_t deadline, - uint64_t now) -{ - uint64_t delt; - - if (deadline <= now) - return DECREMENTER_MIN; - else { - delt = deadline - now; - return (delt >= (DECREMENTER_MAX + 1))? DECREMENTER_MAX: - ((delt >= (DECREMENTER_MIN + 1))? (delt - 1): DECREMENTER_MIN); - } -} - -static void -timespec_to_absolutetime( - mach_timespec_t *ts, - uint64_t *result) -{ - uint32_t divisor; - - *result = ((uint64_t)ts->tv_sec * (divisor = rtclock_sec_divisor)) + - ((uint64_t)ts->tv_nsec * divisor) / NSEC_PER_SEC; -} - -void -clock_interval_to_deadline( - uint32_t interval, - uint32_t scale_factor, - uint64_t *result) -{ - uint64_t abstime; - - clock_get_uptime(result); - - clock_interval_to_absolutetime_interval(interval, scale_factor, &abstime); - - *result += abstime; -} - void clock_interval_to_absolutetime_interval( uint32_t interval, @@ -1071,13 +243,43 @@ clock_interval_to_absolutetime_interval( } void -clock_absolutetime_interval_to_deadline( +absolutetime_to_microtime( + uint64_t abstime, + uint32_t *secs, + uint32_t *microsecs) +{ + uint64_t t64; + uint32_t divisor; + + *secs = t64 = abstime / (divisor = rtclock_sec_divisor); + abstime -= (t64 * divisor); + *microsecs = (abstime * USEC_PER_SEC) / divisor; +} + +void +absolutetime_to_nanotime( uint64_t abstime, + uint32_t *secs, + uint32_t *nanosecs) +{ + uint64_t t64; + uint32_t divisor; + + *secs = t64 = abstime / (divisor = rtclock_sec_divisor); + abstime -= (t64 * divisor); + *nanosecs = (abstime * NSEC_PER_SEC) / divisor; +} + +void +nanotime_to_absolutetime( + uint32_t secs, + uint32_t nanosecs, uint64_t *result) { - clock_get_uptime(result); + uint32_t divisor = rtclock_sec_divisor; - *result += abstime; + *result = ((uint64_t)secs * divisor) + + ((uint64_t)nanosecs * divisor) / NSEC_PER_SEC; } void @@ -1107,25 +309,8 @@ nanoseconds_to_absolutetime( *result += (nanosecs * divisor) / NSEC_PER_SEC; } -/* - * Spin-loop delay primitives. - */ -void -delay_for_interval( - uint32_t interval, - uint32_t scale_factor) -{ - uint64_t now, end; - - clock_interval_to_deadline(interval, scale_factor, &end); - - do { - now = mach_absolute_time(); - } while (now < end); -} - void -clock_delay_until( +machine_delay_until( uint64_t deadline) { uint64_t now; @@ -1134,31 +319,3 @@ clock_delay_until( now = mach_absolute_time(); } while (now < deadline); } - -void -delay( - int usec) -{ - delay_for_interval((usec < 0)? -usec: usec, NSEC_PER_USEC); -} - -/* - * Request a decrementer pop - * - */ - -void treqs(uint32_t dec) { - - - struct per_proc_info *pp; - uint64_t nowtime, newtime; - - nowtime = mach_absolute_time(); /* What time is it? */ - pp = getPerProc(); /* Get our processor block */ - newtime = nowtime + (uint64_t)dec; /* Get requested pop time */ - pp->rtcPop = newtime; /* Copy it */ - - mtdec((uint32_t)(newtime - nowtime)); /* Set decrementer */ - return; - -}