Changeset e4f8c77 in mainline for uspace/lib/posix/time.c


Ignore:
Timestamp:
2011-07-13T22:39:18Z (13 years ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e6910c8
Parents:
5974661 (diff), 8ecef91 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge libposix.

File:
1 edited

Legend:

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

    r5974661 re4f8c77  
    3636#define LIBPOSIX_INTERNAL
    3737
     38/* Must be first. */
     39#include "stdbool.h"
     40
    3841#include "internal/common.h"
    3942#include "time.h"
    4043
     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
    41394/**
    42395 *
     
    44397 * @return
    45398 */
    46 struct posix_tm *posix_localtime(const time_t *timep)
    47 {
    48         // TODO
    49         static struct posix_tm result = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    50         return &result;
     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);
    51411}
    52412
     
    56416 * @return
    57417 */
    58 char *posix_asctime(const struct posix_tm *tm)
    59 {
    60         // TODO
    61         static char result[] = "Sun Jan 01 00:00:00 1900\n";
    62         return result;
     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;
    63446}
    64447
     
    68451 * @return
    69452 */
    70 char *posix_ctime(const time_t *timep)
    71 {
    72         return posix_asctime(posix_localtime(timep));
     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);
    73469}
    74470
     
    81477 * @return
    82478 */
    83 size_t posix_strftime(char *s, size_t maxsize, const char *format, const struct posix_tm *tm)
     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)
    84740{
    85741        // TODO
     
    87743}
    88744
     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
    89792/** @}
    90793 */
Note: See TracChangeset for help on using the changeset viewer.