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