Tizen 2.1 base
[platform/upstream/gcd.git] / dispatch-1.0 / src / time.c
1 /*
2  * Copyright (c) 2008-2009 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 dispatch_time_t
35 dispatch_time(dispatch_time_t inval, int64_t delta)
36 {
37         if (inval == DISPATCH_TIME_FOREVER) {
38                 return DISPATCH_TIME_FOREVER;
39         }
40         if ((int64_t)inval < 0) {
41                 // wall clock
42                 if (delta >= 0) {
43                         if ((int64_t)(inval -= delta) >= 0) {
44                                 return DISPATCH_TIME_FOREVER;      // overflow
45                         }
46                         return inval;
47                 }
48                 if ((int64_t)(inval -= delta) >= -1) {
49                         // -1 is special == DISPATCH_TIME_FOREVER == forever
50                         return -2;      // underflow
51                 }
52                 return inval;
53         }
54         // mach clock
55         delta = _dispatch_time_nano2mach(delta);
56         if (inval == 0) {
57                 inval = _dispatch_absolute_time();
58         }
59         if (delta >= 0) {
60                 if ((int64_t)(inval += delta) <= 0) {
61                         return DISPATCH_TIME_FOREVER;      // overflow
62                 }
63                 return inval;
64         }
65         if ((int64_t)(inval += delta) < 1) {
66                 return 1;       // underflow
67         }
68         return inval;
69 }
70
71 dispatch_time_t
72 dispatch_walltime(const struct timespec *inval, int64_t delta)
73 {
74         int64_t nsec;
75         
76         if (inval) {
77                 nsec = inval->tv_sec * 1000000000ull + inval->tv_nsec;
78         } else {
79                 nsec = _dispatch_get_nanoseconds();
80         }
81
82         nsec += delta;
83         if (nsec <= 1) {
84                 // -1 is special == DISPATCH_TIME_FOREVER == forever
85                 return delta >= 0 ? DISPATCH_TIME_FOREVER : (uint64_t)-2ll;
86         }
87
88         return -nsec;
89 }
90
91 uint64_t
92 _dispatch_timeout(dispatch_time_t when)
93 {
94         uint64_t now;
95
96         if (when == DISPATCH_TIME_FOREVER) {
97                 return DISPATCH_TIME_FOREVER;
98         }
99         if (when == 0) {
100                 return 0;
101         }
102         if ((int64_t)when < 0) {
103                 when = -(int64_t)when;
104                 now = _dispatch_get_nanoseconds();
105                 return now >= when ? 0 : when - now;
106         }
107         now = _dispatch_absolute_time();
108         return now >= when ? 0 : _dispatch_time_mach2nano(when - now);
109 }
110
111 #if USE_POSIX_SEM
112 /*
113  * Unlike Mach semaphores, POSIX semaphores take an absolute, real time as an
114  * argument to sem_timedwait().  This routine converts from dispatch_time_t
115  * but assumes the caller has already handled the possibility of
116  * DISPATCH_TIME_FOREVER.
117  */
118 struct timespec
119 _dispatch_timeout_ts(dispatch_time_t when)
120 {
121         struct timespec ts_realtime;
122         uint64_t abstime, realtime;
123         int ret;
124
125         if (when == 0) {
126                 ret = clock_gettime(CLOCK_REALTIME, &ts_realtime);
127                 (void)dispatch_assume_zero(ret);
128                 return (ts_realtime);
129         }
130         if ((int64_t)when < 0) {
131                 ret = clock_gettime(CLOCK_REALTIME, &ts_realtime);
132                 (void)dispatch_assume_zero(ret);
133                 when = -(int64_t)when + ts_realtime.tv_sec * NSEC_PER_SEC +
134                     ts_realtime.tv_nsec;
135                 ts_realtime.tv_sec = when / NSEC_PER_SEC;
136                 ts_realtime.tv_nsec = when % NSEC_PER_SEC;
137                 return (ts_realtime);
138         }
139
140         /*
141          * Rebase 'when': (when - abstime) + realtime.
142          *
143          * XXXRW: Should we cache this delta to avoid system calls?
144          */
145         abstime = _dispatch_absolute_time();
146         ret = clock_gettime(CLOCK_REALTIME, &ts_realtime);
147         (void)dispatch_assume_zero(ret);
148         realtime = ts_realtime.tv_sec * NSEC_PER_SEC + ts_realtime.tv_nsec +
149             (when - abstime);
150         ts_realtime.tv_sec = realtime / NSEC_PER_SEC;
151         ts_realtime.tv_nsec = realtime % NSEC_PER_SEC;
152         return (ts_realtime);
153 }
154 #endif