]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/clock.c
xnu-792.22.5.tar.gz
[apple/xnu.git] / osfmk / kern / clock.c
CommitLineData
1c79356b 1/*
4452a7af 2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
8f6c56a5
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31/*
1c79356b
A
32 */
33
91447636 34#include <mach/mach_types.h>
91447636 35
1c79356b 36#include <kern/lock.h>
1c79356b 37#include <kern/spl.h>
55e303ae 38#include <kern/sched_prim.h>
1c79356b 39#include <kern/thread.h>
1c79356b 40#include <kern/clock.h>
4452a7af
A
41#include <kern/host_notify.h>
42
43#include <IOKit/IOPlatformExpert.h>
c0fea474 44
4452a7af 45#include <machine/commpage.h>
1c79356b 46
91447636 47#include <mach/mach_traps.h>
1c79356b
A
48#include <mach/mach_time.h>
49
4452a7af 50decl_simple_lock_data(static,clock_lock)
91447636 51
1c79356b 52/*
4452a7af
A
53 * Time of day (calendar) variables.
54 *
55 * Algorithm:
56 *
57 * TOD <- (seconds + epoch, fraction) <- CONV(current absolute time + offset)
58 *
59 * where CONV converts absolute time units into seconds and a fraction.
1c79356b 60 */
4452a7af
A
61static struct clock_calend {
62 uint64_t epoch;
63 uint64_t offset;
64} clock_calend;
1c79356b 65
4452a7af
A
66/*
67 * Calendar adjustment variables and values.
68 */
69#define calend_adjperiod (NSEC_PER_SEC / 100) /* adjustment period, ns */
70#define calend_adjskew (40 * NSEC_PER_USEC) /* "standard" skew, ns / period */
71#define calend_adjbig (NSEC_PER_SEC) /* use 10x skew above adjbig ns */
72
73static uint64_t calend_adjstart; /* Absolute time value for start of this adjustment period */
74static uint32_t calend_adjoffset; /* Absolute time offset for this adjustment period as absolute value */
1c79356b 75
4452a7af
A
76static int32_t calend_adjdelta; /* Nanosecond time delta for this adjustment period */
77static int64_t calend_adjtotal; /* Nanosecond remaining total adjustment */
1c79356b 78
4452a7af
A
79static uint64_t calend_adjdeadline; /* Absolute time value for next adjustment period */
80static uint32_t calend_adjinterval; /* Absolute time interval of adjustment period */
9bccf70c
A
81
82static timer_call_data_t calend_adjcall;
4452a7af
A
83static uint32_t calend_adjactive;
84
85static uint32_t calend_set_adjustment(
86 int32_t *secs,
87 int32_t *microsecs);
88
89static void calend_adjust_call(void);
90static uint32_t calend_adjust(void);
9bccf70c 91
55e303ae
A
92static thread_call_data_t calend_wakecall;
93
4452a7af 94extern void IOKitResetTime(void);
5d5c5d0d 95
4452a7af 96static uint64_t clock_boottime; /* Seconds boottime epoch */
89b3af67 97
4452a7af
A
98#define TIME_ADD(rsecs, secs, rfrac, frac, unit) \
99MACRO_BEGIN \
100 if (((rfrac) += (frac)) >= (unit)) { \
101 (rfrac) -= (unit); \
102 (rsecs) += 1; \
103 } \
104 (rsecs) += (secs); \
105MACRO_END
106
107#define TIME_SUB(rsecs, secs, rfrac, frac, unit) \
108MACRO_BEGIN \
109 if ((int32_t)((rfrac) -= (frac)) < 0) { \
110 (rfrac) += (unit); \
111 (rsecs) -= 1; \
112 } \
113 (rsecs) -= (secs); \
114MACRO_END
1c79356b
A
115
116/*
91447636
A
117 * clock_config:
118 *
119 * Called once at boot to configure the clock subsystem.
1c79356b
A
120 */
121void
122clock_config(void)
123{
4452a7af 124 simple_lock_init(&clock_lock, 0);
55e303ae 125
4452a7af
A
126 timer_call_setup(&calend_adjcall, (timer_call_func_t)calend_adjust_call, NULL);
127 thread_call_setup(&calend_wakecall, (thread_call_func_t)IOKitResetTime, NULL);
8f6c56a5 128
4452a7af 129 clock_oldconfig();
1c79356b 130
91447636
A
131 /*
132 * Initialize the timer callouts.
133 */
134 timer_call_initialize();
1c79356b
A
135}
136
137/*
91447636
A
138 * clock_init:
139 *
140 * Called on a processor each time started.
1c79356b
A
141 */
142void
143clock_init(void)
144{
4452a7af 145 clock_oldinit();
1c79356b
A
146}
147
55e303ae 148/*
4452a7af
A
149 * clock_timebase_init:
150 *
151 * Called by machine dependent code
152 * to initialize areas dependent on the
153 * timebase value. May be called multiple
154 * times during start up.
55e303ae
A
155 */
156void
157clock_timebase_init(void)
158{
4452a7af 159 uint64_t abstime;
8f6c56a5 160
4452a7af
A
161 nanoseconds_to_absolutetime(calend_adjperiod, &abstime);
162 calend_adjinterval = abstime;
5d5c5d0d 163
4452a7af 164 sched_timebase_init();
1c79356b
A
165}
166
167/*
4452a7af
A
168 * mach_timebase_info_trap:
169 *
170 * User trap returns timebase constant.
1c79356b 171 */
21362eb3 172kern_return_t
4452a7af
A
173mach_timebase_info_trap(
174 struct mach_timebase_info_trap_args *args)
21362eb3 175{
4452a7af
A
176 mach_vm_address_t out_info_addr = args->info;
177 mach_timebase_info_data_t info;
21362eb3 178
4452a7af 179 clock_timebase_info(&info);
5d5c5d0d 180
4452a7af 181 copyout((void *)&info, out_info_addr, sizeof (info));
89b3af67 182
21362eb3 183 return (KERN_SUCCESS);
8ad349bb 184}
c0fea474 185
8ad349bb 186/*
4452a7af 187 * Calendar routines.
8ad349bb 188 */
89b3af67 189
21362eb3 190/*
4452a7af
A
191 * clock_get_calendar_microtime:
192 *
193 * Returns the current calendar value,
194 * microseconds as the fraction.
21362eb3 195 */
4452a7af
A
196void
197clock_get_calendar_microtime(
198 uint32_t *secs,
199 uint32_t *microsecs)
21362eb3 200{
4452a7af
A
201 uint64_t now;
202 spl_t s;
89b3af67 203
4452a7af
A
204 s = splclock();
205 simple_lock(&clock_lock);
89b3af67 206
4452a7af 207 now = mach_absolute_time();
89b3af67 208
4452a7af
A
209 if (calend_adjdelta < 0) {
210 uint32_t t32;
89b3af67 211
4452a7af
A
212 if (now > calend_adjstart) {
213 t32 = now - calend_adjstart;
214
215 if (t32 > calend_adjoffset)
216 now -= calend_adjoffset;
217 else
218 now = calend_adjstart;
219 }
220 }
221
222 now += clock_calend.offset;
223
224 absolutetime_to_microtime(now, secs, microsecs);
225
226 *secs += clock_calend.epoch;
227
228 simple_unlock(&clock_lock);
229 splx(s);
8f6c56a5 230}
5d5c5d0d 231
8f6c56a5 232/*
4452a7af
A
233 * clock_get_calendar_nanotime:
234 *
235 * Returns the current calendar value,
236 * nanoseconds as the fraction.
237 *
238 * Since we do not have an interface to
239 * set the calendar with resolution greater
240 * than a microsecond, we honor that here.
8f6c56a5 241 */
4452a7af
A
242void
243clock_get_calendar_nanotime(
244 uint32_t *secs,
245 uint32_t *nanosecs)
8f6c56a5 246{
4452a7af
A
247 uint64_t now;
248 spl_t s;
249
250 s = splclock();
251 simple_lock(&clock_lock);
252
253 now = mach_absolute_time();
254
255 if (calend_adjdelta < 0) {
256 uint32_t t32;
257
258 if (now > calend_adjstart) {
259 t32 = now - calend_adjstart;
260
261 if (t32 > calend_adjoffset)
262 now -= calend_adjoffset;
263 else
264 now = calend_adjstart;
265 }
266 }
267
268 now += clock_calend.offset;
269
270 absolutetime_to_microtime(now, secs, nanosecs);
271 *nanosecs *= NSEC_PER_USEC;
272
273 *secs += clock_calend.epoch;
274
275 simple_unlock(&clock_lock);
276 splx(s);
21362eb3 277}
89b3af67 278
21362eb3 279/*
4452a7af
A
280 * clock_gettimeofday:
281 *
282 * Kernel interface for commpage implementation of
283 * gettimeofday() syscall.
284 *
285 * Returns the current calendar value, and updates the
286 * commpage info as appropriate. Because most calls to
287 * gettimeofday() are handled in user mode by the commpage,
288 * this routine should be used infrequently.
21362eb3 289 */
4452a7af
A
290void
291clock_gettimeofday(
292 uint32_t *secs,
293 uint32_t *microsecs)
21362eb3 294{
4452a7af
A
295 uint64_t now;
296 spl_t s;
89b3af67 297
4452a7af
A
298 s = splclock();
299 simple_lock(&clock_lock);
300
301 now = mach_absolute_time();
302
303 if (calend_adjdelta >= 0) {
304 clock_gettimeofday_set_commpage(now, clock_calend.epoch, clock_calend.offset, secs, microsecs);
1c79356b 305 }
4452a7af
A
306 else {
307 uint32_t t32;
89b3af67 308
4452a7af
A
309 if (now > calend_adjstart) {
310 t32 = now - calend_adjstart;
311
312 if (t32 > calend_adjoffset)
313 now -= calend_adjoffset;
314 else
315 now = calend_adjstart;
316 }
317
318 now += clock_calend.offset;
89b3af67 319
4452a7af
A
320 absolutetime_to_microtime(now, secs, microsecs);
321
322 *secs += clock_calend.epoch;
1c79356b 323 }
1c79356b 324
4452a7af
A
325 simple_unlock(&clock_lock);
326 splx(s);
1c79356b
A
327}
328
329/*
4452a7af
A
330 * clock_set_calendar_microtime:
331 *
332 * Sets the current calendar value by
333 * recalculating the epoch and offset
334 * from the system clock.
335 *
336 * Also adjusts the boottime to keep the
337 * value consistent, writes the new
338 * calendar value to the platform clock,
339 * and sends calendar change notifications.
1c79356b 340 */
4452a7af
A
341void
342clock_set_calendar_microtime(
343 uint32_t secs,
344 uint32_t microsecs)
1c79356b 345{
4452a7af
A
346 uint32_t sys, microsys;
347 uint32_t newsecs;
348 spl_t s;
1c79356b 349
4452a7af
A
350 newsecs = (microsecs < 500*USEC_PER_SEC)?
351 secs: secs + 1;
352
353 s = splclock();
354 simple_lock(&clock_lock);
1c79356b 355
4452a7af 356 commpage_set_timestamp(0,0,0);
8ad349bb 357
5d5c5d0d 358 /*
4452a7af
A
359 * Calculate the new calendar epoch based on
360 * the new value and the system clock.
5d5c5d0d 361 */
4452a7af
A
362 clock_get_system_microtime(&sys, &microsys);
363 TIME_SUB(secs, sys, microsecs, microsys, USEC_PER_SEC);
8ad349bb 364
89b3af67 365 /*
4452a7af 366 * Adjust the boottime based on the delta.
89b3af67 367 */
4452a7af 368 clock_boottime += secs - clock_calend.epoch;
8f6c56a5 369
89b3af67 370 /*
4452a7af 371 * Set the new calendar epoch.
89b3af67 372 */
4452a7af
A
373 clock_calend.epoch = secs;
374 nanoseconds_to_absolutetime((uint64_t)microsecs * NSEC_PER_USEC, &clock_calend.offset);
8f6c56a5 375
4452a7af
A
376 /*
377 * Cancel any adjustment in progress.
378 */
379 calend_adjdelta = calend_adjtotal = 0;
8f6c56a5 380
4452a7af 381 simple_unlock(&clock_lock);
21362eb3 382
4452a7af
A
383 /*
384 * Set the new value for the platform clock.
385 */
386 PESetGMTTimeOfDay(newsecs);
21362eb3 387
4452a7af 388 splx(s);
21362eb3 389
4452a7af
A
390 /*
391 * Send host notifications.
392 */
393 host_notify_calendar_change();
1c79356b
A
394}
395
396/*
4452a7af
A
397 * clock_initialize_calendar:
398 *
399 * Set the calendar and related clocks
400 * from the platform clock at boot or
401 * wake event.
402 *
403 * Also sends host notifications.
1c79356b
A
404 */
405void
4452a7af 406clock_initialize_calendar(void)
1c79356b 407{
4452a7af
A
408 uint32_t sys, microsys;
409 uint32_t microsecs = 0, secs = PEGetGMTTimeOfDay();
410 spl_t s;
1c79356b 411
4452a7af
A
412 s = splclock();
413 simple_lock(&clock_lock);
1c79356b 414
4452a7af 415 commpage_set_timestamp(0,0,0);
1c79356b 416
4452a7af
A
417 if ((int32_t)secs >= (int32_t)clock_boottime) {
418 /*
419 * Initialize the boot time based on the platform clock.
420 */
421 if (clock_boottime == 0)
422 clock_boottime = secs;
1c79356b
A
423
424 /*
4452a7af
A
425 * Calculate the new calendar epoch based on
426 * the platform clock and the system clock.
427 */
428 clock_get_system_microtime(&sys, &microsys);
429 TIME_SUB(secs, sys, microsecs, microsys, USEC_PER_SEC);
1c79356b
A
430
431 /*
4452a7af 432 * Set the new calendar epoch.
1c79356b 433 */
4452a7af
A
434 clock_calend.epoch = secs;
435 nanoseconds_to_absolutetime((uint64_t)microsecs * NSEC_PER_USEC, &clock_calend.offset);
1c79356b 436
4452a7af
A
437 /*
438 * Cancel any adjustment in progress.
1c79356b 439 */
4452a7af 440 calend_adjdelta = calend_adjtotal = 0;
1c79356b
A
441 }
442
4452a7af
A
443 simple_unlock(&clock_lock);
444 splx(s);
445
1c79356b 446 /*
4452a7af 447 * Send host notifications.
1c79356b 448 */
4452a7af 449 host_notify_calendar_change();
1c79356b
A
450}
451
452/*
4452a7af
A
453 * clock_get_boottime_nanotime:
454 *
455 * Return the boottime, used by sysctl.
1c79356b 456 */
4452a7af
A
457void
458clock_get_boottime_nanotime(
459 uint32_t *secs,
460 uint32_t *nanosecs)
1c79356b 461{
4452a7af
A
462 *secs = clock_boottime;
463 *nanosecs = 0;
1c79356b
A
464}
465
466/*
4452a7af
A
467 * clock_adjtime:
468 *
469 * Interface to adjtime() syscall.
470 *
471 * Calculates adjustment variables and
472 * initiates adjustment.
21362eb3 473 */
1c79356b 474void
4452a7af
A
475clock_adjtime(
476 int32_t *secs,
477 int32_t *microsecs)
1c79356b 478{
4452a7af
A
479 uint32_t interval;
480 spl_t s;
1c79356b 481
4452a7af
A
482 s = splclock();
483 simple_lock(&clock_lock);
1c79356b 484
4452a7af
A
485 interval = calend_set_adjustment(secs, microsecs);
486 if (interval != 0) {
487 calend_adjdeadline = mach_absolute_time() + interval;
488 if (!timer_call_enter(&calend_adjcall, calend_adjdeadline))
489 calend_adjactive++;
1c79356b 490 }
4452a7af
A
491 else
492 if (timer_call_cancel(&calend_adjcall))
493 calend_adjactive--;
494
495 simple_unlock(&clock_lock);
496 splx(s);
1c79356b
A
497}
498
4452a7af
A
499static uint32_t
500calend_set_adjustment(
501 int32_t *secs,
502 int32_t *microsecs)
1c79356b 503{
4452a7af
A
504 uint64_t now, t64;
505 int64_t total, ototal;
506 uint32_t interval = 0;
1c79356b 507
4452a7af 508 total = (int64_t)*secs * NSEC_PER_SEC + *microsecs * NSEC_PER_USEC;
1c79356b 509
4452a7af 510 commpage_set_timestamp(0,0,0);
1c79356b 511
4452a7af 512 now = mach_absolute_time();
1c79356b 513
4452a7af 514 ototal = calend_adjtotal;
1c79356b 515
4452a7af
A
516 if (total != 0) {
517 int32_t delta = calend_adjskew;
1c79356b 518
4452a7af
A
519 if (total > 0) {
520 if (total > calend_adjbig)
521 delta *= 10;
522 if (delta > total)
523 delta = total;
1c79356b 524
4452a7af
A
525 nanoseconds_to_absolutetime((uint64_t)delta, &t64);
526 calend_adjoffset = t64;
527 }
528 else {
529 if (total < -calend_adjbig)
530 delta *= 10;
531 delta = -delta;
532 if (delta < total)
533 delta = total;
c0fea474 534
4452a7af 535 calend_adjstart = now;
5d5c5d0d 536
4452a7af
A
537 nanoseconds_to_absolutetime((uint64_t)-delta, &t64);
538 calend_adjoffset = t64;
539 }
89b3af67 540
4452a7af
A
541 calend_adjtotal = total;
542 calend_adjdelta = delta;
543
544 interval = calend_adjinterval;
545 }
546 else
547 calend_adjdelta = calend_adjtotal = 0;
1c79356b 548
4452a7af
A
549 if (ototal != 0) {
550 *secs = ototal / NSEC_PER_SEC;
551 *microsecs = (ototal % NSEC_PER_SEC) / NSEC_PER_USEC;
552 }
553 else
554 *secs = *microsecs = 0;
1c79356b 555
4452a7af 556 return (interval);
1c79356b
A
557}
558
4452a7af
A
559static void
560calend_adjust_call(void)
1c79356b 561{
4452a7af
A
562 uint32_t interval;
563 spl_t s;
1c79356b 564
4452a7af
A
565 s = splclock();
566 simple_lock(&clock_lock);
1c79356b 567
4452a7af
A
568 if (--calend_adjactive == 0) {
569 interval = calend_adjust();
570 if (interval != 0) {
571 clock_deadline_for_periodic_event(interval, mach_absolute_time(),
572 &calend_adjdeadline);
1c79356b 573
4452a7af
A
574 if (!timer_call_enter(&calend_adjcall, calend_adjdeadline))
575 calend_adjactive++;
576 }
1c79356b 577 }
4452a7af
A
578
579 simple_unlock(&clock_lock);
580 splx(s);
1c79356b
A
581}
582
4452a7af
A
583static uint32_t
584calend_adjust(void)
1c79356b 585{
4452a7af
A
586 uint64_t now, t64;
587 int32_t delta;
588 uint32_t interval = 0;
5d5c5d0d 589
4452a7af 590 commpage_set_timestamp(0,0,0);
5d5c5d0d 591
4452a7af 592 now = mach_absolute_time();
5d5c5d0d 593
4452a7af 594 delta = calend_adjdelta;
5d5c5d0d 595
4452a7af
A
596 if (delta > 0) {
597 clock_calend.offset += calend_adjoffset;
89b3af67 598
4452a7af
A
599 calend_adjtotal -= delta;
600 if (delta > calend_adjtotal) {
601 calend_adjdelta = delta = calend_adjtotal;
89b3af67 602
4452a7af
A
603 nanoseconds_to_absolutetime((uint64_t)delta, &t64);
604 calend_adjoffset = t64;
605 }
606 }
607 else
608 if (delta < 0) {
609 clock_calend.offset -= calend_adjoffset;
89b3af67 610
4452a7af
A
611 calend_adjtotal -= delta;
612 if (delta < calend_adjtotal) {
613 calend_adjdelta = delta = calend_adjtotal;
89b3af67 614
4452a7af
A
615 nanoseconds_to_absolutetime((uint64_t)-delta, &t64);
616 calend_adjoffset = t64;
617 }
618
619 if (calend_adjdelta != 0)
620 calend_adjstart = now;
621 }
622
623 if (calend_adjdelta != 0)
624 interval = calend_adjinterval;
625
626 return (interval);
627}
628
629/*
630 * clock_wakeup_calendar:
631 *
632 * Interface to power management, used
633 * to initiate the reset of the calendar
634 * on wake from sleep event.
635 */
636void
637clock_wakeup_calendar(void)
638{
639 thread_call_enter(&calend_wakecall);
1c79356b
A
640}
641
4452a7af
A
642/*
643 * Wait / delay routines.
644 */
91447636
A
645static void
646mach_wait_until_continue(
647 __unused void *parameter,
648 wait_result_t wresult)
649{
650 thread_syscall_return((wresult == THREAD_INTERRUPTED)? KERN_ABORTED: KERN_SUCCESS);
651 /*NOTREACHED*/
652}
653
1c79356b 654kern_return_t
91447636
A
655mach_wait_until_trap(
656 struct mach_wait_until_trap_args *args)
657{
658 uint64_t deadline = args->deadline;
659 wait_result_t wresult;
660
661 wresult = assert_wait_deadline((event_t)mach_wait_until_trap, THREAD_ABORTSAFE, deadline);
662 if (wresult == THREAD_WAITING)
663 wresult = thread_block(mach_wait_until_continue);
664
665 return ((wresult == THREAD_INTERRUPTED)? KERN_ABORTED: KERN_SUCCESS);
666}
667
91447636
A
668void
669clock_delay_until(
1c79356b
A
670 uint64_t deadline)
671{
91447636
A
672 uint64_t now = mach_absolute_time();
673
674 if (now >= deadline)
675 return;
1c79356b 676
91447636
A
677 if ( (deadline - now) < (8 * sched_cswtime) ||
678 get_preemption_level() != 0 ||
679 ml_get_interrupts_enabled() == FALSE )
680 machine_delay_until(deadline);
681 else {
682 assert_wait_deadline((event_t)clock_delay_until, THREAD_UNINT, deadline - sched_cswtime);
683
684 thread_block(THREAD_CONTINUE_NULL);
9bccf70c 685 }
91447636 686}
1c79356b 687
91447636
A
688void
689delay_for_interval(
690 uint32_t interval,
691 uint32_t scale_factor)
692{
693 uint64_t end;
694
695 clock_interval_to_deadline(interval, scale_factor, &end);
696
697 clock_delay_until(end);
698}
699
700void
701delay(
702 int usec)
703{
704 delay_for_interval((usec < 0)? -usec: usec, NSEC_PER_USEC);
1c79356b 705}
9bccf70c 706
4452a7af
A
707/*
708 * Miscellaneous routines.
709 */
55e303ae 710void
4452a7af
A
711clock_interval_to_deadline(
712 uint32_t interval,
713 uint32_t scale_factor,
714 uint64_t *result)
9bccf70c 715{
4452a7af 716 uint64_t abstime;
55e303ae 717
4452a7af 718 clock_interval_to_absolutetime_interval(interval, scale_factor, &abstime);
21362eb3 719
4452a7af 720 *result = mach_absolute_time() + abstime;
8ad349bb 721}
c0fea474 722
4452a7af
A
723void
724clock_absolutetime_interval_to_deadline(
725 uint64_t abstime,
726 uint64_t *result)
8ad349bb 727{
4452a7af 728 *result = mach_absolute_time() + abstime;
8f6c56a5 729}
5d5c5d0d 730
89b3af67 731void
4452a7af
A
732clock_get_uptime(
733 uint64_t *result)
8f6c56a5 734{
4452a7af 735 *result = mach_absolute_time();
21362eb3 736}
89b3af67 737
4452a7af
A
738void
739clock_deadline_for_periodic_event(
740 uint64_t interval,
741 uint64_t abstime,
742 uint64_t *deadline)
21362eb3 743{
4452a7af
A
744 assert(interval != 0);
745
746 *deadline += interval;
747
748 if (*deadline <= abstime) {
749 *deadline = abstime + interval;
750 abstime = mach_absolute_time();
55e303ae 751
4452a7af
A
752 if (*deadline <= abstime)
753 *deadline = abstime + interval;
754 }
55e303ae 755}