Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/posix/time.c

    r3f466c33 r823a929  
    3636#define LIBPOSIX_INTERNAL
    3737
    38 /* Must be first. */
    39 #include "stdbool.h"
    40 
    4138#include "internal/common.h"
    4239#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 
    65 static 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 
    78 static 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 
    94 static 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  */
    106 static 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  */
    117 static 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 
    134 static 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. */
    142 static 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 
    149 static 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 
    155 struct _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 
    167 static 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 
    181 static 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 
    198 static 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  */
    246 static 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  */
    255 static 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  */
    277 static 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  */
    292 static 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  */
    314 static 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 
    322 int posix_daylight;
    323 long posix_timezone;
    324 char *posix_tzname[2];
    325 
    326 void 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 
    335 double 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  */
    347 time_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 
    360 struct posix_tm *posix_gmtime(const time_t *timer)
    361 {
    362         static struct posix_tm result;
    363         return posix_gmtime_r(timer, &result);
    364 }
    365 
    366 struct 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 }
    39340
    39441/**
     
    39744 * @return
    39845 */
    399 struct posix_tm *posix_localtime(const time_t *timer)
     46struct posix_tm *posix_localtime(const time_t *timep)
    40047{
    401         static struct posix_tm result;
    402         return posix_localtime_r(timer, &result);
    403 }
    404 
    405 struct 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);
     48        // TODO
     49        static struct posix_tm result = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
     50        return &result;
    41151}
    41252
     
    41656 * @return
    41757 */
    418 char *posix_asctime(const struct posix_tm *timeptr)
     58char *posix_asctime(const struct posix_tm *tm)
    41959{
    420         static char buf[ASCTIME_BUF_LEN];
    421         return posix_asctime_r(timeptr, buf);
    422 }
    423 
    424 char *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;
     60        // TODO
     61        static char result[] = "Sun Jan 01 00:00:00 1900\n";
     62        return result;
    44663}
    44764
     
    45168 * @return
    45269 */
    453 char *posix_ctime(const time_t *timer)
     70char *posix_ctime(const time_t *timep)
    45471{
    455         struct posix_tm *loctime = posix_localtime(timer);
    456         if (loctime == NULL) {
    457                 return NULL;
    458         }
    459         return posix_asctime(loctime);
    460 }
    461 
    462 char *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);
     72        return posix_asctime(posix_localtime(timep));
    46973}
    47074
     
    47781 * @return
    47882 */
    479 size_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 
    657 int 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 
    672 int 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 
    690 int 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 
    708 int 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 
    732 struct __posix_timer {
    733         posix_clockid_t clockid;
    734         struct posix_sigevent evp;
    735 };
    736 
    737 int posix_timer_create(posix_clockid_t clockid,
    738     struct posix_sigevent *restrict evp,
    739     posix_timer_t *restrict timerid)
     83size_t posix_strftime(char *s, size_t maxsize, const char *format, const struct posix_tm *tm)
    74084{
    74185        // TODO
     
    74387}
    74488
    745 int posix_timer_delete(posix_timer_t timerid)
     89/**
     90 *
     91 * @return
     92 */
     93posix_clock_t posix_clock(void)
    74694{
    74795        // TODO
     
    74997}
    75098
    751 int posix_timer_getoverrun(posix_timer_t timerid)
    752 {
    753         // TODO
    754         not_implemented();
    755 }
    756 
    757 int posix_timer_gettime(posix_timer_t timerid,
    758     struct posix_itimerspec *value)
    759 {
    760         // TODO
    761         not_implemented();
    762 }
    763 
    764 int 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  */
    779 posix_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 
    79299/** @}
    793100 */
Note: See TracChangeset for help on using the changeset viewer.