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