Changes in / [90478727:371cb6c] in mainline


Ignore:
Files:
12 deleted
13 edited

Legend:

Unmodified
Added
Removed
  • boot/Makefile.common

    r90478727 r371cb6c  
    187187        $(USPACE_PATH)/app/vuhid/vuh \
    188188        $(USPACE_PATH)/app/mkbd/mkbd \
    189         $(USPACE_PATH)/app/websrv/websrv \
    190         $(USPACE_PATH)/app/date/date
     189        $(USPACE_PATH)/app/websrv/websrv
    191190
    192191ifeq ($(CONFIG_PCC),y)
  • boot/arch/amd64/Makefile.inc

    r90478727 r371cb6c  
    4242        char/ps2mouse \
    4343        char/xtkbd \
    44         time/cmos-rtc \
    4544        bus/usb/ehci\
    4645        bus/usb/ohci \
  • uspace/Makefile

    r90478727 r371cb6c  
    7070        app/sysinfo \
    7171        app/mkbd \
    72         app/date \
    7372        app/websrv \
    7473        srv/clipboard \
     
    125124        drv/nic/ne2k \
    126125        drv/nic/e1k \
    127         drv/nic/rtl8139 \
     126        drv/nic/rtl8139
    128127
    129128ifeq ($(CONFIG_PCC),y)
     
    154153                drv/bus/isa \
    155154                drv/char/ns8250 \
    156                 drv/time/cmos-rtc \
    157155                srv/hw/irc/apic \
    158156                srv/hw/irc/i8259
     
    165163                drv/bus/isa \
    166164                drv/char/ns8250 \
    167                 drv/time/cmos-rtc \
    168165                srv/hw/irc/apic \
    169166                srv/hw/irc/i8259
  • uspace/drv/bus/isa/isa.dev

    r90478727 r371cb6c  
    2727        dma 1
    2828        dma 5
    29 
    30 cmos-rtc:
    31         match 100 isa/cmos-rtc
    32         io_range 70 2
  • uspace/lib/c/Makefile

    r90478727 r371cb6c  
    6969        generic/device/hw_res_parsed.c \
    7070        generic/device/char_dev.c \
    71         generic/device/clock_dev.c \
    7271        generic/device/nic.c \
    7372        generic/device/pci.c \
  • uspace/lib/c/generic/time.c

    r90478727 r371cb6c  
    11/*
    22 * Copyright (c) 2006 Ondrej Palkovsky
    3  * Copyright (c) 2011 Petr Koupy
    4  * Copyright (c) 2011 Jiri Zarevucky
    53 * All rights reserved.
    64 *
     
    4543#include <ddi.h>
    4644#include <libc.h>
    47 #include <stdint.h>
    48 #include <stdio.h>
    49 #include <ctype.h>
    50 #include <assert.h>
    5145#include <unistd.h>
    52 
    53 #define ASCTIME_BUF_LEN 26
    5446
    5547/** Pointer to kernel shared variables with time */
     
    5951        volatile sysarg_t seconds2;
    6052} *ktime = NULL;
    61 
    62 /* Helper functions ***********************************************************/
    63 
    64 #define HOURS_PER_DAY (24)
    65 #define MINS_PER_HOUR (60)
    66 #define SECS_PER_MIN (60)
    67 #define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY)
    68 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)
    69 #define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY)
    70 
    71 /**
    72  * Checks whether the year is a leap year.
    73  *
    74  * @param year Year since 1900 (e.g. for 1970, the value is 70).
    75  * @return true if year is a leap year, false otherwise
    76  */
    77 static bool _is_leap_year(time_t year)
    78 {
    79         year += 1900;
    80 
    81         if (year % 400 == 0)
    82                 return true;
    83         if (year % 100 == 0)
    84                 return false;
    85         if (year % 4 == 0)
    86                 return true;
    87         return false;
    88 }
    89 
    90 /**
    91  * Returns how many days there are in the given month of the given year.
    92  * Note that year is only taken into account if month is February.
    93  *
    94  * @param year Year since 1900 (can be negative).
    95  * @param mon Month of the year. 0 for January, 11 for December.
    96  * @return Number of days in the specified month.
    97  */
    98 static int _days_in_month(time_t year, time_t mon)
    99 {
    100         assert(mon >= 0 && mon <= 11);
    101 
    102         static int month_days[] =
    103                 { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    104 
    105         if (mon == 1) {
    106                 year += 1900;
    107                 /* february */
    108                 return _is_leap_year(year) ? 29 : 28;
    109         } else {
    110                 return month_days[mon];
    111         }
    112 }
    113 
    114 /**
    115  * For specified year, month and day of month, returns which day of that year
    116  * it is.
    117  *
    118  * For example, given date 2011-01-03, the corresponding expression is:
    119  *     _day_of_year(111, 0, 3) == 2
    120  *
    121  * @param year Year (year 1900 = 0, can be negative).
    122  * @param mon Month (January = 0).
    123  * @param mday Day of month (First day is 1).
    124  * @return Day of year (First day is 0).
    125  */
    126 static int _day_of_year(time_t year, time_t mon, time_t mday)
    127 {
    128         static int mdays[] =
    129             { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
    130         static int leap_mdays[] =
    131             { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
    132 
    133         return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1;
    134 }
    135 
    136 /**
    137  * Integer division that rounds to negative infinity.
    138  * Used by some functions in this file.
    139  *
    140  * @param op1 Dividend.
    141  * @param op2 Divisor.
    142  * @return Rounded quotient.
    143  */
    144 static time_t _floor_div(time_t op1, time_t op2)
    145 {
    146         if (op1 >= 0 || op1 % op2 == 0) {
    147                 return op1 / op2;
    148         } else {
    149                 return op1 / op2 - 1;
    150         }
    151 }
    152 
    153 /**
    154  * Modulo that rounds to negative infinity.
    155  * Used by some functions in this file.
    156  *
    157  * @param op1 Dividend.
    158  * @param op2 Divisor.
    159  * @return Remainder.
    160  */
    161 static time_t _floor_mod(time_t op1, time_t op2)
    162 {
    163         int div = _floor_div(op1, op2);
    164 
    165         /* (a / b) * b + a % b == a */
    166         /* thus, a % b == a - (a / b) * b */
    167 
    168         int result = op1 - div * op2;
    169        
    170         /* Some paranoid checking to ensure I didn't make a mistake here. */
    171         assert(result >= 0);
    172         assert(result < op2);
    173         assert(div * op2 + result == op1);
    174        
    175         return result;
    176 }
    177 
    178 /**
    179  * Number of days since the Epoch.
    180  * Epoch is 1970-01-01, which is also equal to day 0.
    181  *
    182  * @param year Year (year 1900 = 0, may be negative).
    183  * @param mon Month (January = 0).
    184  * @param mday Day of month (first day = 1).
    185  * @return Number of days since the Epoch.
    186  */
    187 static time_t _days_since_epoch(time_t year, time_t mon, time_t mday)
    188 {
    189         return (year - 70) * 365 + _floor_div(year - 69, 4) -
    190             _floor_div(year - 1, 100) + _floor_div(year + 299, 400) +
    191             _day_of_year(year, mon, mday);
    192 }
    193 
    194 /**
    195  * Seconds since the Epoch. see also _days_since_epoch().
    196  *
    197  * @param tm Normalized broken-down time.
    198  * @return Number of seconds since the epoch, not counting leap seconds.
    199  */
    200 static time_t _secs_since_epoch(const struct tm *tm)
    201 {
    202         return _days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) *
    203             SECS_PER_DAY + tm->tm_hour * SECS_PER_HOUR +
    204             tm->tm_min * SECS_PER_MIN + tm->tm_sec;
    205 }
    206 
    207 /**
    208  * Which day of week the specified date is.
    209  *
    210  * @param year Year (year 1900 = 0).
    211  * @param mon Month (January = 0).
    212  * @param mday Day of month (first = 1).
    213  * @return Day of week (Sunday = 0).
    214  */
    215 static int _day_of_week(time_t year, time_t mon, time_t mday)
    216 {
    217         /* 1970-01-01 is Thursday */
    218         return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7);
    219 }
    220 
    221 /**
    222  * Normalizes the broken-down time and optionally adds specified amount of
    223  * seconds.
    224  *
    225  * @param tm Broken-down time to normalize.
    226  * @param sec_add Seconds to add.
    227  * @return 0 on success, -1 on overflow
    228  */
    229 static int _normalize_time(struct tm *tm, time_t sec_add)
    230 {
    231         // TODO: DST correction
    232 
    233         /* Set initial values. */
    234         time_t sec = tm->tm_sec + sec_add;
    235         time_t min = tm->tm_min;
    236         time_t hour = tm->tm_hour;
    237         time_t day = tm->tm_mday - 1;
    238         time_t mon = tm->tm_mon;
    239         time_t year = tm->tm_year;
    240 
    241         /* Adjust time. */
    242         min += _floor_div(sec, SECS_PER_MIN);
    243         sec = _floor_mod(sec, SECS_PER_MIN);
    244         hour += _floor_div(min, MINS_PER_HOUR);
    245         min = _floor_mod(min, MINS_PER_HOUR);
    246         day += _floor_div(hour, HOURS_PER_DAY);
    247         hour = _floor_mod(hour, HOURS_PER_DAY);
    248 
    249         /* Adjust month. */
    250         year += _floor_div(mon, 12);
    251         mon = _floor_mod(mon, 12);
    252 
    253         /* Now the difficult part - days of month. */
    254        
    255         /* First, deal with whole cycles of 400 years = 146097 days. */
    256         year += _floor_div(day, 146097) * 400;
    257         day = _floor_mod(day, 146097);
    258        
    259         /* Then, go in one year steps. */
    260         if (mon <= 1) {
    261                 /* January and February. */
    262                 while (day > 365) {
    263                         day -= _is_leap_year(year) ? 366 : 365;
    264                         year++;
    265                 }
    266         } else {
    267                 /* Rest of the year. */
    268                 while (day > 365) {
    269                         day -= _is_leap_year(year + 1) ? 366 : 365;
    270                         year++;
    271                 }
    272         }
    273        
    274         /* Finally, finish it off month per month. */
    275         while (day >= _days_in_month(year, mon)) {
    276                 day -= _days_in_month(year, mon);
    277                 mon++;
    278                 if (mon >= 12) {
    279                         mon -= 12;
    280                         year++;
    281                 }
    282         }
    283        
    284         /* Calculate the remaining two fields. */
    285         tm->tm_yday = _day_of_year(year, mon, day + 1);
    286         tm->tm_wday = _day_of_week(year, mon, day + 1);
    287        
    288         /* And put the values back to the struct. */
    289         tm->tm_sec = (int) sec;
    290         tm->tm_min = (int) min;
    291         tm->tm_hour = (int) hour;
    292         tm->tm_mday = (int) day + 1;
    293         tm->tm_mon = (int) mon;
    294        
    295         /* Casts to work around libc brain-damage. */
    296         if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) {
    297                 tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX);
    298                 return -1;
    299         }
    300        
    301         tm->tm_year = (int) year;
    302         return 0;
    303 }
    304 
    305 /**
    306  * Which day the week-based year starts on, relative to the first calendar day.
    307  * E.g. if the year starts on December 31st, the return value is -1.
    308  *
    309  * @param Year since 1900.
    310  * @return Offset of week-based year relative to calendar year.
    311  */
    312 static int _wbyear_offset(int year)
    313 {
    314         int start_wday = _day_of_week(year, 0, 1);
    315         return _floor_mod(4 - start_wday, 7) - 3;
    316 }
    317 
    318 /**
    319  * Returns week-based year of the specified time.
    320  *
    321  * @param tm Normalized broken-down time.
    322  * @return Week-based year.
    323  */
    324 static int _wbyear(const struct tm *tm)
    325 {
    326         int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
    327         if (day < 0) {
    328                 /* Last week of previous year. */
    329                 return tm->tm_year - 1;
    330         }
    331         if (day > 364 + _is_leap_year(tm->tm_year)) {
    332                 /* First week of next year. */
    333                 return tm->tm_year + 1;
    334         }
    335         /* All the other days are in the calendar year. */
    336         return tm->tm_year;
    337 }
    338 
    339 /**
    340  * Week number of the year, assuming weeks start on sunday.
    341  * The first Sunday of January is the first day of week 1;
    342  * days in the new year before this are in week 0.
    343  *
    344  * @param tm Normalized broken-down time.
    345  * @return The week number (0 - 53).
    346  */
    347 static int _sun_week_number(const struct tm *tm)
    348 {
    349         int first_day = (7 - _day_of_week(tm->tm_year, 0, 1)) % 7;
    350         return (tm->tm_yday - first_day + 7) / 7;
    351 }
    352 
    353 /**
    354  * Week number of the year, assuming weeks start on monday.
    355  * If the week containing January 1st has four or more days in the new year,
    356  * then it is considered week 1. Otherwise, it is the last week of the previous
    357  * year, and the next week is week 1. Both January 4th and the first Thursday
    358  * of January are always in week 1.
    359  *
    360  * @param tm Normalized broken-down time.
    361  * @return The week number (1 - 53).
    362  */
    363 static int _iso_week_number(const struct tm *tm)
    364 {
    365         int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
    366         if (day < 0) {
    367                 /* Last week of previous year. */
    368                 return 53;
    369         }
    370         if (day > 364 + _is_leap_year(tm->tm_year)) {
    371                 /* First week of next year. */
    372                 return 1;
    373         }
    374         /* All the other days give correct answer. */
    375         return (day / 7 + 1);
    376 }
    377 
    378 /**
    379  * Week number of the year, assuming weeks start on monday.
    380  * The first Monday of January is the first day of week 1;
    381  * days in the new year before this are in week 0.
    382  *
    383  * @param tm Normalized broken-down time.
    384  * @return The week number (0 - 53).
    385  */
    386 static int _mon_week_number(const struct tm *tm)
    387 {
    388         int first_day = (1 - _day_of_week(tm->tm_year, 0, 1)) % 7;
    389         return (tm->tm_yday - first_day + 7) / 7;
    390 }
    391 
    392 /******************************************************************************/
    393 
    39453
    39554/** Add microseconds to given timeval.
     
    570229}
    571230
    572 /**
    573  * This function first normalizes the provided broken-down time
    574  * (moves all values to their proper bounds) and then tries to
    575  * calculate the appropriate time_t representation.
    576  *
    577  * @param tm Broken-down time.
    578  * @return time_t representation of the time, undefined value on overflow.
    579  */
    580 time_t mktime(struct tm *tm)
    581 {
    582         // TODO: take DST flag into account
    583         // TODO: detect overflow
    584 
    585         _normalize_time(tm, 0);
    586         return _secs_since_epoch(tm);
    587 }
    588 
    589 /**
    590  * Convert time and date to a string, based on a specified format and
    591  * current locale.
    592  *
    593  * @param s Buffer to write string to.
    594  * @param maxsize Size of the buffer.
    595  * @param format Format of the output.
    596  * @param tm Broken-down time to format.
    597  * @return Number of bytes written.
    598  */
    599 size_t strftime(char *restrict s, size_t maxsize,
    600     const char *restrict format, const struct tm *restrict tm)
    601 {
    602         assert(s != NULL);
    603         assert(format != NULL);
    604         assert(tm != NULL);
    605 
    606         // TODO: use locale
    607         static const char *wday_abbr[] = {
    608                 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
    609         };
    610         static const char *wday[] = {
    611                 "Sunday", "Monday", "Tuesday", "Wednesday",
    612                 "Thursday", "Friday", "Saturday"
    613         };
    614         static const char *mon_abbr[] = {
    615                 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    616                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    617         };
    618         static const char *mon[] = {
    619                 "January", "February", "March", "April", "May", "June", "July",
    620                 "August", "September", "October", "November", "December"
    621         };
    622        
    623         if (maxsize < 1) {
    624                 return 0;
    625         }
    626        
    627         char *ptr = s;
    628         size_t consumed;
    629         size_t remaining = maxsize;
    630        
    631         #define append(...) { \
    632                 /* FIXME: this requires POSIX-correct snprintf */ \
    633                 /*        otherwise it won't work with non-ascii chars */ \
    634                 consumed = snprintf(ptr, remaining, __VA_ARGS__); \
    635                 if (consumed >= remaining) { \
    636                         return 0; \
    637                 } \
    638                 ptr += consumed; \
    639                 remaining -= consumed; \
    640         }
    641        
    642         #define recurse(fmt) { \
    643                 consumed = strftime(ptr, remaining, fmt, tm); \
    644                 if (consumed == 0) { \
    645                         return 0; \
    646                 } \
    647                 ptr += consumed; \
    648                 remaining -= consumed; \
    649         }
    650        
    651         #define TO_12H(hour) (((hour) > 12) ? ((hour) - 12) : \
    652             (((hour) == 0) ? 12 : (hour)))
    653        
    654         while (*format != '\0') {
    655                 if (*format != '%') {
    656                         append("%c", *format);
    657                         format++;
    658                         continue;
    659                 }
    660                
    661                 format++;
    662                 if (*format == '0' || *format == '+') {
    663                         // TODO: padding
    664                         format++;
    665                 }
    666                 while (isdigit(*format)) {
    667                         // TODO: padding
    668                         format++;
    669                 }
    670                 if (*format == 'O' || *format == 'E') {
    671                         // TODO: locale's alternative format
    672                         format++;
    673                 }
    674                
    675                 switch (*format) {
    676                 case 'a':
    677                         append("%s", wday_abbr[tm->tm_wday]); break;
    678                 case 'A':
    679                         append("%s", wday[tm->tm_wday]); break;
    680                 case 'b':
    681                         append("%s", mon_abbr[tm->tm_mon]); break;
    682                 case 'B':
    683                         append("%s", mon[tm->tm_mon]); break;
    684                 case 'c':
    685                         // TODO: locale-specific datetime format
    686                         recurse("%Y-%m-%d %H:%M:%S"); break;
    687                 case 'C':
    688                         append("%02d", (1900 + tm->tm_year) / 100); break;
    689                 case 'd':
    690                         append("%02d", tm->tm_mday); break;
    691                 case 'D':
    692                         recurse("%m/%d/%y"); break;
    693                 case 'e':
    694                         append("%2d", tm->tm_mday); break;
    695                 case 'F':
    696                         recurse("%+4Y-%m-%d"); break;
    697                 case 'g':
    698                         append("%02d", _wbyear(tm) % 100); break;
    699                 case 'G':
    700                         append("%d", _wbyear(tm)); break;
    701                 case 'h':
    702                         recurse("%b"); break;
    703                 case 'H':
    704                         append("%02d", tm->tm_hour); break;
    705                 case 'I':
    706                         append("%02d", TO_12H(tm->tm_hour)); break;
    707                 case 'j':
    708                         append("%03d", tm->tm_yday); break;
    709                 case 'k':
    710                         append("%2d", tm->tm_hour); break;
    711                 case 'l':
    712                         append("%2d", TO_12H(tm->tm_hour)); break;
    713                 case 'm':
    714                         append("%02d", tm->tm_mon); break;
    715                 case 'M':
    716                         append("%02d", tm->tm_min); break;
    717                 case 'n':
    718                         append("\n"); break;
    719                 case 'p':
    720                         append("%s", tm->tm_hour < 12 ? "AM" : "PM"); break;
    721                 case 'P':
    722                         append("%s", tm->tm_hour < 12 ? "am" : "PM"); break;
    723                 case 'r':
    724                         recurse("%I:%M:%S %p"); break;
    725                 case 'R':
    726                         recurse("%H:%M"); break;
    727                 case 's':
    728                         append("%ld", _secs_since_epoch(tm)); break;
    729                 case 'S':
    730                         append("%02d", tm->tm_sec); break;
    731                 case 't':
    732                         append("\t"); break;
    733                 case 'T':
    734                         recurse("%H:%M:%S"); break;
    735                 case 'u':
    736                         append("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday);
    737                         break;
    738                 case 'U':
    739                         append("%02d", _sun_week_number(tm)); break;
    740                 case 'V':
    741                         append("%02d", _iso_week_number(tm)); break;
    742                 case 'w':
    743                         append("%d", tm->tm_wday); break;
    744                 case 'W':
    745                         append("%02d", _mon_week_number(tm)); break;
    746                 case 'x':
    747                         // TODO: locale-specific date format
    748                         recurse("%Y-%m-%d"); break;
    749                 case 'X':
    750                         // TODO: locale-specific time format
    751                         recurse("%H:%M:%S"); break;
    752                 case 'y':
    753                         append("%02d", tm->tm_year % 100); break;
    754                 case 'Y':
    755                         append("%d", 1900 + tm->tm_year); break;
    756                 case 'z':
    757                         // TODO: timezone
    758                         break;
    759                 case 'Z':
    760                         // TODO: timezone
    761                         break;
    762                 case '%':
    763                         append("%%");
    764                         break;
    765                 default:
    766                         /* Invalid specifier, print verbatim. */
    767                         while (*format != '%') {
    768                                 format--;
    769                         }
    770                         append("%%");
    771                         break;
    772                 }
    773                 format++;
    774         }
    775        
    776         #undef append
    777         #undef recurse
    778        
    779         return maxsize - remaining;
    780 }
    781 
    782 struct tm *gmtime(const time_t *timer)
    783 {
    784         assert(timer != NULL);
    785 
    786         static struct tm result;
    787 
    788         /* Set result to epoch. */
    789         result.tm_sec = 0;
    790         result.tm_min = 0;
    791         result.tm_hour = 0;
    792         result.tm_mday = 1;
    793         result.tm_mon = 0;
    794         result.tm_year = 70; /* 1970 */
    795 
    796         if (_normalize_time(&result, *timer) == -1) {
    797                 errno = EOVERFLOW;
    798                 return NULL;
    799         }
    800 
    801         return &result;
    802 }
    803 
    804 /**
    805  * Converts broken-down time to a string in format
    806  * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
    807  *
    808  * @param timeptr Broken-down time structure.
    809  * @return Pointer to a statically allocated string.
    810  */
    811 char *asctime(const struct tm *timeptr)
    812 {
    813         static char buf[ASCTIME_BUF_LEN];
    814 
    815         assert(timeptr != NULL);
    816 
    817         static const char *wday[] = {
    818                 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
    819         };
    820         static const char *mon[] = {
    821                 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    822                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    823         };
    824 
    825         snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n",
    826             wday[timeptr->tm_wday],
    827             mon[timeptr->tm_mon],
    828             timeptr->tm_mday, timeptr->tm_hour,
    829             timeptr->tm_min, timeptr->tm_sec,
    830             1900 + timeptr->tm_year);
    831 
    832         return buf;
    833 
    834 }
    835 
    836 /**
    837  * Converts a time value to a broken-down local time.
    838  *
    839  * @param timer Time to convert.
    840  * @return Normalized broken-down time in local timezone, NULL on overflow.
    841  */
    842 struct tm *localtime(const time_t *timer)
    843 {
    844         // TODO: deal with timezone
    845         // currently assumes system and all times are in GMT
    846 
    847         static struct tm result;
    848 
    849         /* Set result to epoch. */
    850         result.tm_sec = 0;
    851         result.tm_min = 0;
    852         result.tm_hour = 0;
    853         result.tm_mday = 1;
    854         result.tm_mon = 0;
    855         result.tm_year = 70; /* 1970 */
    856 
    857         if (_normalize_time(&result, *timer) == -1) {
    858                 errno = EOVERFLOW;
    859                 return NULL;
    860         }
    861 
    862         return &result;
    863 }
    864 
    865 /**
    866  * Equivalent to asctime(localtime(clock)).
    867  *
    868  * @param timer Time to convert.
    869  * @return Pointer to a statically allocated string holding the date.
    870  */
    871 char *ctime(const time_t *timer)
    872 {
    873         struct tm *loctime = localtime(timer);
    874         if (loctime == NULL) {
    875                 return NULL;
    876         }
    877         return asctime(loctime);
    878 }
    879 
    880 /**
    881  * Calculate the difference between two times, in seconds.
    882  *
    883  * @param time1 First time.
    884  * @param time0 Second time.
    885  * @return Time in seconds.
    886  */
    887 double difftime(time_t time1, time_t time0)
    888 {
    889         return (double) (time1 - time0);
    890 }
    891 
    892231/** @}
    893232 */
  • uspace/lib/c/include/ipc/dev_iface.h

    r90478727 r371cb6c  
    5454        AHCI_DEV_IFACE,
    5555
    56         /** Interface provided by Real Time Clock devices */
    57         CLOCK_DEV_IFACE,
    58 
    5956        DEV_IFACE_MAX
    6057} dev_inferface_idx_t;
  • uspace/lib/c/include/sys/time.h

    r90478727 r371cb6c  
    11/*
    22 * Copyright (c) 2006 Ondrej Palkovsky
    3  * Copyright (c) 2011 Petr Koupy
    4  * Copyright (c) 2011 Jiri Zarevucky
    53 * All rights reserved.
    64 *
     
    4139
    4240#define DST_NONE 0
    43 #define ASCTIME_BUF_LEN 26
    4441
    4542typedef long time_t;
     
    4845typedef uint32_t useconds_t;
    4946typedef uint32_t mseconds_t;
    50 
    51 struct tm {
    52         int tm_sec;         /* Seconds [0,60]. */
    53         int tm_min;         /* Minutes [0,59]. */
    54         int tm_hour;        /* Hour [0,23]. */
    55         int tm_mday;        /* Day of month [1,31]. */
    56         int tm_mon;         /* Month of year [0,11]. */
    57         int tm_year;        /* Years since 1900. */
    58         int tm_wday;        /* Day of week [0,6] (Sunday = 0). */
    59         int tm_yday;        /* Day of year [0,365]. */
    60         int tm_isdst;       /* Daylight Savings flag. */
    61 };
    6247
    6348struct timeval {
     
    7964extern void udelay(useconds_t);
    8065
    81 extern time_t mktime(struct tm *tm);
    82 extern struct tm *gmtime(const time_t *timer);
    83 extern char *asctime(const struct tm *timeptr);
    84 extern struct tm *localtime(const time_t *timer);
    85 extern char *ctime(const time_t *timer);
    86 extern double difftime(time_t time1, time_t time0);
    87 extern size_t strftime(char *restrict s, size_t maxsize,
    88     const char *restrict format, const struct tm *restrict tm);
    89 
    9066#endif
    9167
  • uspace/lib/drv/Makefile

    r90478727 r371cb6c  
    4545        generic/remote_usbhc.c \
    4646        generic/remote_usbhid.c \
    47         generic/remote_clock_dev.c
    4847        generic/remote_ahci.c
    4948
  • uspace/lib/drv/generic/dev_iface.c

    r90478727 r371cb6c  
    4141#include "remote_hw_res.h"
    4242#include "remote_char_dev.h"
    43 #include "remote_clock_dev.h"
    4443#include "remote_nic.h"
    4544#include "remote_usb.h"
     
    5857                &remote_usbhc_iface,
    5958                &remote_usbhid_iface,
    60                 &remote_clock_dev_iface,
    6159                &remote_ahci_iface
    6260        }
  • uspace/lib/posix/time.c

    r90478727 r371cb6c  
    141141 * Used by some functions in this file.
    142142 *
    143  * @param op1 Dividend.
     143 * @param op1 Divident.
    144144 * @param op2 Divisor.
    145145 * @return Rounded quotient.
     
    158158 * Used by some functions in this file.
    159159 *
    160  * @param op1 Dividend.
     160 * @param op1 Divident.
    161161 * @param op2 Divisor.
    162162 * @return Remainder.
     
    196196
    197197/**
     198 * Seconds since the Epoch. see also _days_since_epoch().
     199 *
     200 * @param tm Normalized broken-down time.
     201 * @return Number of seconds since the epoch, not counting leap seconds.
     202 */
     203static time_t _secs_since_epoch(const struct posix_tm *tm)
     204{
     205        return _days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) *
     206            SECS_PER_DAY + tm->tm_hour * SECS_PER_HOUR +
     207            tm->tm_min * SECS_PER_MIN + tm->tm_sec;
     208}
     209
     210/**
    198211 * Which day of week the specified date is.
    199212 *
     
    217230 * @return 0 on success, -1 on overflow
    218231 */
    219 static int _normalize_time(struct tm *tm, time_t sec_add)
     232static int _normalize_time(struct posix_tm *tm, time_t sec_add)
    220233{
    221234        // TODO: DST correction
     
    293306}
    294307
     308/**
     309 * Which day the week-based year starts on, relative to the first calendar day.
     310 * E.g. if the year starts on December 31st, the return value is -1.
     311 *
     312 * @param Year since 1900.
     313 * @return Offset of week-based year relative to calendar year.
     314 */
     315static int _wbyear_offset(int year)
     316{
     317        int start_wday = _day_of_week(year, 0, 1);
     318        return _floor_mod(4 - start_wday, 7) - 3;
     319}
     320
     321/**
     322 * Returns week-based year of the specified time.
     323 *
     324 * @param tm Normalized broken-down time.
     325 * @return Week-based year.
     326 */
     327static int _wbyear(const struct posix_tm *tm)
     328{
     329        int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
     330        if (day < 0) {
     331                /* Last week of previous year. */
     332                return tm->tm_year - 1;
     333        }
     334        if (day > 364 + _is_leap_year(tm->tm_year)) {
     335                /* First week of next year. */
     336                return tm->tm_year + 1;
     337        }
     338        /* All the other days are in the calendar year. */
     339        return tm->tm_year;
     340}
     341
     342/**
     343 * Week number of the year, assuming weeks start on sunday.
     344 * The first Sunday of January is the first day of week 1;
     345 * days in the new year before this are in week 0.
     346 *
     347 * @param tm Normalized broken-down time.
     348 * @return The week number (0 - 53).
     349 */
     350static int _sun_week_number(const struct posix_tm *tm)
     351{
     352        int first_day = (7 - _day_of_week(tm->tm_year, 0, 1)) % 7;
     353        return (tm->tm_yday - first_day + 7) / 7;
     354}
     355
     356/**
     357 * Week number of the year, assuming weeks start on monday.
     358 * If the week containing January 1st has four or more days in the new year,
     359 * then it is considered week 1. Otherwise, it is the last week of the previous
     360 * year, and the next week is week 1. Both January 4th and the first Thursday
     361 * of January are always in week 1.
     362 *
     363 * @param tm Normalized broken-down time.
     364 * @return The week number (1 - 53).
     365 */
     366static int _iso_week_number(const struct posix_tm *tm)
     367{
     368        int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
     369        if (day < 0) {
     370                /* Last week of previous year. */
     371                return 53;
     372        }
     373        if (day > 364 + _is_leap_year(tm->tm_year)) {
     374                /* First week of next year. */
     375                return 1;
     376        }
     377        /* All the other days give correct answer. */
     378        return (day / 7 + 1);
     379}
     380
     381/**
     382 * Week number of the year, assuming weeks start on monday.
     383 * The first Monday of January is the first day of week 1;
     384 * days in the new year before this are in week 0.
     385 *
     386 * @param tm Normalized broken-down time.
     387 * @return The week number (0 - 53).
     388 */
     389static int _mon_week_number(const struct posix_tm *tm)
     390{
     391        int first_day = (1 - _day_of_week(tm->tm_year, 0, 1)) % 7;
     392        return (tm->tm_yday - first_day + 7) / 7;
     393}
     394
    295395/******************************************************************************/
    296396
     
    312412
    313413/**
     414 * Calculate the difference between two times, in seconds.
     415 *
     416 * @param time1 First time.
     417 * @param time0 Second time.
     418 * @return Time in seconds.
     419 */
     420double posix_difftime(time_t time1, time_t time0)
     421{
     422        return (double) (time1 - time0);
     423}
     424
     425/**
     426 * This function first normalizes the provided broken-down time
     427 * (moves all values to their proper bounds) and then tries to
     428 * calculate the appropriate time_t representation.
     429 *
     430 * @param tm Broken-down time.
     431 * @return time_t representation of the time, undefined value on overflow.
     432 */
     433time_t posix_mktime(struct posix_tm *tm)
     434{
     435        // TODO: take DST flag into account
     436        // TODO: detect overflow
     437
     438        _normalize_time(tm, 0);
     439        return _secs_since_epoch(tm);
     440}
     441
     442/**
     443 * Converts a time value to a broken-down UTC time.
     444 *
     445 * @param timer Time to convert.
     446 * @return Normalized broken-down time in UTC, NULL on overflow.
     447 */
     448struct posix_tm *posix_gmtime(const time_t *timer)
     449{
     450        assert(timer != NULL);
     451
     452        static struct posix_tm result;
     453        return posix_gmtime_r(timer, &result);
     454}
     455
     456/**
    314457 * Converts a time value to a broken-down UTC time.
    315458 *
     
    318461 * @return Value of result on success, NULL on overflow.
    319462 */
    320 struct tm *posix_gmtime_r(const time_t *restrict timer,
    321     struct tm *restrict result)
     463struct posix_tm *posix_gmtime_r(const time_t *restrict timer,
     464    struct posix_tm *restrict result)
    322465{
    323466        assert(timer != NULL);
     
    342485/**
    343486 * Converts a time value to a broken-down local time.
     487 *
     488 * @param timer Time to convert.
     489 * @return Normalized broken-down time in local timezone, NULL on overflow.
     490 */
     491struct posix_tm *posix_localtime(const time_t *timer)
     492{
     493        static struct posix_tm result;
     494        return posix_localtime_r(timer, &result);
     495}
     496
     497/**
     498 * Converts a time value to a broken-down local time.
    344499 *
    345500 * @param timer Time to convert.
     
    347502 * @return Value of result on success, NULL on overflow.
    348503 */
    349 struct tm *posix_localtime_r(const time_t *restrict timer,
    350     struct tm *restrict result)
     504struct posix_tm *posix_localtime_r(const time_t *restrict timer,
     505    struct posix_tm *restrict result)
    351506{
    352507        // TODO: deal with timezone
    353508        // currently assumes system and all times are in GMT
    354509        return posix_gmtime_r(timer, result);
     510}
     511
     512/**
     513 * Converts broken-down time to a string in format
     514 * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
     515 *
     516 * @param timeptr Broken-down time structure.
     517 * @return Pointer to a statically allocated string.
     518 */
     519char *posix_asctime(const struct posix_tm *timeptr)
     520{
     521        static char buf[ASCTIME_BUF_LEN];
     522        return posix_asctime_r(timeptr, buf);
    355523}
    356524
     
    364532 * @return Value of buf.
    365533 */
    366 char *posix_asctime_r(const struct tm *restrict timeptr,
     534char *posix_asctime_r(const struct posix_tm *restrict timeptr,
    367535    char *restrict buf)
    368536{
     
    389557
    390558/**
     559 * Equivalent to asctime(localtime(clock)).
     560 *
     561 * @param timer Time to convert.
     562 * @return Pointer to a statically allocated string holding the date.
     563 */
     564char *posix_ctime(const time_t *timer)
     565{
     566        struct posix_tm *loctime = posix_localtime(timer);
     567        if (loctime == NULL) {
     568                return NULL;
     569        }
     570        return posix_asctime(loctime);
     571}
     572
     573/**
    391574 * Reentrant variant of ctime().
    392575 *
     
    398581char *posix_ctime_r(const time_t *timer, char *buf)
    399582{
    400         struct tm loctime;
     583        struct posix_tm loctime;
    401584        if (posix_localtime_r(timer, &loctime) == NULL) {
    402585                return NULL;
    403586        }
    404587        return posix_asctime_r(&loctime, buf);
     588}
     589
     590/**
     591 * Convert time and date to a string, based on a specified format and
     592 * current locale.
     593 *
     594 * @param s Buffer to write string to.
     595 * @param maxsize Size of the buffer.
     596 * @param format Format of the output.
     597 * @param tm Broken-down time to format.
     598 * @return Number of bytes written.
     599 */
     600size_t posix_strftime(char *restrict s, size_t maxsize,
     601    const char *restrict format, const struct posix_tm *restrict tm)
     602{
     603        assert(s != NULL);
     604        assert(format != NULL);
     605        assert(tm != NULL);
     606
     607        // TODO: use locale
     608        static const char *wday_abbr[] = {
     609                "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
     610        };
     611        static const char *wday[] = {
     612                "Sunday", "Monday", "Tuesday", "Wednesday",
     613                "Thursday", "Friday", "Saturday"
     614        };
     615        static const char *mon_abbr[] = {
     616                "Jan", "Feb", "Mar", "Apr", "May", "Jun",
     617                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
     618        };
     619        static const char *mon[] = {
     620                "January", "February", "March", "April", "May", "June", "July",
     621                "August", "September", "October", "November", "December"
     622        };
     623       
     624        if (maxsize < 1) {
     625                return 0;
     626        }
     627       
     628        char *ptr = s;
     629        size_t consumed;
     630        size_t remaining = maxsize;
     631       
     632        #define append(...) { \
     633                /* FIXME: this requires POSIX-correct snprintf */ \
     634                /*        otherwise it won't work with non-ascii chars */ \
     635                consumed = snprintf(ptr, remaining, __VA_ARGS__); \
     636                if (consumed >= remaining) { \
     637                        return 0; \
     638                } \
     639                ptr += consumed; \
     640                remaining -= consumed; \
     641        }
     642       
     643        #define recurse(fmt) { \
     644                consumed = posix_strftime(ptr, remaining, fmt, tm); \
     645                if (consumed == 0) { \
     646                        return 0; \
     647                } \
     648                ptr += consumed; \
     649                remaining -= consumed; \
     650        }
     651       
     652        #define TO_12H(hour) (((hour) > 12) ? ((hour) - 12) : \
     653            (((hour) == 0) ? 12 : (hour)))
     654       
     655        while (*format != '\0') {
     656                if (*format != '%') {
     657                        append("%c", *format);
     658                        format++;
     659                        continue;
     660                }
     661               
     662                format++;
     663                if (*format == '0' || *format == '+') {
     664                        // TODO: padding
     665                        format++;
     666                }
     667                while (isdigit(*format)) {
     668                        // TODO: padding
     669                        format++;
     670                }
     671                if (*format == 'O' || *format == 'E') {
     672                        // TODO: locale's alternative format
     673                        format++;
     674                }
     675               
     676                switch (*format) {
     677                case 'a':
     678                        append("%s", wday_abbr[tm->tm_wday]); break;
     679                case 'A':
     680                        append("%s", wday[tm->tm_wday]); break;
     681                case 'b':
     682                        append("%s", mon_abbr[tm->tm_mon]); break;
     683                case 'B':
     684                        append("%s", mon[tm->tm_mon]); break;
     685                case 'c':
     686                        // TODO: locale-specific datetime format
     687                        recurse("%Y-%m-%d %H:%M:%S"); break;
     688                case 'C':
     689                        append("%02d", (1900 + tm->tm_year) / 100); break;
     690                case 'd':
     691                        append("%02d", tm->tm_mday); break;
     692                case 'D':
     693                        recurse("%m/%d/%y"); break;
     694                case 'e':
     695                        append("%2d", tm->tm_mday); break;
     696                case 'F':
     697                        recurse("%+4Y-%m-%d"); break;
     698                case 'g':
     699                        append("%02d", _wbyear(tm) % 100); break;
     700                case 'G':
     701                        append("%d", _wbyear(tm)); break;
     702                case 'h':
     703                        recurse("%b"); break;
     704                case 'H':
     705                        append("%02d", tm->tm_hour); break;
     706                case 'I':
     707                        append("%02d", TO_12H(tm->tm_hour)); break;
     708                case 'j':
     709                        append("%03d", tm->tm_yday); break;
     710                case 'k':
     711                        append("%2d", tm->tm_hour); break;
     712                case 'l':
     713                        append("%2d", TO_12H(tm->tm_hour)); break;
     714                case 'm':
     715                        append("%02d", tm->tm_mon); break;
     716                case 'M':
     717                        append("%02d", tm->tm_min); break;
     718                case 'n':
     719                        append("\n"); break;
     720                case 'p':
     721                        append("%s", tm->tm_hour < 12 ? "AM" : "PM"); break;
     722                case 'P':
     723                        append("%s", tm->tm_hour < 12 ? "am" : "PM"); break;
     724                case 'r':
     725                        recurse("%I:%M:%S %p"); break;
     726                case 'R':
     727                        recurse("%H:%M"); break;
     728                case 's':
     729                        append("%ld", _secs_since_epoch(tm)); break;
     730                case 'S':
     731                        append("%02d", tm->tm_sec); break;
     732                case 't':
     733                        append("\t"); break;
     734                case 'T':
     735                        recurse("%H:%M:%S"); break;
     736                case 'u':
     737                        append("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday); break;
     738                case 'U':
     739                        append("%02d", _sun_week_number(tm)); break;
     740                case 'V':
     741                        append("%02d", _iso_week_number(tm)); break;
     742                case 'w':
     743                        append("%d", tm->tm_wday); break;
     744                case 'W':
     745                        append("%02d", _mon_week_number(tm)); break;
     746                case 'x':
     747                        // TODO: locale-specific date format
     748                        recurse("%Y-%m-%d"); break;
     749                case 'X':
     750                        // TODO: locale-specific time format
     751                        recurse("%H:%M:%S"); break;
     752                case 'y':
     753                        append("%02d", tm->tm_year % 100); break;
     754                case 'Y':
     755                        append("%d", 1900 + tm->tm_year); break;
     756                case 'z':
     757                        // TODO: timezone
     758                        break;
     759                case 'Z':
     760                        // TODO: timezone
     761                        break;
     762                case '%':
     763                        append("%%");
     764                        break;
     765                default:
     766                        /* Invalid specifier, print verbatim. */
     767                        while (*format != '%') {
     768                                format--;
     769                        }
     770                        append("%%");
     771                        break;
     772                }
     773                format++;
     774        }
     775       
     776        #undef append
     777        #undef recurse
     778       
     779        return maxsize - remaining;
    405780}
    406781
     
    519894        stats_task_t *task_stats = stats_get_task(task_get_id());
    520895        if (task_stats) {
    521                 total_cycles = (posix_clock_t) (task_stats->kcycles +
    522                     task_stats->ucycles);
     896                total_cycles = (posix_clock_t) (task_stats->kcycles + task_stats->ucycles);
    523897                free(task_stats);
    524898                task_stats = 0;
  • uspace/lib/posix/time.h

    r90478727 r371cb6c  
    6363#endif
    6464
     65#undef ASCTIME_BUF_LEN
     66#define ASCTIME_BUF_LEN 26
     67
    6568#undef CLOCK_REALTIME
    6669#define CLOCK_REALTIME ((posix_clockid_t) 0)
     70
     71struct posix_tm {
     72        int tm_sec;         /* Seconds [0,60]. */
     73        int tm_min;         /* Minutes [0,59]. */
     74        int tm_hour;        /* Hour [0,23]. */
     75        int tm_mday;        /* Day of month [1,31]. */
     76        int tm_mon;         /* Month of year [0,11]. */
     77        int tm_year;        /* Years since 1900. */
     78        int tm_wday;        /* Day of week [0,6] (Sunday = 0). */
     79        int tm_yday;        /* Day of year [0,365]. */
     80        int tm_isdst;       /* Daylight Savings flag. */
     81};
    6782
    6883struct posix_timespec {
     
    8499extern void posix_tzset(void);
    85100
     101/* Elapsed Time */
     102extern double posix_difftime(time_t time1, time_t time0);
     103
    86104/* Broken-down Time */
    87 extern struct tm *posix_gmtime_r(const time_t *restrict timer,
    88     struct tm *restrict result);
    89 extern struct tm *posix_localtime_r(const time_t *restrict timer,
    90     struct tm *restrict result);
     105extern time_t posix_mktime(struct posix_tm *tm);
     106extern struct posix_tm *posix_gmtime(const time_t *timer);
     107extern struct posix_tm *posix_gmtime_r(const time_t *restrict timer,
     108    struct posix_tm *restrict result);
     109extern struct posix_tm *posix_localtime(const time_t *timer);
     110extern struct posix_tm *posix_localtime_r(const time_t *restrict timer,
     111    struct posix_tm *restrict result);
    91112
    92113/* Formatting Calendar Time */
    93 extern char *posix_asctime_r(const struct tm *restrict timeptr,
     114extern char *posix_asctime(const struct posix_tm *timeptr);
     115extern char *posix_asctime_r(const struct posix_tm *restrict timeptr,
    94116    char *restrict buf);
     117extern char *posix_ctime(const time_t *timer);
    95118extern char *posix_ctime_r(const time_t *timer, char *buf);
     119extern size_t posix_strftime(char *restrict s, size_t maxsize,
     120    const char *restrict format, const struct posix_tm *restrict tm);
    96121
    97122/* Clocks */
     
    109134
    110135#ifndef LIBPOSIX_INTERNAL
     136        #define tm posix_tm
    111137        #define timespec posix_timespec
    112138        #define itimerspec posix_itimerspec
     
    118144        #define tzset posix_tzset
    119145
     146        #define difftime posix_difftime
     147
     148        #define mktime posix_mktime
     149        #define gmtime posix_gmtime
    120150        #define gmtime_r posix_gmtime_r
     151        #define localtime posix_localtime
    121152        #define localtime_r posix_localtime_r
    122153
     154        #define asctime posix_asctime
    123155        #define asctime_r posix_asctime_r
     156        #define ctime posix_ctime
    124157        #define ctime_r posix_ctime_r
     158        #define strftime posix_strftime
    125159
    126160        #define clock_getres posix_clock_getres
  • uspace/srv/locsrv/locsrv.c

    r90478727 r371cb6c  
    13531353        categ_dir_add_cat(&cdir, cat);
    13541354
    1355         cat = category_new("clock");
    1356         categ_dir_add_cat(&cdir, cat);
    1357 
    13581355        cat = category_new("test3");
    13591356        categ_dir_add_cat(&cdir, cat);
Note: See TracChangeset for help on using the changeset viewer.