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