]> git.saurik.com Git - apple/libdispatch.git/blob - src/shims/time.h
libdispatch-913.30.4.tar.gz
[apple/libdispatch.git] / src / shims / time.h
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
34 #if TARGET_OS_WIN32
35 static inline unsigned int
36 sleep(unsigned int seconds)
37 {
38 Sleep(seconds * 1000); // milliseconds
39 return 0;
40 }
41 #endif
42
43 typedef enum {
44 DISPATCH_CLOCK_WALL,
45 DISPATCH_CLOCK_MACH,
46 #define DISPATCH_CLOCK_COUNT (DISPATCH_CLOCK_MACH + 1)
47 } dispatch_clock_t;
48
49 void _dispatch_time_init(void);
50
51 #if defined(__i386__) || defined(__x86_64__) || !HAVE_MACH_ABSOLUTE_TIME
52 #define DISPATCH_TIME_UNIT_USES_NANOSECONDS 1
53 #else
54 #define DISPATCH_TIME_UNIT_USES_NANOSECONDS 0
55 #endif
56
57 #if DISPATCH_TIME_UNIT_USES_NANOSECONDS
58 // x86 currently implements mach time in nanoseconds
59 // this is NOT likely to change
60 DISPATCH_ALWAYS_INLINE
61 static inline uint64_t
62 _dispatch_time_mach2nano(uint64_t machtime)
63 {
64 return machtime;
65 }
66
67 DISPATCH_ALWAYS_INLINE
68 static inline uint64_t
69 _dispatch_time_nano2mach(uint64_t nsec)
70 {
71 return nsec;
72 }
73 #else
74 #define DISPATCH_USE_HOST_TIME 1
75 extern uint64_t (*_dispatch_host_time_mach2nano)(uint64_t machtime);
76 extern uint64_t (*_dispatch_host_time_nano2mach)(uint64_t nsec);
77 static inline uint64_t
78 _dispatch_time_mach2nano(uint64_t machtime)
79 {
80 return _dispatch_host_time_mach2nano(machtime);
81 }
82
83 static inline uint64_t
84 _dispatch_time_nano2mach(uint64_t nsec)
85 {
86 return _dispatch_host_time_nano2mach(nsec);
87 }
88 #endif // DISPATCH_USE_HOST_TIME
89
90 /* XXXRW: Some kind of overflow detection needed? */
91 #define _dispatch_timespec_to_nano(ts) \
92 ((uint64_t)(ts).tv_sec * NSEC_PER_SEC + (uint64_t)(ts).tv_nsec)
93 #define _dispatch_timeval_to_nano(tv) \
94 ((uint64_t)(tv).tv_sec * NSEC_PER_SEC + \
95 (uint64_t)(tv).tv_usec * NSEC_PER_USEC)
96
97 static inline uint64_t
98 _dispatch_get_nanoseconds(void)
99 {
100 dispatch_static_assert(sizeof(NSEC_PER_SEC) == 8);
101 dispatch_static_assert(sizeof(USEC_PER_SEC) == 8);
102
103 #if TARGET_OS_MAC
104 return clock_gettime_nsec_np(CLOCK_REALTIME);
105 #elif HAVE_DECL_CLOCK_REALTIME
106 struct timespec ts;
107 dispatch_assume_zero(clock_gettime(CLOCK_REALTIME, &ts));
108 return _dispatch_timespec_to_nano(ts);
109 #elif TARGET_OS_WIN32
110 // FILETIME is 100-nanosecond intervals since January 1, 1601 (UTC).
111 FILETIME ft;
112 ULARGE_INTEGER li;
113 GetSystemTimeAsFileTime(&ft);
114 li.LowPart = ft.dwLowDateTime;
115 li.HighPart = ft.dwHighDateTime;
116 return li.QuadPart * 100ull;
117 #else
118 struct timeval tv;
119 dispatch_assert_zero(gettimeofday(&tv, NULL));
120 return _dispatch_timeval_to_nano(tv);
121 #endif
122 }
123
124 static inline uint64_t
125 _dispatch_absolute_time(void)
126 {
127 #if HAVE_MACH_ABSOLUTE_TIME
128 return mach_absolute_time();
129 #elif HAVE_DECL_CLOCK_UPTIME && !defined(__linux__)
130 struct timespec ts;
131 dispatch_assume_zero(clock_gettime(CLOCK_UPTIME, &ts));
132 return _dispatch_timespec_to_nano(ts);
133 #elif HAVE_DECL_CLOCK_MONOTONIC
134 struct timespec ts;
135 dispatch_assume_zero(clock_gettime(CLOCK_MONOTONIC, &ts));
136 return _dispatch_timespec_to_nano(ts);
137 #elif TARGET_OS_WIN32
138 LARGE_INTEGER now;
139 return QueryPerformanceCounter(&now) ? now.QuadPart : 0;
140 #else
141 #error platform needs to implement _dispatch_absolute_time()
142 #endif
143 }
144
145 DISPATCH_ALWAYS_INLINE
146 static inline uint64_t
147 _dispatch_approximate_time(void)
148 {
149 #if HAVE_MACH_APPROXIMATE_TIME
150 return mach_approximate_time();
151 #elif HAVE_DECL_CLOCK_UPTIME_FAST && !defined(__linux__)
152 struct timespec ts;
153 dispatch_assume_zero(clock_gettime(CLOCK_UPTIME_FAST, &ts));
154 return _dispatch_timespec_to_nano(ts);
155 #elif defined(__linux__)
156 struct timespec ts;
157 dispatch_assume_zero(clock_gettime(CLOCK_REALTIME_COARSE, &ts));
158 return _dispatch_timespec_to_nano(ts);
159 #else
160 return _dispatch_absolute_time();
161 #endif
162 }
163
164 DISPATCH_ALWAYS_INLINE
165 static inline uint64_t
166 _dispatch_time_now(dispatch_clock_t clock)
167 {
168 switch (clock) {
169 case DISPATCH_CLOCK_MACH:
170 return _dispatch_absolute_time();
171 case DISPATCH_CLOCK_WALL:
172 return _dispatch_get_nanoseconds();
173 }
174 __builtin_unreachable();
175 }
176
177 typedef struct {
178 uint64_t nows[DISPATCH_CLOCK_COUNT];
179 } dispatch_clock_now_cache_s, *dispatch_clock_now_cache_t;
180
181 DISPATCH_ALWAYS_INLINE
182 static inline uint64_t
183 _dispatch_time_now_cached(dispatch_clock_t clock,
184 dispatch_clock_now_cache_t cache)
185 {
186 if (likely(cache->nows[clock])) {
187 return cache->nows[clock];
188 }
189 return cache->nows[clock] = _dispatch_time_now(clock);
190 }
191
192 #endif // __DISPATCH_SHIMS_TIME__