]> git.saurik.com Git - apple/libdispatch.git/blob - src/time.c
libdispatch-339.92.1.tar.gz
[apple/libdispatch.git] / src / time.c
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
23 uint64_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
47 DISPATCH_CACHELINE_ALIGN _dispatch_host_time_data_s _dispatch_host_time_data;
48
49 void
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
68 dispatch_time_t
69 dispatch_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
111 dispatch_time_t
112 dispatch_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
128 uint64_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 }