source: mainline/uspace/lib/posix/time.c@ 3f466c33

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3f466c33 was 3f466c33, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

More additions to time.h (still WIP)

  • Property mode set to 100644
File size: 18.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
34 */
35
36#define LIBPOSIX_INTERNAL
37
38/* Must be first. */
39#include "stdbool.h"
40
41#include "internal/common.h"
42#include "time.h"
43
44#include "ctype.h"
45#include "errno.h"
46#include "signal.h"
47
48#include "libc/malloc.h"
49#include "libc/task.h"
50#include "libc/stats.h"
51#include "libc/sys/time.h"
52
53// TODO: documentation
54// TODO: test everything in this file
55
56/* Helper functions ***********************************************************/
57
58#define HOURS_PER_DAY (24)
59#define MINS_PER_HOUR (60)
60#define SECS_PER_MIN (60)
61#define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY)
62#define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)
63#define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY)
64
65static bool _is_leap_year(time_t year)
66{
67 year += 1900;
68
69 if (year % 400 == 0)
70 return true;
71 if (year % 100 == 0)
72 return false;
73 if (year % 4 == 0)
74 return true;
75 return false;
76}
77
78static int _days_in_month(time_t year, time_t mon)
79{
80 assert(mon >= 0 && mon <= 11);
81 year += 1900;
82
83 static int month_days[] =
84 { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
85
86 if (mon == 1) {
87 /* february */
88 return _is_leap_year(year) ? 29 : 28;
89 } else {
90 return month_days[mon];
91 }
92}
93
94static int _day_of_year(time_t year, time_t mon, time_t mday)
95{
96 static int mdays[] =
97 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
98 static int leap_mdays[] =
99 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
100
101 return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1;
102}
103
104/* Integer division that rounds to negative infinity.
105 */
106static time_t _floor_div(time_t op1, time_t op2)
107{
108 if (op1 >= 0 || op1 % op2 == 0) {
109 return op1 / op2;
110 } else {
111 return op1 / op2 - 1;
112 }
113}
114
115/* Modulo that rounds to negative infinity.
116 */
117static time_t _floor_mod(time_t op1, time_t op2)
118{
119 int div = _floor_div(op1, op2);
120
121 /* (a / b) * b + a % b == a */
122 /* thus, a % b == a - (a / b) * b */
123
124 int result = op1 - div * op2;
125
126 /* Some paranoid checking to ensure I didn't make a mistake here. */
127 assert(result >= 0);
128 assert(result < op2);
129 assert(div * op2 + result == op1);
130
131 return result;
132}
133
134static time_t _days_since_epoch(time_t year, time_t mon, time_t mday)
135{
136 return (year - 70) * 365 + _floor_div(year - 69, 4) -
137 _floor_div(year - 1, 100) + _floor_div(year + 299, 400) +
138 _day_of_year(year, mon, mday);
139}
140
141/* Assumes normalized broken-down time. */
142static time_t _secs_since_epoch(const struct posix_tm *tm)
143{
144 return _days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) *
145 SECS_PER_DAY + tm->tm_hour * SECS_PER_HOUR +
146 tm->tm_min * SECS_PER_MIN + tm->tm_sec;
147}
148
149static int _day_of_week(time_t year, time_t mon, time_t mday)
150{
151 /* 1970-01-01 is Thursday */
152 return (_days_since_epoch(year, mon, mday) + 4) % 7;
153}
154
155struct _long_tm {
156 time_t tm_sec;
157 time_t tm_min;
158 time_t tm_hour;
159 time_t tm_mday;
160 time_t tm_mon;
161 time_t tm_year;
162 int tm_wday;
163 int tm_yday;
164 int tm_isdst;
165};
166
167static void _posix_to_long_tm(struct _long_tm *ltm, struct posix_tm *ptm)
168{
169 assert(ltm != NULL && ptm != NULL);
170 ltm->tm_sec = ptm->tm_sec;
171 ltm->tm_min = ptm->tm_min;
172 ltm->tm_hour = ptm->tm_hour;
173 ltm->tm_mday = ptm->tm_mday;
174 ltm->tm_mon = ptm->tm_mon;
175 ltm->tm_year = ptm->tm_year;
176 ltm->tm_wday = ptm->tm_wday;
177 ltm->tm_yday = ptm->tm_yday;
178 ltm->tm_isdst = ptm->tm_isdst;
179}
180
181static void _long_to_posix_tm(struct posix_tm *ptm, struct _long_tm *ltm)
182{
183 assert(ltm != NULL && ptm != NULL);
184 // FIXME: the cast should be unnecessary, libarch/common.h brain-damage
185 assert((ltm->tm_year >= (int) INT_MIN) && (ltm->tm_year <= (int) INT_MAX));
186
187 ptm->tm_sec = ltm->tm_sec;
188 ptm->tm_min = ltm->tm_min;
189 ptm->tm_hour = ltm->tm_hour;
190 ptm->tm_mday = ltm->tm_mday;
191 ptm->tm_mon = ltm->tm_mon;
192 ptm->tm_year = ltm->tm_year;
193 ptm->tm_wday = ltm->tm_wday;
194 ptm->tm_yday = ltm->tm_yday;
195 ptm->tm_isdst = ltm->tm_isdst;
196}
197
198static void _normalize_time(struct _long_tm *tm)
199{
200 // TODO: DST correction
201
202 /* Adjust time. */
203 tm->tm_min += _floor_div(tm->tm_sec, SECS_PER_MIN);
204 tm->tm_sec = _floor_mod(tm->tm_sec, SECS_PER_MIN);
205 tm->tm_hour += _floor_div(tm->tm_min, MINS_PER_HOUR);
206 tm->tm_min = _floor_mod(tm->tm_min, MINS_PER_HOUR);
207 tm->tm_mday += _floor_div(tm->tm_hour, HOURS_PER_DAY);
208 tm->tm_hour = _floor_mod(tm->tm_hour, HOURS_PER_DAY);
209
210 /* Adjust month. */
211 tm->tm_year += _floor_div(tm->tm_mon, 12);
212 tm->tm_mon = _floor_mod(tm->tm_mon, 12);
213
214 /* Now the difficult part - days of month. */
215 /* Slow, but simple. */
216 // FIXME: do this faster
217
218 while (tm->tm_mday < 1) {
219 tm->tm_mon--;
220 if (tm->tm_mon == -1) {
221 tm->tm_mon = 11;
222 tm->tm_year--;
223 }
224
225 tm->tm_mday += _days_in_month(tm->tm_year, tm->tm_mon);
226 }
227
228 while (tm->tm_mday > _days_in_month(tm->tm_year, tm->tm_mon)) {
229 tm->tm_mday -= _days_in_month(tm->tm_year, tm->tm_mon);
230
231 tm->tm_mon++;
232 if (tm->tm_mon == 12) {
233 tm->tm_mon = 0;
234 tm->tm_year++;
235 }
236 }
237
238 /* Calculate the remaining two fields. */
239 tm->tm_yday = _day_of_year(tm->tm_year, tm->tm_mon, tm->tm_mday);
240 tm->tm_wday = _day_of_week(tm->tm_year, tm->tm_mon, tm->tm_mday);
241}
242
243/* Which day the week-based year starts on relative to the first calendar day.
244 * E.g. if the year starts on December 31st, the return value is -1.
245 */
246static int _wbyear_offset(int year)
247{
248 int start_wday = _day_of_week(year, 0, 1);
249 return _floor_mod(4 - start_wday, 7) - 3;
250}
251
252/* Returns week-based year of the specified time.
253 * Assumes normalized broken-down time.
254 */
255static int _wbyear(const struct posix_tm *tm)
256{
257 int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
258 if (day < 0) {
259 /* Last week of previous year. */
260 return tm->tm_year - 1;
261 }
262 if (day > 364 + _is_leap_year(tm->tm_year)){
263 /* First week of next year. */
264 return tm->tm_year + 1;
265 }
266 /* All the other days are in the calendar year. */
267 return tm->tm_year;
268}
269
270/** Week number of the year, assuming weeks start on sunday.
271 * The first Sunday of January is the first day of week 1;
272 * days in the new year before this are in week 0.
273 *
274 * @param tm Normalized broken-down time.
275 * @return The week number (0 - 53).
276 */
277static int _sun_week_number(const struct posix_tm *tm)
278{
279 int first_day = (7 - _day_of_week(tm->tm_year, 0, 1)) % 7;
280 return (tm->tm_yday - first_day + 7) / 7;
281}
282
283/** Week number of the year, assuming weeks start on monday.
284 * If the week containing January 1st has four or more days in the new year,
285 * then it is considered week 1. Otherwise, it is the last week of the previous
286 * year, and the next week is week 1. Both January 4th and the first Thursday
287 * of January are always in week 1.
288 *
289 * @param tm Normalized broken-down time.
290 * @return The week number (1 - 53).
291 */
292static int _iso_week_number(const struct posix_tm *tm)
293{
294 int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
295 if (day < 0) {
296 /* Last week of previous year. */
297 return 53;
298 }
299 if (day > 364 + _is_leap_year(tm->tm_year)){
300 /* First week of next year. */
301 return 1;
302 }
303 /* All the other days give correct answer. */
304 return (day / 7 + 1);
305}
306
307/** Week number of the year, assuming weeks start on monday.
308 * The first Monday of January is the first day of week 1;
309 * days in the new year before this are in week 0.
310 *
311 * @param tm Normalized broken-down time.
312 * @return The week number (0 - 53).
313 */
314static int _mon_week_number(const struct posix_tm *tm)
315{
316 int first_day = (1 - _day_of_week(tm->tm_year, 0, 1)) % 7;
317 return (tm->tm_yday - first_day + 7) / 7;
318}
319
320/******************************************************************************/
321
322int posix_daylight;
323long posix_timezone;
324char *posix_tzname[2];
325
326void posix_tzset(void)
327{
328 // TODO: read environment
329 posix_tzname[0] = (char *) "GMT";
330 posix_tzname[1] = (char *) "GMT";
331 posix_daylight = 0;
332 posix_timezone = 0;
333}
334
335double posix_difftime(time_t time1, time_t time0)
336{
337 return (double) (time1 - time0);
338}
339
340/** This function first normalizes the provided broken-down time
341 * (moves all values to their proper bounds) and then tries to
342 * calculate the appropriate time_t representation.
343 *
344 * @param timeptr Broken-down time.
345 * @return time_t representation of the time, undefined value on overflow
346 */
347time_t posix_mktime(struct posix_tm *tm)
348{
349 // TODO: take DST flag into account
350 // TODO: detect overflow
351
352 struct _long_tm ltm;
353 _posix_to_long_tm(&ltm, tm);
354 _normalize_time(&ltm);
355 _long_to_posix_tm(tm, &ltm);
356
357 return _secs_since_epoch(tm);
358}
359
360struct posix_tm *posix_gmtime(const time_t *timer)
361{
362 static struct posix_tm result;
363 return posix_gmtime_r(timer, &result);
364}
365
366struct posix_tm *posix_gmtime_r(const time_t *restrict timer,
367 struct posix_tm *restrict result)
368{
369 assert(timer != NULL);
370 assert(result != NULL);
371
372 /* Set epoch and seconds to _long_tm struct and normalize to get
373 * correct values.
374 */
375 struct _long_tm ltm = {
376 .tm_sec = *timer,
377 .tm_min = 0,
378 .tm_hour = 0, /* 00:00:xx */
379 .tm_mday = 1,
380 .tm_mon = 0, /* January 1st */
381 .tm_year = 70, /* 1970 */
382 };
383 _normalize_time(&ltm);
384
385 if (ltm.tm_year < (int) INT_MIN || ltm.tm_year > (int) INT_MAX) {
386 errno = EOVERFLOW;
387 return NULL;
388 }
389
390 _long_to_posix_tm(result, &ltm);
391 return result;
392}
393
394/**
395 *
396 * @param timep
397 * @return
398 */
399struct posix_tm *posix_localtime(const time_t *timer)
400{
401 static struct posix_tm result;
402 return posix_localtime_r(timer, &result);
403}
404
405struct posix_tm *posix_localtime_r(const time_t *restrict timer,
406 struct posix_tm *restrict result)
407{
408 // TODO: deal with timezone
409 // currently assumes system and all times are in GMT
410 return posix_gmtime_r(timer, result);
411}
412
413/**
414 *
415 * @param tm
416 * @return
417 */
418char *posix_asctime(const struct posix_tm *timeptr)
419{
420 static char buf[ASCTIME_BUF_LEN];
421 return posix_asctime_r(timeptr, buf);
422}
423
424char *posix_asctime_r(const struct posix_tm *restrict timeptr,
425 char *restrict buf)
426{
427 assert(timeptr != NULL);
428 assert(buf != NULL);
429
430 static const char *wday[] = {
431 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
432 };
433 static const char *mon[] = {
434 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
435 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
436 };
437
438 snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n",
439 wday[timeptr->tm_wday],
440 mon[timeptr->tm_mon],
441 timeptr->tm_mday, timeptr->tm_hour,
442 timeptr->tm_min, timeptr->tm_sec,
443 1900 + timeptr->tm_year);
444
445 return buf;
446}
447
448/**
449 *
450 * @param timep
451 * @return
452 */
453char *posix_ctime(const time_t *timer)
454{
455 struct posix_tm *loctime = posix_localtime(timer);
456 if (loctime == NULL) {
457 return NULL;
458 }
459 return posix_asctime(loctime);
460}
461
462char *posix_ctime_r(const time_t *timer, char *buf)
463{
464 struct posix_tm loctime;
465 if (posix_localtime_r(timer, &loctime) == NULL) {
466 return NULL;
467 }
468 return posix_asctime_r(&loctime, buf);
469}
470
471/**
472 *
473 * @param s
474 * @param maxsize
475 * @param format
476 * @param tm
477 * @return
478 */
479size_t posix_strftime(char *s, size_t maxsize,
480 const char *format, const struct posix_tm *tm)
481{
482 // TODO: use locale
483 static const char *wday_abbr[] = {
484 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
485 };
486 static const char *wday[] = {
487 "Sunday", "Monday", "Tuesday", "Wednesday",
488 "Thursday", "Friday", "Saturday"
489 };
490 static const char *mon_abbr[] = {
491 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
492 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
493 };
494 static const char *mon[] = {
495 "January", "February", "March", "April", "May", "June", "July",
496 "August", "September", "October", "November", "December"
497 };
498
499 if (maxsize < 1) {
500 return 0;
501 }
502
503 char *ptr = s;
504 size_t consumed;
505 size_t remaining = maxsize;
506
507 #define append(...) { \
508 /* FIXME: this requires POSIX-correct snprintf */ \
509 /* otherwise it won't work with non-ascii chars */ \
510 consumed = snprintf(ptr, remaining, __VA_ARGS__); \
511 if (consumed >= remaining) { \
512 return 0; \
513 } \
514 ptr += consumed; \
515 remaining -= consumed; \
516 }
517
518 #define recurse(fmt) { \
519 consumed = posix_strftime(ptr, remaining, fmt, tm); \
520 if (consumed == 0) { \
521 return 0; \
522 } \
523 ptr += consumed; \
524 remaining -= consumed; \
525 }
526
527 #define TO_12H(hour) (((hour) > 12) ? ((hour) - 12) : \
528 (((hour) == 0) ? 12 : (hour)))
529
530 while (*format != '\0') {
531 if (*format != '%') {
532 append("%c", *format);
533 format++;
534 continue;
535 }
536
537 format++;
538 if (*format == '0' || *format == '+') {
539 // TODO: padding
540 format++;
541 }
542 while (isdigit(*format)) {
543 // TODO: padding
544 format++;
545 }
546 if (*format == 'O' || *format == 'E') {
547 // TODO: locale's alternative format
548 format++;
549 }
550
551 switch (*format) {
552 case 'a':
553 append("%s", wday_abbr[tm->tm_wday]); break;
554 case 'A':
555 append("%s", wday[tm->tm_wday]); break;
556 case 'b':
557 append("%s", mon_abbr[tm->tm_mon]); break;
558 case 'B':
559 append("%s", mon[tm->tm_mon]); break;
560 case 'c':
561 // TODO: locale-specific datetime format
562 recurse("%Y-%m-%d %H:%M:%S"); break;
563 case 'C':
564 append("%02d", (1900 + tm->tm_year) / 100); break;
565 case 'd':
566 append("%02d", tm->tm_mday); break;
567 case 'D':
568 recurse("%m/%d/%y"); break;
569 case 'e':
570 append("%2d", tm->tm_mday); break;
571 case 'F':
572 recurse("%+4Y-%m-%d"); break;
573 case 'g':
574 append("%02d", _wbyear(tm) % 100); break;
575 case 'G':
576 append("%d", _wbyear(tm)); break;
577 case 'h':
578 recurse("%b"); break;
579 case 'H':
580 append("%02d", tm->tm_hour); break;
581 case 'I':
582 append("%02d", TO_12H(tm->tm_hour)); break;
583 case 'j':
584 append("%03d", tm->tm_yday); break;
585 case 'k':
586 append("%2d", tm->tm_hour); break;
587 case 'l':
588 append("%2d", TO_12H(tm->tm_hour)); break;
589 case 'm':
590 append("%02d", tm->tm_mon); break;
591 case 'M':
592 append("%02d", tm->tm_min); break;
593 case 'n':
594 append("\n"); break;
595 case 'p':
596 append("%s", tm->tm_hour < 12 ? "AM" : "PM"); break;
597 case 'P':
598 append("%s", tm->tm_hour < 12 ? "am" : "PM"); break;
599 case 'r':
600 recurse("%I:%M:%S %p"); break;
601 case 'R':
602 recurse("%H:%M"); break;
603 case 's':
604 append("%ld", _secs_since_epoch(tm)); break;
605 case 'S':
606 append("%02d", tm->tm_sec); break;
607 case 't':
608 append("\t"); break;
609 case 'T':
610 recurse("%H:%M:%S"); break;
611 case 'u':
612 append("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday); break;
613 case 'U':
614 append("%02d", _sun_week_number(tm)); break;
615 case 'V':
616 append("%02d", _iso_week_number(tm)); break;
617 case 'w':
618 append("%d", tm->tm_wday); break;
619 case 'W':
620 append("%02d", _mon_week_number(tm)); break;
621 case 'x':
622 // TODO: locale-specific date format
623 recurse("%Y-%m-%d"); break;
624 case 'X':
625 // TODO: locale-specific time format
626 recurse("%H:%M:%S"); break;
627 case 'y':
628 append("%02d", tm->tm_year % 100); break;
629 case 'Y':
630 append("%d", 1900 + tm->tm_year); break;
631 case 'z':
632 // TODO: timezone
633 break;
634 case 'Z':
635 // TODO: timezone
636 break;
637 case '%':
638 append("%%");
639 break;
640 default:
641 /* Invalid specifier, print verbatim. */
642 while (*format != '%') {
643 format--;
644 }
645 append("%%");
646 break;
647 }
648 format++;
649 }
650
651 #undef append
652 #undef recurse
653
654 return maxsize - remaining;
655}
656
657int posix_clock_getres(posix_clockid_t clock_id, struct posix_timespec *res)
658{
659 assert(res != NULL);
660
661 switch (clock_id) {
662 case CLOCK_REALTIME:
663 res->tv_sec = 0;
664 res->tv_nsec = 1000; /* Microsecond resolution. */
665 return 0;
666 default:
667 errno = EINVAL;
668 return -1;
669 }
670}
671
672int posix_clock_gettime(posix_clockid_t clock_id, struct posix_timespec *tp)
673{
674 assert(tp != NULL);
675
676 switch (clock_id) {
677 case CLOCK_REALTIME:
678 ;
679 struct timeval tv;
680 gettimeofday(&tv, NULL);
681 tp->tv_sec = tv.tv_sec;
682 tp->tv_nsec = tv.tv_usec * 1000;
683 return 0;
684 default:
685 errno = EINVAL;
686 return -1;
687 }
688}
689
690int posix_clock_settime(posix_clockid_t clock_id,
691 const struct posix_timespec *tp)
692{
693 assert(tp != NULL);
694
695 switch (clock_id) {
696 case CLOCK_REALTIME:
697 // TODO: setting clock
698 // FIXME: HelenOS doesn't actually support hardware
699 // clock yet
700 errno = EPERM;
701 return -1;
702 default:
703 errno = EINVAL;
704 return -1;
705 }
706}
707
708int posix_clock_nanosleep(posix_clockid_t clock_id, int flags,
709 const struct posix_timespec *rqtp, struct posix_timespec *rmtp)
710{
711 assert(rqtp != NULL);
712 assert(rmtp != NULL);
713
714 switch (clock_id) {
715 case CLOCK_REALTIME:
716 // TODO: interruptible sleep
717 if (rqtp->tv_sec != 0) {
718 sleep(rqtp->tv_sec);
719 }
720 if (rqtp->tv_nsec != 0) {
721 usleep(rqtp->tv_nsec / 1000);
722 }
723 return 0;
724 default:
725 errno = EINVAL;
726 return -1;
727 }
728}
729
730#if 0
731
732struct __posix_timer {
733 posix_clockid_t clockid;
734 struct posix_sigevent evp;
735};
736
737int posix_timer_create(posix_clockid_t clockid,
738 struct posix_sigevent *restrict evp,
739 posix_timer_t *restrict timerid)
740{
741 // TODO
742 not_implemented();
743}
744
745int posix_timer_delete(posix_timer_t timerid)
746{
747 // TODO
748 not_implemented();
749}
750
751int posix_timer_getoverrun(posix_timer_t timerid)
752{
753 // TODO
754 not_implemented();
755}
756
757int posix_timer_gettime(posix_timer_t timerid,
758 struct posix_itimerspec *value)
759{
760 // TODO
761 not_implemented();
762}
763
764int posix_timer_settime(posix_timer_t timerid, int flags,
765 const struct posix_itimerspec *restrict value,
766 struct posix_itimerspec *restrict ovalue)
767{
768 // TODO
769 not_implemented();
770}
771
772#endif
773
774/**
775 * Get CPU time used since the process invocation.
776 *
777 * @return Consumed CPU cycles by this process or -1 if not available.
778 */
779posix_clock_t posix_clock(void)
780{
781 posix_clock_t total_cycles = -1;
782 stats_task_t *task_stats = stats_get_task(task_get_id());
783 if (task_stats) {
784 total_cycles = (posix_clock_t) (task_stats->kcycles + task_stats->ucycles);
785 }
786 free(task_stats);
787 task_stats = 0;
788
789 return total_cycles;
790}
791
792/** @}
793 */
Note: See TracBrowser for help on using the repository browser.