source: mainline/uspace/lib/posix/source/time.c@ fdf97f6

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

Libposix functions are without posix_ prefix

Prior this commit, libposix headers declared all functions as posix_*
and used macros to rename e.g. strncpy to posix_strncpy in all (ported)
sources.

After this change, libposix headers look as normal POSIX compliant headers
(well, almost) and no renaming is done in the source codei (of the ported
applications). Instead, the renaming is done at object files level to
bypass weird problems that are bound to happen if you use macros.

The scheme is following. libposix headers use special macro to declare
the names. When included from outside, the functions have their normal
(standard) names. When included from the libposix sources, posix_ prefix
is added. Thus, when libposix is compiled and linked, it contains the
posix_* naming while compiling of ported software uses the normal
non-prefixed versions. This way the posix_* can use HelenOS libc without
any problem. Before linking, the posix_* prefix is removed from all
symbols and special prefix helenos_libc_ is added to all functions
that exists in our (HelenOS) libc and its name clashes with the POSIX
one.

The following happens, for example, to the open() function that exists in
both libposix and in libc.

  • Headers and sources of libc are left intact.
  • Copy of libc.a is made and to all clashing functions is added the helenos_libc prefix. This library is called libc4posix.a.
  • POSIX_DEF(open)(const char *) is used in libposix headers. This macro expands to plain open when included from the "outside world". But it expands to posix_open when included from libposix sources.
  • Libposix is compiled and linked, containing posix_open() that internally calls open() [the original one from libc].
  • Libposix is transformed - all open() are replaced with prefix variant: helenos_libc_open() and all posix_open() are replaced with open(). The transformed library is stored as libposixaslibc.a

Binutils and PCC are then linked with libc4posix and libposixaslibc
libraries instead of libc and libposix as was done previously.

WARNING: it looks that binutils, PCC and MSIM still works but not all
architectures were tested.

  • Property mode set to 100644
