]> git.saurik.com Git - apple/libdispatch.git/blob - src/time.c
libdispatch-228.18.tar.gz
[apple/libdispatch.git] / src / time.c
1 /*
2 * Copyright (c) 2008-2010 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 struct timeval now;
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;
32 }
33
34 #if !(defined(__i386__) || defined(__x86_64__) || !HAVE_MACH_ABSOLUTE_TIME)
35 DISPATCH_CACHELINE_ALIGN _dispatch_host_time_data_s _dispatch_host_time_data;
36
37 void
38 _dispatch_get_host_time_init(void *context DISPATCH_UNUSED)
39 {
40 mach_timebase_info_data_t tbi;
41 (void)dispatch_assume_zero(mach_timebase_info(&tbi));
42 _dispatch_host_time_data.frac = tbi.numer;
43 _dispatch_host_time_data.frac /= tbi.denom;
44 _dispatch_host_time_data.ratio_1_to_1 = (tbi.numer == tbi.denom);
45 }
46 #endif
47
48 dispatch_time_t
49 dispatch_time(dispatch_time_t inval, int64_t delta)
50 {
51 if (inval == DISPATCH_TIME_FOREVER) {
52 return DISPATCH_TIME_FOREVER;
53 }
54 if ((int64_t)inval < 0) {
55 // wall clock
56 if (delta >= 0) {
57 if ((int64_t)(inval -= delta) >= 0) {
58 return DISPATCH_TIME_FOREVER; // overflow
59 }
60 return inval;
61 }
62 if ((int64_t)(inval -= delta) >= -1) {
63 // -1 is special == DISPATCH_TIME_FOREVER == forever
64 return -2; // underflow
65 }
66 return inval;
67 }
68 // mach clock
69 delta = _dispatch_time_nano2mach(delta);
70 if (inval == 0) {
71 inval = _dispatch_absolute_time();
72 }
73 if (delta >= 0) {
74 if ((int64_t)(inval += delta) <= 0) {
75 return DISPATCH_TIME_FOREVER; // overflow
76 }
77 return inval;
78 }
79 if ((int64_t)(inval += delta) < 1) {
80 return 1; // underflow
81 }
82 return inval;
83 }
84
85 dispatch_time_t
86 dispatch_walltime(const struct timespec *inval, int64_t delta)
87 {
88 int64_t nsec;
89
90 if (inval) {
91 nsec = inval->tv_sec * 1000000000ull + inval->tv_nsec;
92 } else {
93 nsec = _dispatch_get_nanoseconds();
94 }
95
96 nsec += delta;
97 if (nsec <= 1) {
98 // -1 is special == DISPATCH_TIME_FOREVER == forever
99 return delta >= 0 ? DISPATCH_TIME_FOREVER : (uint64_t)-2ll;
100 }
101
102 return -nsec;
103 }
104
105 uint64_t
106 _dispatch_timeout(dispatch_time_t when)
107 {
108 uint64_t now;
109
110 if (when == DISPATCH_TIME_FOREVER) {
111 return DISPATCH_TIME_FOREVER;
112 }
113 if (when == 0) {
114 return 0;
115 }
116 if ((int64_t)when < 0) {
117 when = -(int64_t)when;
118 now = _dispatch_get_nanoseconds();
119 return now >= when ? 0 : when - now;
120 }
121 now = _dispatch_absolute_time();
122 return now >= when ? 0 : _dispatch_time_mach2nano(when - now);
123 }