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