]> git.saurik.com Git - apple/libdispatch.git/blob - src/time.c
libdispatch-703.50.37.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 #if !(defined(__i386__) || defined(__x86_64__) || !HAVE_MACH_ABSOLUTE_TIME) \
24 || TARGET_OS_WIN32
25 DISPATCH_CACHELINE_ALIGN _dispatch_host_time_data_s _dispatch_host_time_data = {
26 .ratio_1_to_1 = true,
27 };
28
29 void
30 _dispatch_get_host_time_init(void *context DISPATCH_UNUSED)
31 {
32 #if !TARGET_OS_WIN32
33 mach_timebase_info_data_t tbi;
34 (void)dispatch_assume_zero(mach_timebase_info(&tbi));
35 _dispatch_host_time_data.frac = tbi.numer;
36 _dispatch_host_time_data.frac /= tbi.denom;
37 _dispatch_host_time_data.ratio_1_to_1 = (tbi.numer == tbi.denom);
38 #else
39 LARGE_INTEGER freq;
40 dispatch_assume(QueryPerformanceFrequency(&freq));
41 _dispatch_host_time_data.frac = (long double)NSEC_PER_SEC /
42 (long double)freq.QuadPart;
43 _dispatch_host_time_data.ratio_1_to_1 = (freq.QuadPart == 1);
44 #endif /* TARGET_OS_WIN32 */
45 }
46 #endif
47
48 dispatch_time_t
49 dispatch_time(dispatch_time_t inval, int64_t delta)
50 {
51 uint64_t offset;
52 if (inval == DISPATCH_TIME_FOREVER) {
53 return DISPATCH_TIME_FOREVER;
54 }
55 if ((int64_t)inval < 0) {
56 // wall clock
57 if (delta >= 0) {
58 offset = (uint64_t)delta;
59 if ((int64_t)(inval -= offset) >= 0) {
60 return DISPATCH_TIME_FOREVER; // overflow
61 }
62 return inval;
63 } else {
64 offset = (uint64_t)-delta;
65 if ((int64_t)(inval += offset) >= -1) {
66 // -1 is special == DISPATCH_TIME_FOREVER == forever
67 return (dispatch_time_t)-2ll; // underflow
68 }
69 return inval;
70 }
71 }
72 // mach clock
73 if (inval == 0) {
74 inval = _dispatch_absolute_time();
75 }
76 if (delta >= 0) {
77 offset = _dispatch_time_nano2mach((uint64_t)delta);
78 if ((int64_t)(inval += offset) <= 0) {
79 return DISPATCH_TIME_FOREVER; // overflow
80 }
81 return inval;
82 } else {
83 offset = _dispatch_time_nano2mach((uint64_t)-delta);
84 if ((int64_t)(inval -= offset) < 1) {
85 return 1; // underflow
86 }
87 return inval;
88 }
89 }
90
91 dispatch_time_t
92 dispatch_walltime(const struct timespec *inval, int64_t delta)
93 {
94 int64_t nsec;
95 if (inval) {
96 nsec = (int64_t)_dispatch_timespec_to_nano(*inval);
97 } else {
98 nsec = (int64_t)_dispatch_get_nanoseconds();
99 }
100 nsec += delta;
101 if (nsec <= 1) {
102 // -1 is special == DISPATCH_TIME_FOREVER == forever
103 return delta >= 0 ? DISPATCH_TIME_FOREVER : (dispatch_time_t)-2ll;
104 }
105 return (dispatch_time_t)-nsec;
106 }
107
108 uint64_t
109 _dispatch_timeout(dispatch_time_t when)
110 {
111 dispatch_time_t now;
112 if (when == DISPATCH_TIME_FOREVER) {
113 return DISPATCH_TIME_FOREVER;
114 }
115 if (when == 0) {
116 return 0;
117 }
118 if ((int64_t)when < 0) {
119 when = (dispatch_time_t)-(int64_t)when;
120 now = _dispatch_get_nanoseconds();
121 return now >= when ? 0 : when - now;
122 }
123 now = _dispatch_absolute_time();
124 return now >= when ? 0 : _dispatch_time_mach2nano(when - now);
125 }
126
127 uint64_t
128 _dispatch_time_nanoseconds_since_epoch(dispatch_time_t when)
129 {
130 if (when == DISPATCH_TIME_FOREVER) {
131 return DISPATCH_TIME_FOREVER;
132 }
133 if ((int64_t)when < 0) {
134 // time in nanoseconds since the POSIX epoch already
135 return (uint64_t)-(int64_t)when;
136 }
137 return _dispatch_get_nanoseconds() + _dispatch_timeout(when);
138 }