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 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 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 = { 141 NULL, rtclock_init, 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 = { 155 NULL, NULL, 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; 175 register int i; 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) 188 clock->cl_ops = NULL; 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; 200 register int i; 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; 219 register int i; 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{ 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; 304 305 return (KERN_SUCCESS); 306} 307 308kern_return_t 309calend_gettime( 310 mach_timespec_t *time) /* OUT */ 311{ 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; 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; 623 register alarm_t alrm1; 624 register alarm_t alrm2; 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) { 655 alrm2->al_next = NULL; 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{ 690 register alarm_t alrm; 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{ 729 register alarm_t alrm1, alrm2; 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); 766 timer_call_enter_with_leeway(&alarm_expire_timer, NULL, abstime, 0, TIMER_CALL_USER_NORMAL, FALSE); 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 795#ifndef __LP64__ 796 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} 818 819#endif /* __LP64__ */ 820