+
+int64_t
+clock_set_calendar_adjtime(
+ int64_t total,
+ uint32_t delta)
+{
+ int64_t ototal;
+ 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);
+
+ timer_call_enter(&calend_adjcall, calend_adjdeadline);
+ }
+ else {
+ calend_adjtotal = 0;
+
+ timer_call_cancel(&calend_adjcall);
+ }
+
+ simple_unlock(&calend_adjlock);
+ splx(s);
+
+ return (ototal);
+}
+
+static void
+clock_calend_adjust(
+ timer_call_param_t p0,
+ timer_call_param_t p1)
+{
+ 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);
+
+ timer_call_enter(&calend_adjcall, calend_adjdeadline);
+ }
+
+ simple_unlock(&calend_adjlock);
+ splx(s);
+}