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