1/* 2 * Copyright (c) 2008-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_APACHE_LICENSE_HEADER_START@ 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * @APPLE_APACHE_LICENSE_HEADER_END@ 19 */ 20 21#include "internal.h" 22 23uint64_t 24_dispatch_get_nanoseconds(void) 25{ 26#if !TARGET_OS_WIN32 27 struct timeval now; 28 int r = gettimeofday(&now, NULL); 29 dispatch_assert_zero(r); 30 dispatch_assert(sizeof(NSEC_PER_SEC) == 8); 31 dispatch_assert(sizeof(NSEC_PER_USEC) == 8); 32 return (uint64_t)now.tv_sec * NSEC_PER_SEC + 33 (uint64_t)now.tv_usec * NSEC_PER_USEC; 34#else /* TARGET_OS_WIN32 */ 35 // FILETIME is 100-nanosecond intervals since January 1, 1601 (UTC). 36 FILETIME ft; 37 ULARGE_INTEGER li; 38 GetSystemTimeAsFileTime(&ft); 39 li.LowPart = ft.dwLowDateTime; 40 li.HighPart = ft.dwHighDateTime; 41 return li.QuadPart * 100ull; 42#endif /* TARGET_OS_WIN32 */ 43} 44 45#if !(defined(__i386__) || defined(__x86_64__) || !HAVE_MACH_ABSOLUTE_TIME) \ 46 || TARGET_OS_WIN32 47DISPATCH_CACHELINE_ALIGN _dispatch_host_time_data_s _dispatch_host_time_data; 48 49void 50_dispatch_get_host_time_init(void *context DISPATCH_UNUSED) 51{ 52#if !TARGET_OS_WIN32 53 mach_timebase_info_data_t tbi; 54 (void)dispatch_assume_zero(mach_timebase_info(&tbi)); 55 _dispatch_host_time_data.frac = tbi.numer; 56 _dispatch_host_time_data.frac /= tbi.denom; 57 _dispatch_host_time_data.ratio_1_to_1 = (tbi.numer == tbi.denom); 58#else 59 LARGE_INTEGER freq; 60 dispatch_assume(QueryPerformanceFrequency(&freq)); 61 _dispatch_host_time_data.frac = (long double)NSEC_PER_SEC / 62 (long double)freq.QuadPart; 63 _dispatch_host_time_data.ratio_1_to_1 = (freq.QuadPart == 1); 64#endif /* TARGET_OS_WIN32 */ 65} 66#endif 67 68dispatch_time_t 69dispatch_time(dispatch_time_t inval, int64_t delta) 70{ 71 uint64_t offset; 72 if (inval == DISPATCH_TIME_FOREVER) { 73 return DISPATCH_TIME_FOREVER; 74 } 75 if ((int64_t)inval < 0) { 76 // wall clock 77 if (delta >= 0) { 78 offset = (uint64_t)delta; 79 if ((int64_t)(inval -= offset) >= 0) { 80 return DISPATCH_TIME_FOREVER; // overflow 81 } 82 return inval; 83 } else { 84 offset = (uint64_t)-delta; 85 if ((int64_t)(inval += offset) >= -1) { 86 // -1 is special == DISPATCH_TIME_FOREVER == forever 87 return (dispatch_time_t)-2ll; // underflow 88 } 89 return inval; 90 } 91 } 92 // mach clock 93 if (inval == 0) { 94 inval = _dispatch_absolute_time(); 95 } 96 if (delta >= 0) { 97 offset = _dispatch_time_nano2mach((uint64_t)delta); 98 if ((int64_t)(inval += offset) <= 0) { 99 return DISPATCH_TIME_FOREVER; // overflow 100 } 101 return inval; 102 } else { 103 offset = _dispatch_time_nano2mach((uint64_t)-delta); 104 if ((int64_t)(inval -= offset) < 1) { 105 return 1; // underflow 106 } 107 return inval; 108 } 109} 110 111dispatch_time_t 112dispatch_walltime(const struct timespec *inval, int64_t delta) 113{ 114 int64_t nsec; 115 if (inval) { 116 nsec = inval->tv_sec * 1000000000ll + inval->tv_nsec; 117 } else { 118 nsec = (int64_t)_dispatch_get_nanoseconds(); 119 } 120 nsec += delta; 121 if (nsec <= 1) { 122 // -1 is special == DISPATCH_TIME_FOREVER == forever 123 return delta >= 0 ? DISPATCH_TIME_FOREVER : (dispatch_time_t)-2ll; 124 } 125 return (dispatch_time_t)-nsec; 126} 127 128uint64_t 129_dispatch_timeout(dispatch_time_t when) 130{ 131 dispatch_time_t now; 132 if (when == DISPATCH_TIME_FOREVER) { 133 return DISPATCH_TIME_FOREVER; 134 } 135 if (when == 0) { 136 return 0; 137 } 138 if ((int64_t)when < 0) { 139 when = (dispatch_time_t)-(int64_t)when; 140 now = _dispatch_get_nanoseconds(); 141 return now >= when ? 0 : when - now; 142 } 143 now = _dispatch_absolute_time(); 144 return now >= when ? 0 : _dispatch_time_mach2nano(when - now); 145} 146