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/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 = { 158 NULL, NULL, 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) 191 clock->cl_ops = NULL; 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{ 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; 307 308 return (KERN_SUCCESS); 309} 310 311kern_return_t 312calend_gettime( 313 mach_timespec_t *time) /* OUT */ 314{ 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; 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) { 658 alrm2->al_next = NULL; 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); 769 timer_call_enter_with_leeway(&alarm_expire_timer, NULL, abstime, 0, TIMER_CALL_USER_NORMAL, FALSE); 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 798#ifndef __LP64__ 799 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} 821 822#endif /* __LP64__ */ 823