File size: 8.5 KB
Line 
1/*
2 * Copyright (c) 2011 Petr Koupy
3 * Copyright (c) 2011 Jiri Zarevucky
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libposix
31 * @{
32 */
33/** @file Time measurement support.
34 */
35
36#define LIBPOSIX_INTERNAL
37#define __POSIX_DEF__(x) posix_##x
38
39#include "internal/common.h"
40#include "posix/time.h"
41
42#include "posix/ctype.h"
43#include "posix/errno.h"
44#include "posix/signal.h"
45#include "posix/assert.h"
46
47#include "libc/malloc.h"
48#include "libc/task.h"
49#include "libc/stats.h"
50#include "libc/stdbool.h"
51#include "libc/sys/time.h"
52
53// TODO: test everything in this file
54
55/* In some places in this file, phrase "normalized broken-down time" is used.
56 * This means time broken down to components (year, month, day, hour, min, sec),
57 * in which every component is in its proper bounds. Non-normalized time could
58 * e.g. be 2011-54-5 29:13:-5, which would semantically mean start of year 2011
59 * + 53 months + 4 days + 29 hours + 13 minutes - 5 seconds.
60 */
61
62int posix_daylight;
63long posix_timezone;
64char *posix_tzname[2];
65
66/**
67 * Set timezone conversion information.
68 */
69void posix_tzset(void)
70{
71 // TODO: read environment
72 posix_tzname[0] = (char *) "GMT";
73 posix_tzname[1] = (char *) "GMT";
74 posix_daylight = 0;
75 posix_timezone = 0;
76}
77
78/**
79 * Converts a time value to a broken-down UTC time.
80 *
81 * @param timer Time to convert.
82 * @param result Structure to store the result to.
83 * @return Value of result on success, NULL on overflow.
84 */
85struct tm *posix_gmtime_r(const time_t *restrict timer,
86 struct tm *restrict result)
87{
88 int rc = time_utc2tm(*timer, result);
89 if (rc != EOK) {
90 errno = rc;
91 return NULL;
92 }
93
94 return result;
95}
96
97/**
98 * Converts a time value to a broken-down UTC time.
99 * (non reentrant version)
100 *
101 * @param timep Time to convert
102 * @return Pointer to a statically allocated structure that stores
103 * the result, NULL in case of error.
104 */
105struct tm *posix_gmtime(const time_t *restrict timep)
106{
107 static struct tm result;
108
109 return posix_gmtime_r(timep, &result);
110}
111
112/**
113 * Converts a time value to a broken-down local time.
114 *
115 * @param timer Time to convert.
116 * @param result Structure to store the result to.
117 * @return Value of result on success, NULL on overflow.
118 */
119struct tm *posix_localtime_r(const time_t *restrict timer,
120 struct tm *restrict result)
121{
122 // TODO: deal with timezone
123 // currently assumes system and all times are in GMT
124 return posix_gmtime_r(timer, result);
125}
126
127/**
128 * Converts a time value to a broken-down local time.
129 * (non reentrant version)
130 *
131 * @param timep Time to convert.
132 * @return Pointer to a statically allocated structure that stores
133 * the result, NULL in case of error.
134 */
135struct tm *posix_localtime(const time_t *restrict timep)
136{
137 static struct tm result;
138
139 return posix_localtime_r(timep, &result);
140}
141
142/**
143 * Converts broken-down time to a string in format
144 * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
145 *
146 * @param timeptr Broken-down time structure.
147 * @param buf Buffer to store string to, must be at least ASCTIME_BUF_LEN
148 * bytes long.
149 * @return Value of buf.
150 */
151char *posix_asctime_r(const struct tm *restrict timeptr,
152 char *restrict buf)
153{
154 time_tm2str(timeptr, buf);
155 return buf;
156}
157
158/**
159 * Convers broken-down time to a string in format
160 * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
161 * (non reentrant version)
162 *
163 * @param timeptr Broken-down time structure.
164 * @return Pointer to a statically allocated buffer that stores
165 * the result, NULL in case of error.
166 */
167char *posix_asctime(const struct tm *restrict timeptr)
168{
169 static char buf[ASCTIME_BUF_LEN];
170
171 return posix_asctime_r(timeptr, buf);
172}
173
174/**
175 * Converts the calendar time to a string in format
176 * "Sun Jan 1 00:00:00 1970\n" (Obsolete)
177 *
178 * @param timer Time to convert.
179 * @param buf Buffer to store string to. Must be at least ASCTIME_BUF_LEN
180 * bytes long.
181 * @return Pointer to buf on success, NULL on failure.
182 */
183char *posix_ctime_r(const time_t *timer, char *buf)
184{
185 int r = time_local2str(*timer, buf);
186 if (r != EOK) {
187 errno = r;
188 return NULL;
189 }
190
191 return buf;
192}
193
194/**
195 * Converts the calendar time to a string in format
196 * "Sun Jan 1 00:00:00 1970\n" (Obsolete)
197 * (non reentrant version)
198 *
199 * @param timep Time to convert.
200 * @return Pointer to a statically allocated buffer that stores
201 * the result, NULL in case of error.
202 */
203char *posix_ctime(const time_t *timep)
204{
205 static char buf[ASCTIME_BUF_LEN];
206
207 return posix_ctime_r(timep, buf);
208}
209
210/**
211 * Get clock resolution. Only CLOCK_REALTIME is supported.
212 *
213 * @param clock_id Clock ID.
214 * @param res Pointer to the variable where the resolution is to be written.
215 * @return 0 on success, -1 with errno set on failure.
216 */
217int posix_clock_getres(posix_clockid_t clock_id, struct posix_timespec *res)
218{
219 assert(res != NULL);
220
221 switch (clock_id) {
222 case CLOCK_REALTIME:
223 res->tv_sec = 0;
224 res->tv_nsec = 1000; /* Microsecond resolution. */
225 return 0;
226 default:
227 errno = EINVAL;
228 return -1;
229 }
230}
231
232/**
233 * Get time. Only CLOCK_REALTIME is supported.
234 *
235 * @param clock_id ID of the clock to query.
236 * @param tp Pointer to the variable where the time is to be written.
237 * @return 0 on success, -1 with errno on failure.
238 */
239int posix_clock_gettime(posix_clockid_t clock_id, struct posix_timespec *tp)
240{
241 assert(tp != NULL);
242
243 switch (clock_id) {
244 case CLOCK_REALTIME:
245 ;
246 struct timeval tv;
247 gettimeofday(&tv, NULL);
248 tp->tv_sec = tv.tv_sec;
249 tp->tv_nsec = tv.tv_usec * 1000;
250 return 0;
251 default:
252 errno = EINVAL;
253 return -1;
254 }
255}
256
257/**
258 * Set time on a specified clock. As HelenOS doesn't support this yet,
259 * this function always fails.
260 *
261 * @param clock_id ID of the clock to set.
262 * @param tp Time to set.
263 * @return 0 on success, -1 with errno on failure.
264 */
265int posix_clock_settime(posix_clockid_t clock_id,
266 const struct posix_timespec *tp)
267{
268 assert(tp != NULL);
269
270 switch (clock_id) {
271 case CLOCK_REALTIME:
272 // TODO: setting clock
273 // FIXME: HelenOS doesn't actually support hardware
274 // clock yet
275 errno = EPERM;
276 return -1;
277 default:
278 errno = EINVAL;
279 return -1;
280 }
281}
282
283/**
284 * Sleep on a specified clock.
285 *
286 * @param clock_id ID of the clock to sleep on (only CLOCK_REALTIME supported).
287 * @param flags Flags (none supported).
288 * @param rqtp Sleep time.
289 * @param rmtp Remaining time is written here if sleep is interrupted.
290 * @return 0 on success, -1 with errno set on failure.
291 */
292int posix_clock_nanosleep(posix_clockid_t clock_id, int flags,
293 const struct posix_timespec *rqtp, struct posix_timespec *rmtp)
294{
295 assert(rqtp != NULL);
296 assert(rmtp != NULL);
297
298 switch (clock_id) {
299 case CLOCK_REALTIME:
300 // TODO: interruptible sleep
301 if (rqtp->tv_sec != 0) {
302 sleep(rqtp->tv_sec);
303 }
304 if (rqtp->tv_nsec != 0) {
305 usleep(rqtp->tv_nsec / 1000);
306 }
307 return 0;
308 default:
309 errno = EINVAL;
310 return -1;
311 }
312}
313
314/**
315 * Get CPU time used since the process invocation.
316 *
317 * @return Consumed CPU cycles by this process or -1 if not available.
318 */
319posix_clock_t posix_clock(void)
320{
321 posix_clock_t total_cycles = -1;
322 stats_task_t *task_stats = stats_get_task(task_get_id());
323 if (task_stats) {
324 total_cycles = (posix_clock_t) (task_stats->kcycles +
325 task_stats->ucycles);
326 free(task_stats);
327 task_stats = 0;
328 }
329
330 return total_cycles;
331}
332
333/** @}
334 */
Note: See TracBrowser for help on using the repository browser.