]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/clock_oldops.c
xnu-792.25.20.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_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 */
64 struct 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 };
84 typedef 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 */
93 decl_simple_lock_data(static,alarm_lock) /* alarm synchronization */
94 static struct zone *alarm_zone; /* zone for user alarms */
95 static struct alarm *alrmfree; /* alarm free list pointer */
96 static struct alarm *alrmdone; /* alarm done list pointer */
97 static struct alarm *alrmlist;
98 static long alrm_seqno; /* uniquely identifies alarms */
99 static thread_call_data_t alarm_done_call;
100 static timer_call_data_t alarm_expire_timer;
101
102 extern struct clock clock_list[];
103 extern int clock_count;
104
105 static void post_alarm(
106 alarm_t alarm);
107
108 static void set_alarm(
109 mach_timespec_t *alarm_time);
110
111 static int check_time(
112 alarm_type_t alarm_type,
113 mach_timespec_t *alarm_time,
114 mach_timespec_t *clock_time);
115
116 static void alarm_done(void);
117
118 static void alarm_expire(void);
119
120 static kern_return_t clock_sleep_internal(
121 clock_t clock,
122 sleep_type_t sleep_type,
123 mach_timespec_t *sleep_time);
124
125 int rtclock_config(void);
126
127 int rtclock_init(void);
128
129 kern_return_t rtclock_gettime(
130 mach_timespec_t *cur_time);
131
132 kern_return_t rtclock_getattr(
133 clock_flavor_t flavor,
134 clock_attr_t attr,
135 mach_msg_type_number_t *count);
136
137 struct clock_ops sysclk_ops = {
138 rtclock_config, rtclock_init,
139 rtclock_gettime,
140 rtclock_getattr,
141 };
142
143 kern_return_t calend_gettime(
144 mach_timespec_t *cur_time);
145
146 kern_return_t calend_getattr(
147 clock_flavor_t flavor,
148 clock_attr_t attr,
149 mach_msg_type_number_t *count);
150
151 struct 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
168 void
169 clock_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
193 void
194 clock_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 */
212 void
213 clock_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 */
240 kern_return_t
241 host_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 */
260 kern_return_t
261 host_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 */
281 kern_return_t
282 clock_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
291 kern_return_t
292 rtclock_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
300 kern_return_t
301 calend_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 */
312 kern_return_t
313 clock_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
326 kern_return_t
327 rtclock_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
351 kern_return_t
352 calend_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 */
382 kern_return_t
383 clock_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 */
395 kern_return_t
396 clock_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 */
410 kern_return_t
411 clock_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 */
478 kern_return_t
479 clock_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
516 static kern_return_t
517 clock_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 */
606 static void
607 alarm_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
674 static void
675 alarm_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 */
712 static void
713 post_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
746 static void
747 set_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 */
762 static int
763 check_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
782 mach_timespec_t
783 clock_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
793 mach_timespec_t
794 clock_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 }