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