xref: /trueos/lib/libdispatch/src/time.c (revision bf5f91cb28c5878845eb00fbf329c042f6c643c9)
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
_dispatch_get_nanoseconds(void)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 	.ratio_1_to_1 = true,
49 };
50 
51 void
_dispatch_get_host_time_init(void * context DISPATCH_UNUSED)52 _dispatch_get_host_time_init(void *context DISPATCH_UNUSED)
53 {
54 #if !TARGET_OS_WIN32
55 	mach_timebase_info_data_t tbi;
56 	(void)dispatch_assume_zero(mach_timebase_info(&tbi));
57 	_dispatch_host_time_data.frac = tbi.numer;
58 	_dispatch_host_time_data.frac /= tbi.denom;
59 	_dispatch_host_time_data.ratio_1_to_1 = (tbi.numer == tbi.denom);
60 #else
61 	LARGE_INTEGER freq;
62 	dispatch_assume(QueryPerformanceFrequency(&freq));
63 	_dispatch_host_time_data.frac = (long double)NSEC_PER_SEC /
64 			(long double)freq.QuadPart;
65 	_dispatch_host_time_data.ratio_1_to_1 = (freq.QuadPart == 1);
66 #endif	/* TARGET_OS_WIN32 */
67 }
68 #endif
69 
70 dispatch_time_t
dispatch_time(dispatch_time_t inval,int64_t delta)71 dispatch_time(dispatch_time_t inval, int64_t delta)
72 {
73 	uint64_t offset;
74 	if (inval == DISPATCH_TIME_FOREVER) {
75 		return DISPATCH_TIME_FOREVER;
76 	}
77 	if ((int64_t)inval < 0) {
78 		// wall clock
79 		if (delta >= 0) {
80 			offset = (uint64_t)delta;
81 			if ((int64_t)(inval -= offset) >= 0) {
82 				return DISPATCH_TIME_FOREVER; // overflow
83 			}
84 			return inval;
85 		} else {
86 			offset = (uint64_t)-delta;
87 			if ((int64_t)(inval += offset) >= -1) {
88 				// -1 is special == DISPATCH_TIME_FOREVER == forever
89 				return (dispatch_time_t)-2ll; // underflow
90 			}
91 			return inval;
92 		}
93 	}
94 	// mach clock
95 	if (inval == 0) {
96 		inval = _dispatch_absolute_time();
97 	}
98 	if (delta >= 0) {
99 		offset = _dispatch_time_nano2mach((uint64_t)delta);
100 		if ((int64_t)(inval += offset) <= 0) {
101 			return DISPATCH_TIME_FOREVER; // overflow
102 		}
103 		return inval;
104 	} else {
105 		offset = _dispatch_time_nano2mach((uint64_t)-delta);
106 		if ((int64_t)(inval -= offset) < 1) {
107 			return 1; // underflow
108 		}
109 		return inval;
110 	}
111 }
112 
113 dispatch_time_t
dispatch_walltime(const struct timespec * inval,int64_t delta)114 dispatch_walltime(const struct timespec *inval, int64_t delta)
115 {
116 	int64_t nsec;
117 	if (inval) {
118 		nsec = inval->tv_sec * 1000000000ll + inval->tv_nsec;
119 	} else {
120 		nsec = (int64_t)_dispatch_get_nanoseconds();
121 	}
122 	nsec += delta;
123 	if (nsec <= 1) {
124 		// -1 is special == DISPATCH_TIME_FOREVER == forever
125 		return delta >= 0 ? DISPATCH_TIME_FOREVER : (dispatch_time_t)-2ll;
126 	}
127 	return (dispatch_time_t)-nsec;
128 }
129 
130 uint64_t
_dispatch_timeout(dispatch_time_t when)131 _dispatch_timeout(dispatch_time_t when)
132 {
133 	dispatch_time_t now;
134 	if (when == DISPATCH_TIME_FOREVER) {
135 		return DISPATCH_TIME_FOREVER;
136 	}
137 	if (when == 0) {
138 		return 0;
139 	}
140 	if ((int64_t)when < 0) {
141 		when = (dispatch_time_t)-(int64_t)when;
142 		now = _dispatch_get_nanoseconds();
143 		return now >= when ? 0 : when - now;
144 	}
145 	now = _dispatch_absolute_time();
146 	return now >= when ? 0 : _dispatch_time_mach2nano(when - now);
147 }
148