2 * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
24 _dispatch_get_nanoseconds(void)
27 int r
= gettimeofday(&now
, NULL
);
28 dispatch_assert_zero(r
);
29 dispatch_assert(sizeof(NSEC_PER_SEC
) == 8);
30 dispatch_assert(sizeof(NSEC_PER_USEC
) == 8);
31 return now
.tv_sec
* NSEC_PER_SEC
+ now
.tv_usec
* NSEC_PER_USEC
;
34 #if defined(__i386__) || defined(__x86_64__)
35 // x86 currently implements mach time in nanoseconds; this is NOT likely to change
36 #define _dispatch_time_mach2nano(x) (x)
37 #define _dispatch_time_nano2mach(x) (x)
39 static struct _dispatch_host_time_data_s
{
40 mach_timebase_info_data_t tbi
;
41 uint64_t safe_numer_math
;
43 } _dispatch_host_time_data
;
46 _dispatch_get_host_time_init(void *context
__attribute__((unused
)))
48 dispatch_assume_zero(mach_timebase_info(&_dispatch_host_time_data
.tbi
));
49 _dispatch_host_time_data
.safe_numer_math
= DISPATCH_TIME_FOREVER
/ _dispatch_host_time_data
.tbi
.numer
;
53 _dispatch_time_mach2nano(uint64_t nsec
)
55 struct _dispatch_host_time_data_s
*const data
= &_dispatch_host_time_data
;
56 uint64_t small_tmp
= nsec
;
58 __uint128_t big_tmp
= nsec
;
60 long double big_tmp
= nsec
;
63 dispatch_once_f(&data
->pred
, NULL
, _dispatch_get_host_time_init
);
65 if (slowpath(data
->tbi
.numer
!= data
->tbi
.denom
)) {
66 if (nsec
< data
->safe_numer_math
) {
67 small_tmp
*= data
->tbi
.numer
;
68 small_tmp
/= data
->tbi
.denom
;
70 big_tmp
*= data
->tbi
.numer
;
71 big_tmp
/= data
->tbi
.denom
;
79 _dispatch_time_nano2mach(int64_t nsec
)
81 struct _dispatch_host_time_data_s
*const data
= &_dispatch_host_time_data
;
83 __int128_t big_tmp
= nsec
;
85 long double big_tmp
= nsec
;
88 dispatch_once_f(&data
->pred
, NULL
, _dispatch_get_host_time_init
);
90 if (fastpath(data
->tbi
.numer
== data
->tbi
.denom
)) {
94 // Multiply by the inverse to convert nsec to Mach absolute time
95 big_tmp
*= data
->tbi
.denom
;
96 big_tmp
/= data
->tbi
.numer
;
98 if (big_tmp
> INT64_MAX
) {
101 if (big_tmp
< INT64_MIN
) {
109 dispatch_time(dispatch_time_t inval
, int64_t delta
)
111 if (inval
== DISPATCH_TIME_FOREVER
) {
112 return DISPATCH_TIME_FOREVER
;
114 if ((int64_t)inval
< 0) {
117 if ((int64_t)(inval
-= delta
) >= 0) {
118 return DISPATCH_TIME_FOREVER
; // overflow
122 if ((int64_t)(inval
-= delta
) >= -1) {
123 // -1 is special == DISPATCH_TIME_FOREVER == forever
124 return -2; // underflow
129 delta
= _dispatch_time_nano2mach(delta
);
131 inval
= mach_absolute_time();
134 if ((int64_t)(inval
+= delta
) <= 0) {
135 return DISPATCH_TIME_FOREVER
; // overflow
139 if ((int64_t)(inval
+= delta
) < 1) {
140 return 1; // underflow
146 dispatch_walltime(const struct timespec
*inval
, int64_t delta
)
151 nsec
= inval
->tv_sec
* 1000000000ull + inval
->tv_nsec
;
153 nsec
= _dispatch_get_nanoseconds();
158 // -1 is special == DISPATCH_TIME_FOREVER == forever
159 return delta
>= 0 ? DISPATCH_TIME_FOREVER
: (uint64_t)-2ll;
166 _dispatch_timeout(dispatch_time_t when
)
170 if (when
== DISPATCH_TIME_FOREVER
) {
171 return DISPATCH_TIME_FOREVER
;
176 if ((int64_t)when
< 0) {
177 when
= -(int64_t)when
;
178 now
= _dispatch_get_nanoseconds();
179 return now
>= when
? 0 : when
- now
;
181 now
= mach_absolute_time();
182 return now
>= when
? 0 : _dispatch_time_mach2nano(when
- now
);