]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/clock_oldops.c
xnu-792.25.20.tar.gz
[apple/xnu.git] / osfmk / kern / clock_oldops.c
CommitLineData
0c530ab8
A
1/*
2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * @OSF_COPYRIGHT@
24 */
25/*
26 * DEPRECATED INTERFACES - Should be removed
27 *
28 * Purpose: Routines for the creation and use of kernel
29 * alarm clock services. This file and the ipc
30 * routines in kern/ipc_clock.c constitute the
31 * machine-independent clock service layer.
32 */
33
34#include <mach/mach_types.h>
35
36#include <kern/lock.h>
37#include <kern/host.h>
38#include <kern/spl.h>
39#include <kern/sched_prim.h>
40#include <kern/thread.h>
41#include <kern/ipc_host.h>
42#include <kern/clock.h>
43#include <kern/zalloc.h>
44
45#include <ipc/ipc_types.h>
46#include <ipc/ipc_port.h>
47
48#include <mach/mach_traps.h>
49#include <mach/mach_time.h>
50
51#include <mach/clock_server.h>
52#include <mach/clock_reply.h>
53#include <mach/clock_priv_server.h>
54
55#include <mach/mach_host_server.h>
56#include <mach/host_priv_server.h>
57
58/*
59 * Actual clock alarm structure. Used for user clock_sleep() and
60 * clock_alarm() calls. Alarms are allocated from the alarm free
61 * list and entered in time priority order into the active alarm
62 * chain of the target clock.
63 */
64struct alarm {
65 struct alarm *al_next; /* next alarm in chain */
66 struct alarm *al_prev; /* previous alarm in chain */
67 int al_status; /* alarm status */
68 mach_timespec_t al_time; /* alarm time */
69 struct { /* message alarm data */
70 int type; /* alarm type */
71 ipc_port_t port; /* alarm port */
72 mach_msg_type_name_t
73 port_type; /* alarm port type */
74 struct clock *clock; /* alarm clock */
75 void *data; /* alarm data */
76 } al_alrm;
77#define al_type al_alrm.type
78#define al_port al_alrm.port
79#define al_port_type al_alrm.port_type
80#define al_clock al_alrm.clock
81#define al_data al_alrm.data
82 long al_seqno; /* alarm sequence number */
83};
84typedef struct alarm alarm_data_t;
85
86/* alarm status */
87#define ALARM_FREE 0 /* alarm is on free list */
88#define ALARM_SLEEP 1 /* active clock_sleep() */
89#define ALARM_CLOCK 2 /* active clock_alarm() */
90#define ALARM_DONE 4 /* alarm has expired */
91
92/* local data declarations */
93decl_simple_lock_data(static,alarm_lock) /* alarm synchronization */
94static struct zone *alarm_zone; /* zone for user alarms */
95static struct alarm *alrmfree; /* alarm free list pointer */
96static struct alarm *alrmdone; /* alarm done list pointer */
97static struct alarm *alrmlist;
98static long alrm_seqno; /* uniquely identifies alarms */
99static thread_call_data_t alarm_done_call;
100static timer_call_data_t alarm_expire_timer;
101
102extern struct clock clock_list[];
103extern int clock_count;
104
105static void post_alarm(
106 alarm_t alarm);
107
108static void set_alarm(
109 mach_timespec_t *alarm_time);
110
111static int check_time(
112 alarm_type_t alarm_type,
113 mach_timespec_t *alarm_time,
114 mach_timespec_t *clock_time);
115
116static void alarm_done(void);
117
118static void alarm_expire(void);
119
120static kern_return_t clock_sleep_internal(
121 clock_t clock,
122 sleep_type_t sleep_type,
123 mach_timespec_t *sleep_time);
124
125int rtclock_config(void);
126
127int rtclock_init(void);
128
129kern_return_t rtclock_gettime(
130 mach_timespec_t *cur_time);
131
132kern_return_t rtclock_getattr(
133 clock_flavor_t flavor,
134 clock_attr_t attr,
135 mach_msg_type_number_t *count);
136
137struct clock_ops sysclk_ops = {
138 rtclock_config, rtclock_init,
139 rtclock_gettime,
140 rtclock_getattr,
141};
142
143kern_return_t calend_gettime(
144 mach_timespec_t *cur_time);
145
146kern_return_t calend_getattr(
147 clock_flavor_t flavor,
148 clock_attr_t attr,
149 mach_msg_type_number_t *count);
150
151struct clock_ops calend_ops = {
152 0, 0,
153 calend_gettime,
154 calend_getattr,
155};
156
157/*
158 * Macros to lock/unlock clock system.
159 */
160#define LOCK_ALARM(s) \
161 s = splclock(); \
162 simple_lock(&alarm_lock);
163
164#define UNLOCK_ALARM(s) \
165 simple_unlock(&alarm_lock); \
166 splx(s);
167
168void
169clock_oldconfig(void)
170{
171 clock_t clock;
172 register int i;
173
174 simple_lock_init(&alarm_lock, 0);
175 thread_call_setup(&alarm_done_call, (thread_call_func_t)alarm_done, NULL);
176 timer_call_setup(&alarm_expire_timer, (timer_call_func_t)alarm_expire, NULL);
177
178 /*
179 * Configure clock devices.
180 */
181 for (i = 0; i < clock_count; i++) {
182 clock = &clock_list[i];
183 if (clock->cl_ops && clock->cl_ops->c_config) {
184 if ((*clock->cl_ops->c_config)() == 0)
185 clock->cl_ops = 0;
186 }
187 }
188
189 /* start alarm sequence numbers at 0 */
190 alrm_seqno = 0;
191}
192
193void
194clock_oldinit(void)
195{
196 clock_t clock;
197 register int i;
198
199 /*
200 * Initialize basic clock structures.
201 */
202 for (i = 0; i < clock_count; i++) {
203 clock = &clock_list[i];
204 if (clock->cl_ops && clock->cl_ops->c_init)
205 (*clock->cl_ops->c_init)();
206 }
207}
208
209/*
210 * Initialize the clock ipc service facility.
211 */
212void
213clock_service_create(void)
214{
215 clock_t clock;
216 register int i;
217
218 /*
219 * Initialize ipc clock services.
220 */
221 for (i = 0; i < clock_count; i++) {
222 clock = &clock_list[i];
223 if (clock->cl_ops) {
224 ipc_clock_init(clock);
225 ipc_clock_enable(clock);
226 }
227 }
228
229 /*
230 * Perform miscellaneous late
231 * initialization.
232 */
233 i = sizeof(struct alarm);
234 alarm_zone = zinit(i, (4096/i)*i, 10*i, "alarms");
235}
236
237/*
238 * Get the service port on a clock.
239 */
240kern_return_t
241host_get_clock_service(
242 host_t host,
243 clock_id_t clock_id,
244 clock_t *clock) /* OUT */
245{
246 if (host == HOST_NULL || clock_id < 0 || clock_id >= clock_count) {
247 *clock = CLOCK_NULL;
248 return (KERN_INVALID_ARGUMENT);
249 }
250
251 *clock = &clock_list[clock_id];
252 if ((*clock)->cl_ops == 0)
253 return (KERN_FAILURE);
254 return (KERN_SUCCESS);
255}
256
257/*
258 * Get the control port on a clock.
259 */
260kern_return_t
261host_get_clock_control(
262 host_priv_t host_priv,
263 clock_id_t clock_id,
264 clock_t *clock) /* OUT */
265{
266 if (host_priv == HOST_PRIV_NULL ||
267 clock_id < 0 || clock_id >= clock_count) {
268 *clock = CLOCK_NULL;
269 return (KERN_INVALID_ARGUMENT);
270 }
271
272 *clock = &clock_list[clock_id];
273 if ((*clock)->cl_ops == 0)
274 return (KERN_FAILURE);
275 return (KERN_SUCCESS);
276}
277
278/*
279 * Get the current clock time.
280 */
281kern_return_t
282clock_get_time(
283 clock_t clock,
284 mach_timespec_t *cur_time) /* OUT */
285{
286 if (clock == CLOCK_NULL)
287 return (KERN_INVALID_ARGUMENT);
288 return ((*clock->cl_ops->c_gettime)(cur_time));
289}
290
291kern_return_t
292rtclock_gettime(
293 mach_timespec_t *time) /* OUT */
294{
295 clock_get_system_nanotime(&time->tv_sec, (uint32_t *)&time->tv_nsec);
296
297 return (KERN_SUCCESS);
298}
299
300kern_return_t
301calend_gettime(
302 mach_timespec_t *time) /* OUT */
303{
304 clock_get_calendar_nanotime(&time->tv_sec, (uint32_t *)&time->tv_nsec);
305
306 return (KERN_SUCCESS);
307}
308
309/*
310 * Get clock attributes.
311 */
312kern_return_t
313clock_get_attributes(
314 clock_t clock,
315 clock_flavor_t flavor,
316 clock_attr_t attr, /* OUT */
317 mach_msg_type_number_t *count) /* IN/OUT */
318{
319 if (clock == CLOCK_NULL)
320 return (KERN_INVALID_ARGUMENT);
321 if (clock->cl_ops->c_getattr)
322 return (clock->cl_ops->c_getattr(flavor, attr, count));
323 return (KERN_FAILURE);
324}
325
326kern_return_t
327rtclock_getattr(
328 clock_flavor_t flavor,
329 clock_attr_t attr, /* OUT */
330 mach_msg_type_number_t *count) /* IN/OUT */
331{
332 if (*count != 1)
333 return (KERN_FAILURE);
334
335 switch (flavor) {
336
337 case CLOCK_GET_TIME_RES: /* >0 res */
338 case CLOCK_ALARM_CURRES: /* =0 no alarm */
339 case CLOCK_ALARM_MINRES:
340 case CLOCK_ALARM_MAXRES:
341 *(clock_res_t *) attr = NSEC_PER_SEC / 100;
342 break;
343
344 default:
345 return (KERN_INVALID_VALUE);
346 }
347
348 return (KERN_SUCCESS);
349}
350
351kern_return_t
352calend_getattr(
353 clock_flavor_t flavor,
354 clock_attr_t attr, /* OUT */
355 mach_msg_type_number_t *count) /* IN/OUT */
356{
357 if (*count != 1)
358 return (KERN_FAILURE);
359
360 switch (flavor) {
361
362 case CLOCK_GET_TIME_RES: /* >0 res */
363 *(clock_res_t *) attr = NSEC_PER_SEC / 100;
364 break;
365
366 case CLOCK_ALARM_CURRES: /* =0 no alarm */
367 case CLOCK_ALARM_MINRES:
368 case CLOCK_ALARM_MAXRES:
369 *(clock_res_t *) attr = 0;
370 break;
371
372 default:
373 return (KERN_INVALID_VALUE);
374 }
375
376 return (KERN_SUCCESS);
377}
378
379/*
380 * Set the current clock time.
381 */
382kern_return_t
383clock_set_time(
384 clock_t clock,
385__unused mach_timespec_t new_time)
386{
387 if (clock == CLOCK_NULL)
388 return (KERN_INVALID_ARGUMENT);
389 return (KERN_FAILURE);
390}
391
392/*
393 * Set the clock alarm resolution.
394 */
395kern_return_t
396clock_set_attributes(
397 clock_t clock,
398__unused clock_flavor_t flavor,
399__unused clock_attr_t attr,
400__unused mach_msg_type_number_t count)
401{
402 if (clock == CLOCK_NULL)
403 return (KERN_INVALID_ARGUMENT);
404 return (KERN_FAILURE);
405}
406
407/*
408 * Setup a clock alarm.
409 */
410kern_return_t
411clock_alarm(
412 clock_t clock,
413 alarm_type_t alarm_type,
414 mach_timespec_t alarm_time,
415 ipc_port_t alarm_port,
416 mach_msg_type_name_t alarm_port_type)
417{
418 alarm_t alarm;
419 mach_timespec_t clock_time;
420 int chkstat;
421 kern_return_t reply_code;
422 spl_t s;
423
424 if (clock == CLOCK_NULL)
425 return (KERN_INVALID_ARGUMENT);
426 if (clock != &clock_list[SYSTEM_CLOCK])
427 return (KERN_FAILURE);
428 if (IP_VALID(alarm_port) == 0)
429 return (KERN_INVALID_CAPABILITY);
430
431 /*
432 * Check alarm parameters. If parameters are invalid,
433 * send alarm message immediately.
434 */
435 (*clock->cl_ops->c_gettime)(&clock_time);
436 chkstat = check_time(alarm_type, &alarm_time, &clock_time);
437 if (chkstat <= 0) {
438 reply_code = (chkstat < 0 ? KERN_INVALID_VALUE : KERN_SUCCESS);
439 clock_alarm_reply(alarm_port, alarm_port_type,
440 reply_code, alarm_type, clock_time);
441 return (KERN_SUCCESS);
442 }
443
444 /*
445 * Get alarm and add to clock alarm list.
446 */
447
448 LOCK_ALARM(s);
449 if ((alarm = alrmfree) == 0) {
450 UNLOCK_ALARM(s);
451 alarm = (alarm_t) zalloc(alarm_zone);
452 if (alarm == 0)
453 return (KERN_RESOURCE_SHORTAGE);
454 LOCK_ALARM(s);
455 }
456 else
457 alrmfree = alarm->al_next;
458
459 alarm->al_status = ALARM_CLOCK;
460 alarm->al_time = alarm_time;
461 alarm->al_type = alarm_type;
462 alarm->al_port = alarm_port;
463 alarm->al_port_type = alarm_port_type;
464 alarm->al_clock = clock;
465 alarm->al_seqno = alrm_seqno++;
466 post_alarm(alarm);
467 UNLOCK_ALARM(s);
468
469 return (KERN_SUCCESS);
470}
471
472/*
473 * Sleep on a clock. System trap. User-level libmach clock_sleep
474 * interface call takes a mach_timespec_t sleep_time argument which it
475 * converts to sleep_sec and sleep_nsec arguments which are then
476 * passed to clock_sleep_trap.
477 */
478kern_return_t
479clock_sleep_trap(
480 struct clock_sleep_trap_args *args)
481{
482 mach_port_name_t clock_name = args->clock_name;
483 sleep_type_t sleep_type = args->sleep_type;
484 int sleep_sec = args->sleep_sec;
485 int sleep_nsec = args->sleep_nsec;
486 mach_vm_address_t wakeup_time_addr = args->wakeup_time;
487 clock_t clock;
488 mach_timespec_t swtime;
489 kern_return_t rvalue;
490
491 /*
492 * Convert the trap parameters.
493 */
494 if (clock_name == MACH_PORT_NULL)
495 clock = &clock_list[SYSTEM_CLOCK];
496 else
497 clock = port_name_to_clock(clock_name);
498
499 swtime.tv_sec = sleep_sec;
500 swtime.tv_nsec = sleep_nsec;
501
502 /*
503 * Call the actual clock_sleep routine.
504 */
505 rvalue = clock_sleep_internal(clock, sleep_type, &swtime);
506
507 /*
508 * Return current time as wakeup time.
509 */
510 if (rvalue != KERN_INVALID_ARGUMENT && rvalue != KERN_FAILURE) {
511 copyout((char *)&swtime, wakeup_time_addr, sizeof(mach_timespec_t));
512 }
513 return (rvalue);
514}
515
516static kern_return_t
517clock_sleep_internal(
518 clock_t clock,
519 sleep_type_t sleep_type,
520 mach_timespec_t *sleep_time)
521{
522 alarm_t alarm;
523 mach_timespec_t clock_time;
524 kern_return_t rvalue;
525 int chkstat;
526 spl_t s;
527
528 if (clock == CLOCK_NULL)
529 return (KERN_INVALID_ARGUMENT);
530
531 if (clock != &clock_list[SYSTEM_CLOCK])
532 return (KERN_FAILURE);
533
534 /*
535 * Check sleep parameters. If parameters are invalid
536 * return an error, otherwise post alarm request.
537 */
538 (*clock->cl_ops->c_gettime)(&clock_time);
539
540 chkstat = check_time(sleep_type, sleep_time, &clock_time);
541 if (chkstat < 0)
542 return (KERN_INVALID_VALUE);
543 rvalue = KERN_SUCCESS;
544 if (chkstat > 0) {
545 wait_result_t wait_result;
546
547 /*
548 * Get alarm and add to clock alarm list.
549 */
550
551 LOCK_ALARM(s);
552 if ((alarm = alrmfree) == 0) {
553 UNLOCK_ALARM(s);
554 alarm = (alarm_t) zalloc(alarm_zone);
555 if (alarm == 0)
556 return (KERN_RESOURCE_SHORTAGE);
557 LOCK_ALARM(s);
558 }
559 else
560 alrmfree = alarm->al_next;
561
562 /*
563 * Wait for alarm to occur.
564 */
565 wait_result = assert_wait((event_t)alarm, THREAD_ABORTSAFE);
566 if (wait_result == THREAD_WAITING) {
567 alarm->al_time = *sleep_time;
568 alarm->al_status = ALARM_SLEEP;
569 post_alarm(alarm);
570 UNLOCK_ALARM(s);
571
572 wait_result = thread_block(THREAD_CONTINUE_NULL);
573
574 /*
575 * Note if alarm expired normally or whether it
576 * was aborted. If aborted, delete alarm from
577 * clock alarm list. Return alarm to free list.
578 */
579 LOCK_ALARM(s);
580 if (alarm->al_status != ALARM_DONE) {
581 assert(wait_result != THREAD_AWAKENED);
582 if (((alarm->al_prev)->al_next = alarm->al_next) != NULL)
583 (alarm->al_next)->al_prev = alarm->al_prev;
584 rvalue = KERN_ABORTED;
585 }
586 *sleep_time = alarm->al_time;
587 alarm->al_status = ALARM_FREE;
588 } else {
589 assert(wait_result == THREAD_INTERRUPTED);
590 assert(alarm->al_status == ALARM_FREE);
591 rvalue = KERN_ABORTED;
592 }
593 alarm->al_next = alrmfree;
594 alrmfree = alarm;
595 UNLOCK_ALARM(s);
596 }
597 else
598 *sleep_time = clock_time;
599
600 return (rvalue);
601}
602
603/*
604 * Service clock alarm expirations.
605 */
606static void
607alarm_expire(void)
608{
609 clock_t clock;
610 register alarm_t alrm1;
611 register alarm_t alrm2;
612 mach_timespec_t clock_time;
613 mach_timespec_t *alarm_time;
614 spl_t s;
615
616 clock = &clock_list[SYSTEM_CLOCK];
617 (*clock->cl_ops->c_gettime)(&clock_time);
618
619 /*
620 * Update clock alarm list. Alarms that are due are moved
621 * to the alarmdone list to be serviced by a thread callout.
622 */
623 LOCK_ALARM(s);
624 alrm1 = (alarm_t)&alrmlist;
625 while ((alrm2 = alrm1->al_next) != NULL) {
626 alarm_time = &alrm2->al_time;
627 if (CMP_MACH_TIMESPEC(alarm_time, &clock_time) > 0)
628 break;
629
630 /*
631 * Alarm has expired, so remove it from the
632 * clock alarm list.
633 */
634 if ((alrm1->al_next = alrm2->al_next) != NULL)
635 (alrm1->al_next)->al_prev = alrm1;
636
637 /*
638 * If a clock_sleep() alarm, wakeup the thread
639 * which issued the clock_sleep() call.
640 */
641 if (alrm2->al_status == ALARM_SLEEP) {
642 alrm2->al_next = 0;
643 alrm2->al_status = ALARM_DONE;
644 alrm2->al_time = clock_time;
645 thread_wakeup((event_t)alrm2);
646 }
647
648 /*
649 * If a clock_alarm() alarm, place the alarm on
650 * the alarm done list and schedule the alarm
651 * delivery mechanism.
652 */
653 else {
654 assert(alrm2->al_status == ALARM_CLOCK);
655 if ((alrm2->al_next = alrmdone) != NULL)
656 alrmdone->al_prev = alrm2;
657 else
658 thread_call_enter(&alarm_done_call);
659 alrm2->al_prev = (alarm_t)&alrmdone;
660 alrmdone = alrm2;
661 alrm2->al_status = ALARM_DONE;
662 alrm2->al_time = clock_time;
663 }
664 }
665
666 /*
667 * Setup to expire for the next pending alarm.
668 */
669 if (alrm2)
670 set_alarm(alarm_time);
671 UNLOCK_ALARM(s);
672}
673
674static void
675alarm_done(void)
676{
677 register alarm_t alrm;
678 kern_return_t code;
679 spl_t s;
680
681 LOCK_ALARM(s);
682 while ((alrm = alrmdone) != NULL) {
683 if ((alrmdone = alrm->al_next) != NULL)
684 alrmdone->al_prev = (alarm_t)&alrmdone;
685 UNLOCK_ALARM(s);
686
687 code = (alrm->al_status == ALARM_DONE? KERN_SUCCESS: KERN_ABORTED);
688 if (alrm->al_port != IP_NULL) {
689 /* Deliver message to designated port */
690 if (IP_VALID(alrm->al_port)) {
691 clock_alarm_reply(alrm->al_port, alrm->al_port_type, code,
692 alrm->al_type, alrm->al_time);
693 }
694
695 LOCK_ALARM(s);
696 alrm->al_status = ALARM_FREE;
697 alrm->al_next = alrmfree;
698 alrmfree = alrm;
699 }
700 else
701 panic("clock_alarm_deliver");
702 }
703
704 UNLOCK_ALARM(s);
705}
706
707/*
708 * Post an alarm on the active alarm list.
709 *
710 * Always called from within a LOCK_ALARM() code section.
711 */
712static void
713post_alarm(
714 alarm_t alarm)
715{
716 register alarm_t alrm1, alrm2;
717 mach_timespec_t *alarm_time;
718 mach_timespec_t *queue_time;
719
720 /*
721 * Traverse alarm list until queue time is greater
722 * than alarm time, then insert alarm.
723 */
724 alarm_time = &alarm->al_time;
725 alrm1 = (alarm_t)&alrmlist;
726 while ((alrm2 = alrm1->al_next) != NULL) {
727 queue_time = &alrm2->al_time;
728 if (CMP_MACH_TIMESPEC(queue_time, alarm_time) > 0)
729 break;
730 alrm1 = alrm2;
731 }
732 alrm1->al_next = alarm;
733 alarm->al_next = alrm2;
734 alarm->al_prev = alrm1;
735 if (alrm2)
736 alrm2->al_prev = alarm;
737
738 /*
739 * If the inserted alarm is the 'earliest' alarm,
740 * reset the device layer alarm time accordingly.
741 */
742 if (alrmlist == alarm)
743 set_alarm(alarm_time);
744}
745
746static void
747set_alarm(
748 mach_timespec_t *alarm_time)
749{
750 uint64_t abstime;
751
752 nanotime_to_absolutetime(alarm_time->tv_sec, alarm_time->tv_nsec, &abstime);
753 timer_call_enter(&alarm_expire_timer, abstime);
754}
755
756/*
757 * Check the validity of 'alarm_time' and 'alarm_type'. If either
758 * argument is invalid, return a negative value. If the 'alarm_time'
759 * is now, return a 0 value. If the 'alarm_time' is in the future,
760 * return a positive value.
761 */
762static int
763check_time(
764 alarm_type_t alarm_type,
765 mach_timespec_t *alarm_time,
766 mach_timespec_t *clock_time)
767{
768 int result;
769
770 if (BAD_ALRMTYPE(alarm_type))
771 return (-1);
772 if (BAD_MACH_TIMESPEC(alarm_time))
773 return (-1);
774 if ((alarm_type & ALRMTYPE) == TIME_RELATIVE)
775 ADD_MACH_TIMESPEC(alarm_time, clock_time);
776
777 result = CMP_MACH_TIMESPEC(alarm_time, clock_time);
778
779 return ((result >= 0)? result: 0);
780}
781
782mach_timespec_t
783clock_get_system_value(void)
784{
785 clock_t clock = &clock_list[SYSTEM_CLOCK];
786 mach_timespec_t value;
787
788 (void) (*clock->cl_ops->c_gettime)(&value);
789
790 return value;
791}
792
793mach_timespec_t
794clock_get_calendar_value(void)
795{
796 clock_t clock = &clock_list[CALENDAR_CLOCK];
797 mach_timespec_t value = MACH_TIMESPEC_ZERO;
798
799 (void) (*clock->cl_ops->c_gettime)(&value);
800
801 return value;
802}