#include <kern/lock.h>
#include <kern/host.h>
#include <kern/spl.h>
+#include <kern/sched_prim.h>
#include <kern/thread.h>
#include <kern/thread_swap.h>
#include <kern/ipc_host.h>
#include <mach/clock_reply.h>
#include <mach/mach_time.h>
-#include <kern/mk_timer.h>
-
/*
* Exported interface
*/
static thread_call_data_t alarm_deliver;
decl_simple_lock_data(static,calend_adjlock)
-static int64_t calend_adjtotal;
-static uint32_t calend_adjdelta;
static timer_call_data_t calend_adjcall;
static uint64_t calend_adjinterval, calend_adjdeadline;
+static thread_call_data_t calend_wakecall;
+
/* backwards compatibility */
int hz = HZ; /* GET RID OF THIS !!! */
int tick = (1000000 / HZ); /* GET RID OF THIS !!! */
thread_call_param_t p1);
static
-void clock_calend_adjust(
+void calend_adjust_call(
timer_call_param_t p0,
timer_call_param_t p1);
+static
+void calend_dowakeup(
+ thread_call_param_t p0,
+ thread_call_param_t p1);
+
/*
* Macros to lock/unlock clock system.
*/
if (cpu_number() != master_cpu)
panic("clock_config");
+ simple_lock_init(&ClockLock, ETAP_MISC_CLOCK);
+ thread_call_setup(&alarm_deliver, clock_alarm_deliver, NULL);
+
+ simple_lock_init(&calend_adjlock, ETAP_MISC_CLOCK);
+ timer_call_setup(&calend_adjcall, calend_adjust_call, NULL);
+
+ thread_call_setup(&calend_wakecall, calend_dowakeup, NULL);
+
/*
* Configure clock devices.
*/
- simple_lock_init(&calend_adjlock, ETAP_MISC_CLOCK);
- simple_lock_init(&ClockLock, ETAP_MISC_CLOCK);
for (i = 0; i < clock_count; i++) {
clock = &clock_list[i];
if (clock->cl_ops) {
}
}
+/*
+ * Called by machine dependent code
+ * to initialize areas dependent on the
+ * timebase value. May be called multiple
+ * times during start up.
+ */
+void
+clock_timebase_init(void)
+{
+ sched_timebase_init();
+}
+
/*
* Initialize the clock ipc service facility.
*/
clock_t clock;
register int i;
- mk_timer_initialize();
-
/*
* Initialize ipc clock services.
*/
}
}
- timer_call_setup(&calend_adjcall, clock_calend_adjust, NULL);
-
/*
- * Initialize clock service alarms.
+ * Perform miscellaneous late
+ * initialization.
*/
i = sizeof(struct alarm);
alarm_zone = zinit(i, (4096/i)*i, 10*i, "alarms");
-
- thread_call_setup(&alarm_deliver, clock_alarm_deliver, NULL);
}
/*
mach_timespec_t *clock_time;
kern_return_t (*settime)(
mach_timespec_t *clock_time);
- extern kern_return_t
- calend_settime(
- mach_timespec_t *clock_time);
if (clock == CLOCK_NULL)
return (KERN_INVALID_ARGUMENT);
if ((settime = clock->cl_ops->c_settime) == 0)
return (KERN_FAILURE);
- if (settime == calend_settime)
- return (KERN_FAILURE);
clock_time = &new_time;
if (BAD_MACH_TIMESPEC(clock_time))
return (KERN_INVALID_VALUE);
return value;
}
-void
-clock_set_calendar_value(
- mach_timespec_t value)
-{
- clock_t clock = &clock_list[CALENDAR_CLOCK];
-
- (void) (*clock->cl_ops->c_settime)(&value);
-}
-
void
clock_deadline_for_periodic_event(
uint64_t interval,
*deadline += interval;
if (*deadline <= abstime) {
- *deadline = abstime;
- clock_get_uptime(&abstime);
- *deadline += interval;
+ *deadline = abstime + interval;
+ abstime = mach_absolute_time();
- if (*deadline <= abstime) {
- *deadline = abstime;
- *deadline += interval;
- }
+ if (*deadline <= abstime)
+ *deadline = abstime + interval;
}
}
return ((wait_result == THREAD_INTERRUPTED)? KERN_ABORTED: KERN_SUCCESS);
}
-int64_t
-clock_set_calendar_adjtime(
- int64_t total,
- uint32_t delta)
+void
+clock_adjtime(
+ int32_t *secs,
+ int32_t *microsecs)
{
- int64_t ototal;
- spl_t s;
+ uint32_t interval;
+ spl_t s;
s = splclock();
simple_lock(&calend_adjlock);
- if (calend_adjinterval == 0)
- clock_interval_to_absolutetime_interval(10000, NSEC_PER_USEC,
- &calend_adjinterval);
-
- ototal = calend_adjtotal;
-
- if (total != 0) {
- uint64_t abstime;
-
- if (total > 0) {
- if (delta > total)
- delta = total;
- }
- else {
- if (delta > -total)
- delta = -total;
- }
-
- calend_adjtotal = total;
- calend_adjdelta = delta;
-
- if (calend_adjdeadline >= calend_adjinterval)
- calend_adjdeadline -= calend_adjinterval;
- clock_get_uptime(&abstime);
- clock_deadline_for_periodic_event(calend_adjinterval, abstime,
- &calend_adjdeadline);
+ interval = clock_set_calendar_adjtime(secs, microsecs);
+ if (interval != 0) {
+ if (calend_adjdeadline >= interval)
+ calend_adjdeadline -= interval;
+ clock_deadline_for_periodic_event(interval, mach_absolute_time(),
+ &calend_adjdeadline);
timer_call_enter(&calend_adjcall, calend_adjdeadline);
}
- else {
- calend_adjtotal = 0;
-
+ else
timer_call_cancel(&calend_adjcall);
- }
simple_unlock(&calend_adjlock);
splx(s);
-
- return (ototal);
}
static void
-clock_calend_adjust(
+calend_adjust_call(
timer_call_param_t p0,
timer_call_param_t p1)
{
+ uint32_t interval;
spl_t s;
s = splclock();
simple_lock(&calend_adjlock);
- if (calend_adjtotal > 0) {
- clock_adjust_calendar((clock_res_t)calend_adjdelta);
- calend_adjtotal -= calend_adjdelta;
-
- if (calend_adjdelta > calend_adjtotal)
- calend_adjdelta = calend_adjtotal;
- }
- else
- if (calend_adjtotal < 0) {
- clock_adjust_calendar(-(clock_res_t)calend_adjdelta);
- calend_adjtotal += calend_adjdelta;
-
- if (calend_adjdelta > -calend_adjtotal)
- calend_adjdelta = -calend_adjtotal;
- }
-
- if (calend_adjtotal != 0) {
- uint64_t abstime;
-
- clock_get_uptime(&abstime);
- clock_deadline_for_periodic_event(calend_adjinterval, abstime,
- &calend_adjdeadline);
+ interval = clock_adjust_calendar();
+ if (interval != 0) {
+ clock_deadline_for_periodic_event(interval, mach_absolute_time(),
+ &calend_adjdeadline);
timer_call_enter(&calend_adjcall, calend_adjdeadline);
}
simple_unlock(&calend_adjlock);
splx(s);
}
+
+void
+clock_wakeup_calendar(void)
+{
+ thread_call_enter(&calend_wakecall);
+}
+
+static void
+calend_dowakeup(
+ thread_call_param_t p0,
+ thread_call_param_t p1)
+{
+ void IOKitResetTime(void);
+
+ IOKitResetTime();
+}