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/* 22 * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch 23 * which are subject to change in future releases of Mac OS X. Any applications 24 * relying on these interfaces WILL break. 25 */ 26 27#ifndef __DISPATCH_SHIMS_TIME__ 28#define __DISPATCH_SHIMS_TIME__ 29 30#ifndef __DISPATCH_INDIRECT__ 31#error "Please #include <dispatch/dispatch.h> instead of this file directly." 32#endif 33 34DISPATCH_ALWAYS_INLINE_NDEBUG 35static inline void 36_dispatch_contention_usleep(unsigned int us) 37{ 38#if HAVE_MACH 39#if defined(SWITCH_OPTION_DISPATCH_CONTENTION) && !(TARGET_IPHONE_SIMULATOR && \ 40 IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED < 1090) 41 thread_switch(MACH_PORT_NULL, SWITCH_OPTION_DISPATCH_CONTENTION, us); 42#else 43 thread_switch(MACH_PORT_NULL, SWITCH_OPTION_WAIT, ((us-1)/1000)+1); 44#endif 45#else 46 usleep(us); 47#endif 48} 49 50#if TARGET_OS_WIN32 51static inline unsigned int 52sleep(unsigned int seconds) 53{ 54 Sleep(seconds * 1000); // milliseconds 55 return 0; 56} 57#endif 58 59uint64_t _dispatch_get_nanoseconds(void); 60 61#if defined(__i386__) || defined(__x86_64__) || !HAVE_MACH_ABSOLUTE_TIME 62// x86 currently implements mach time in nanoseconds 63// this is NOT likely to change 64DISPATCH_ALWAYS_INLINE 65static inline uint64_t 66_dispatch_time_mach2nano(uint64_t machtime) 67{ 68 return machtime; 69} 70 71DISPATCH_ALWAYS_INLINE 72static inline uint64_t 73_dispatch_time_nano2mach(uint64_t nsec) 74{ 75 return nsec; 76} 77#else 78typedef struct _dispatch_host_time_data_s { 79 dispatch_once_t pred; 80 long double frac; 81 bool ratio_1_to_1; 82} _dispatch_host_time_data_s; 83extern _dispatch_host_time_data_s _dispatch_host_time_data; 84void _dispatch_get_host_time_init(void *context); 85 86static inline uint64_t 87_dispatch_time_mach2nano(uint64_t machtime) 88{ 89 _dispatch_host_time_data_s *const data = &_dispatch_host_time_data; 90 dispatch_once_f(&data->pred, NULL, _dispatch_get_host_time_init); 91 92 if (!machtime || slowpath(data->ratio_1_to_1)) { 93 return machtime; 94 } 95 if (machtime >= INT64_MAX) { 96 return INT64_MAX; 97 } 98 long double big_tmp = ((long double)machtime * data->frac) + .5; 99 if (slowpath(big_tmp >= INT64_MAX)) { 100 return INT64_MAX; 101 } 102 return (uint64_t)big_tmp; 103} 104 105static inline uint64_t 106_dispatch_time_nano2mach(uint64_t nsec) 107{ 108 _dispatch_host_time_data_s *const data = &_dispatch_host_time_data; 109 dispatch_once_f(&data->pred, NULL, _dispatch_get_host_time_init); 110 111 if (!nsec || slowpath(data->ratio_1_to_1)) { 112 return nsec; 113 } 114 if (nsec >= INT64_MAX) { 115 return INT64_MAX; 116 } 117 long double big_tmp = ((long double)nsec / data->frac) + .5; 118 if (slowpath(big_tmp >= INT64_MAX)) { 119 return INT64_MAX; 120 } 121 return (uint64_t)big_tmp; 122} 123#endif 124 125static inline uint64_t 126_dispatch_absolute_time(void) 127{ 128#if HAVE_MACH_ABSOLUTE_TIME 129 return mach_absolute_time(); 130#elif TARGET_OS_WIN32 131 LARGE_INTEGER now; 132 return QueryPerformanceCounter(&now) ? now.QuadPart : 0; 133#else 134 struct timespec ts; 135 int ret; 136 137#if HAVE_DECL_CLOCK_UPTIME 138 ret = clock_gettime(CLOCK_UPTIME, &ts); 139#elif HAVE_DECL_CLOCK_MONOTONIC 140 ret = clock_gettime(CLOCK_MONOTONIC, &ts); 141#else 142#error "clock_gettime: no supported absolute time clock" 143#endif 144 (void)dispatch_assume_zero(ret); 145 146 /* XXXRW: Some kind of overflow detection needed? */ 147 return (ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec); 148#endif // HAVE_MACH_ABSOLUTE_TIME 149} 150 151 152#endif // __DISPATCH_SHIMS_TIME__ 153