xref: /trueos/lib/libdispatch/src/shims/time.h (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 /*
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
sleep(unsigned int seconds)36 sleep(unsigned int seconds)
37 {
38 	Sleep(seconds * 1000); // milliseconds
39 	return 0;
40 }
41 #endif
42 
43 uint64_t _dispatch_get_nanoseconds(void);
44 
45 #if defined(__i386__) || defined(__x86_64__) || !HAVE_MACH_ABSOLUTE_TIME
46 // x86 currently implements mach time in nanoseconds
47 // this is NOT likely to change
48 DISPATCH_ALWAYS_INLINE
49 static inline uint64_t
_dispatch_time_mach2nano(uint64_t machtime)50 _dispatch_time_mach2nano(uint64_t machtime)
51 {
52 	return machtime;
53 }
54 
55 DISPATCH_ALWAYS_INLINE
56 static inline uint64_t
_dispatch_time_nano2mach(uint64_t nsec)57 _dispatch_time_nano2mach(uint64_t nsec)
58 {
59 	return nsec;
60 }
61 #else
62 typedef struct _dispatch_host_time_data_s {
63 	dispatch_once_t pred;
64 	long double frac;
65 	bool ratio_1_to_1;
66 } _dispatch_host_time_data_s;
67 extern _dispatch_host_time_data_s _dispatch_host_time_data;
68 void _dispatch_get_host_time_init(void *context);
69 
70 static inline uint64_t
_dispatch_time_mach2nano(uint64_t machtime)71 _dispatch_time_mach2nano(uint64_t machtime)
72 {
73 	_dispatch_host_time_data_s *const data = &_dispatch_host_time_data;
74 	dispatch_once_f(&data->pred, NULL, _dispatch_get_host_time_init);
75 
76 	if (!machtime || slowpath(data->ratio_1_to_1)) {
77 		return machtime;
78 	}
79 	if (machtime >= INT64_MAX) {
80 		return INT64_MAX;
81 	}
82 	long double big_tmp = ((long double)machtime * data->frac) + .5;
83 	if (slowpath(big_tmp >= INT64_MAX)) {
84 		return INT64_MAX;
85 	}
86 	return (uint64_t)big_tmp;
87 }
88 
89 static inline uint64_t
_dispatch_time_nano2mach(uint64_t nsec)90 _dispatch_time_nano2mach(uint64_t nsec)
91 {
92 	_dispatch_host_time_data_s *const data = &_dispatch_host_time_data;
93 	dispatch_once_f(&data->pred, NULL, _dispatch_get_host_time_init);
94 
95 	if (!nsec || slowpath(data->ratio_1_to_1)) {
96 		return nsec;
97 	}
98 	if (nsec >= INT64_MAX) {
99 		return INT64_MAX;
100 	}
101 	long double big_tmp = ((long double)nsec / data->frac) + .5;
102 	if (slowpath(big_tmp >= INT64_MAX)) {
103 		return INT64_MAX;
104 	}
105 	return (uint64_t)big_tmp;
106 }
107 #endif
108 
109 static inline uint64_t
_dispatch_absolute_time(void)110 _dispatch_absolute_time(void)
111 {
112 #if HAVE_MACH_ABSOLUTE_TIME
113 	return mach_absolute_time();
114 #elif TARGET_OS_WIN32
115 	LARGE_INTEGER now;
116 	return QueryPerformanceCounter(&now) ? now.QuadPart : 0;
117 #else
118 	struct timespec ts;
119 	int ret;
120 
121 #if HAVE_DECL_CLOCK_UPTIME
122 	ret = clock_gettime(CLOCK_UPTIME, &ts);
123 #elif HAVE_DECL_CLOCK_MONOTONIC
124 	ret = clock_gettime(CLOCK_MONOTONIC, &ts);
125 #else
126 #error "clock_gettime: no supported absolute time clock"
127 #endif
128 	(void)dispatch_assume_zero(ret);
129 
130 	/* XXXRW: Some kind of overflow detection needed? */
131 	return (ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec);
132 #endif // HAVE_MACH_ABSOLUTE_TIME
133 }
134 
135 
136 #endif // __DISPATCH_SHIMS_TIME__
137