source: mainline/uspace/lib/c/generic/time.c@ a92f13d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a92f13d was d4d74dc, checked in by Vojtech Horky <vojtechhorky@…>, 13 years ago

Less includes in library headers

There is no need for errno.h to include fibril.h.
Similarly, tinput.h does not need list.h or async.h.

Unfortunately, many programs depended on the fact that including
errno.h would (recursively) include unistd.h and NULL would be
defined. Most of the fixes remedy this problem.

  • Property mode set to 100644
File size: 5.2 KB
Line 
1/*
2 * Copyright (c) 2006 Ondrej Palkovsky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/** @file
33 */
34
35#include <sys/time.h>
36#include <time.h>
37#include <bool.h>
38#include <libarch/barrier.h>
39#include <macros.h>
40#include <errno.h>
41#include <sysinfo.h>
42#include <as.h>
43#include <ddi.h>
44#include <libc.h>
45#include <unistd.h>
46
47/** Pointer to kernel shared variables with time */
48struct {
49 volatile sysarg_t seconds1;
50 volatile sysarg_t useconds;
51 volatile sysarg_t seconds2;
52} *ktime = NULL;
53
54/** Add microseconds to given timeval.
55 *
56 * @param tv Destination timeval.
57 * @param usecs Number of microseconds to add.
58 *
59 */
60void tv_add(struct timeval *tv, suseconds_t usecs)
61{
62 tv->tv_sec += usecs / 1000000;
63 tv->tv_usec += usecs % 1000000;
64
65 if (tv->tv_usec > 1000000) {
66 tv->tv_sec++;
67 tv->tv_usec -= 1000000;
68 }
69}
70
71/** Subtract two timevals.
72 *
73 * @param tv1 First timeval.
74 * @param tv2 Second timeval.
75 *
76 * @return Difference between tv1 and tv2 (tv1 - tv2) in
77 * microseconds.
78 *
79 */
80suseconds_t tv_sub(struct timeval *tv1, struct timeval *tv2)
81{
82 return (tv1->tv_usec - tv2->tv_usec) +
83 ((tv1->tv_sec - tv2->tv_sec) * 1000000);
84}
85
86/** Decide if one timeval is greater than the other.
87 *
88 * @param t1 First timeval.
89 * @param t2 Second timeval.
90 *
91 * @return True if tv1 is greater than tv2.
92 * @return False otherwise.
93 *
94 */
95int tv_gt(struct timeval *tv1, struct timeval *tv2)
96{
97 if (tv1->tv_sec > tv2->tv_sec)
98 return true;
99
100 if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec > tv2->tv_usec))
101 return true;
102
103 return false;
104}
105
106/** Decide if one timeval is greater than or equal to the other.
107 *
108 * @param tv1 First timeval.
109 * @param tv2 Second timeval.
110 *
111 * @return True if tv1 is greater than or equal to tv2.
112 * @return False otherwise.
113 *
114 */
115int tv_gteq(struct timeval *tv1, struct timeval *tv2)
116{
117 if (tv1->tv_sec > tv2->tv_sec)
118 return true;
119
120 if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec >= tv2->tv_usec))
121 return true;
122
123 return false;
124}
125
126/** Get time of day
127 *
128 * The time variables are memory mapped (read-only) from kernel which
129 * updates them periodically.
130 *
131 * As it is impossible to read 2 values atomically, we use a trick:
132 * First we read the seconds, then we read the microseconds, then we
133 * read the seconds again. If a second elapsed in the meantime, set
134 * the microseconds to zero.
135 *
136 * This assures that the values returned by two subsequent calls
137 * to gettimeofday() are monotonous.
138 *
139 */
140int gettimeofday(struct timeval *tv, struct timezone *tz)
141{
142 if (ktime == NULL) {
143 uintptr_t faddr;
144 int rc = sysinfo_get_value("clock.faddr", &faddr);
145 if (rc != EOK) {
146 errno = rc;
147 return -1;
148 }
149
150 void *addr;
151 rc = physmem_map((void *) faddr, 1,
152 AS_AREA_READ | AS_AREA_CACHEABLE, &addr);
153 if (rc != EOK) {
154 as_area_destroy(addr);
155 errno = rc;
156 return -1;
157 }
158
159 ktime = addr;
160 }
161
162 if (tz) {
163 tz->tz_minuteswest = 0;
164 tz->tz_dsttime = DST_NONE;
165 }
166
167 sysarg_t s2 = ktime->seconds2;
168
169 read_barrier();
170 tv->tv_usec = ktime->useconds;
171
172 read_barrier();
173 sysarg_t s1 = ktime->seconds1;
174
175 if (s1 != s2) {
176 tv->tv_sec = max(s1, s2);
177 tv->tv_usec = 0;
178 } else
179 tv->tv_sec = s1;
180
181 return 0;
182}
183
184time_t time(time_t *tloc)
185{
186 struct timeval tv;
187 if (gettimeofday(&tv, NULL))
188 return (time_t) -1;
189
190 if (tloc)
191 *tloc = tv.tv_sec;
192
193 return tv.tv_sec;
194}
195
196/** Wait unconditionally for specified number of microseconds
197 *
198 */
199int usleep(useconds_t usec)
200{
201 (void) __SYSCALL1(SYS_THREAD_USLEEP, usec);
202 return 0;
203}
204
205void udelay(useconds_t time)
206{
207 (void) __SYSCALL1(SYS_THREAD_UDELAY, (sysarg_t) time);
208}
209
210
211/** Wait unconditionally for specified number of seconds
212 *
213 */
214unsigned int sleep(unsigned int sec)
215{
216 /*
217 * Sleep in 1000 second steps to support
218 * full argument range
219 */
220
221 while (sec > 0) {
222 unsigned int period = (sec > 1000) ? 1000 : sec;
223
224 usleep(period * 1000000);
225 sec -= period;
226 }
227
228 return 0;
229}
230
231/** @}
232 */
Note: See TracBrowser for help on using the repository browser.