Changes in / [3123d2a:e1e4192] in mainline
- Files:
-
- 12 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
boot/Makefile.common
r3123d2a re1e4192 185 185 $(USPACE_PATH)/app/vuhid/vuh \ 186 186 $(USPACE_PATH)/app/mkbd/mkbd \ 187 $(USPACE_PATH)/app/websrv/websrv 187 $(USPACE_PATH)/app/websrv/websrv \ 188 $(USPACE_PATH)/app/date/date 188 189 189 190 ifeq ($(CONFIG_PCC),y) -
boot/arch/amd64/Makefile.inc
r3123d2a re1e4192 42 42 char/ps2mouse \ 43 43 char/xtkbd \ 44 time/cmos-rtc \ 44 45 bus/usb/ehci\ 45 46 bus/usb/ohci \ -
uspace/Makefile
r3123d2a re1e4192 71 71 app/sysinfo \ 72 72 app/mkbd \ 73 app/date \ 73 74 app/websrv \ 74 75 srv/clipboard \ … … 123 124 drv/nic/ne2k \ 124 125 drv/nic/e1k \ 125 drv/nic/rtl8139 126 drv/nic/rtl8139 \ 126 127 127 128 ifeq ($(CONFIG_PCC),y) … … 152 153 drv/bus/isa \ 153 154 drv/char/ns8250 \ 155 drv/time/cmos-rtc \ 154 156 srv/hw/irc/apic \ 155 157 srv/hw/irc/i8259 … … 162 164 drv/bus/isa \ 163 165 drv/char/ns8250 \ 166 drv/time/cmos-rtc \ 164 167 srv/hw/irc/apic \ 165 168 srv/hw/irc/i8259 -
uspace/drv/bus/isa/isa.dev
r3123d2a re1e4192 27 27 dma 1 28 28 dma 5 29 30 cmos-rtc: 31 match 100 isa/cmos-rtc 32 io_range 70 2 -
uspace/lib/c/Makefile
r3123d2a re1e4192 69 69 generic/device/hw_res_parsed.c \ 70 70 generic/device/char_dev.c \ 71 generic/device/clock_dev.c \ 71 72 generic/device/nic.c \ 72 73 generic/device/pci.c \ -
uspace/lib/c/generic/time.c
r3123d2a re1e4192 1 1 /* 2 2 * Copyright (c) 2006 Ondrej Palkovsky 3 * Copyright (c) 2011 Petr Koupy 4 * Copyright (c) 2011 Jiri Zarevucky 3 5 * All rights reserved. 4 6 * … … 43 45 #include <ddi.h> 44 46 #include <libc.h> 47 #include <stdint.h> 48 #include <stdio.h> 49 #include <ctype.h> 50 #include <assert.h> 45 51 #include <unistd.h> 52 53 #define ASCTIME_BUF_LEN 26 46 54 47 55 /** Pointer to kernel shared variables with time */ … … 51 59 volatile sysarg_t seconds2; 52 60 } *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 53 394 54 395 /** Add microseconds to given timeval. … … 229 570 } 230 571 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 231 892 /** @} 232 893 */ -
uspace/lib/c/include/ipc/dev_iface.h
r3123d2a re1e4192 52 52 USBHID_DEV_IFACE, 53 53 54 /** Interface provided by Real Time Clock devices */ 55 CLOCK_DEV_IFACE, 56 54 57 DEV_IFACE_MAX 55 58 } dev_inferface_idx_t; -
uspace/lib/c/include/sys/time.h
r3123d2a re1e4192 1 1 /* 2 2 * Copyright (c) 2006 Ondrej Palkovsky 3 * Copyright (c) 2011 Petr Koupy 4 * Copyright (c) 2011 Jiri Zarevucky 3 5 * All rights reserved. 4 6 * … … 39 41 40 42 #define DST_NONE 0 43 #define ASCTIME_BUF_LEN 26 41 44 42 45 typedef long time_t; … … 45 48 typedef uint32_t useconds_t; 46 49 typedef 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 }; 47 62 48 63 struct timeval { … … 64 79 extern void udelay(useconds_t); 65 80 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 66 90 #endif 67 91 -
uspace/lib/drv/Makefile
r3123d2a re1e4192 44 44 generic/remote_pci.c \ 45 45 generic/remote_usbhc.c \ 46 generic/remote_usbhid.c 46 generic/remote_usbhid.c \ 47 generic/remote_clock_dev.c 47 48 48 49 include $(USPACE_PREFIX)/Makefile.common -
uspace/lib/drv/generic/dev_iface.c
r3123d2a re1e4192 41 41 #include "remote_hw_res.h" 42 42 #include "remote_char_dev.h" 43 #include "remote_clock_dev.h" 43 44 #include "remote_nic.h" 44 45 #include "remote_usb.h" … … 55 56 &remote_usb_iface, 56 57 &remote_usbhc_iface, 57 &remote_usbhid_iface 58 &remote_usbhid_iface, 59 &remote_clock_dev_iface, 58 60 } 59 61 }; -
uspace/lib/posix/time.c
r3123d2a re1e4192 141 141 * Used by some functions in this file. 142 142 * 143 * @param op1 Dividen t.143 * @param op1 Dividend. 144 144 * @param op2 Divisor. 145 145 * @return Rounded quotient. … … 158 158 * Used by some functions in this file. 159 159 * 160 * @param op1 Dividen t.160 * @param op1 Dividend. 161 161 * @param op2 Divisor. 162 162 * @return Remainder. … … 196 196 197 197 /** 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 */203 static 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 /**211 198 * Which day of week the specified date is. 212 199 * … … 230 217 * @return 0 on success, -1 on overflow 231 218 */ 232 static int _normalize_time(struct posix_tm *tm, time_t sec_add)219 static int _normalize_time(struct tm *tm, time_t sec_add) 233 220 { 234 221 // TODO: DST correction … … 306 293 } 307 294 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 */315 static 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 */327 static 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 */350 static 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 previous360 * year, and the next week is week 1. Both January 4th and the first Thursday361 * of January are always in week 1.362 *363 * @param tm Normalized broken-down time.364 * @return The week number (1 - 53).365 */366 static 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 */389 static 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 395 295 /******************************************************************************/ 396 296 … … 412 312 413 313 /** 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 */420 double 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 time427 * (moves all values to their proper bounds) and then tries to428 * 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 */433 time_t posix_mktime(struct posix_tm *tm)434 {435 // TODO: take DST flag into account436 // TODO: detect overflow437 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 */448 struct 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 /**457 314 * Converts a time value to a broken-down UTC time. 458 315 * … … 461 318 * @return Value of result on success, NULL on overflow. 462 319 */ 463 struct posix_tm *posix_gmtime_r(const time_t *restrict timer,464 struct posix_tm *restrict result)320 struct tm *posix_gmtime_r(const time_t *restrict timer, 321 struct tm *restrict result) 465 322 { 466 323 assert(timer != NULL); … … 485 342 /** 486 343 * 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 */491 struct 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.499 344 * 500 345 * @param timer Time to convert. … … 502 347 * @return Value of result on success, NULL on overflow. 503 348 */ 504 struct posix_tm *posix_localtime_r(const time_t *restrict timer,505 struct posix_tm *restrict result)349 struct tm *posix_localtime_r(const time_t *restrict timer, 350 struct tm *restrict result) 506 351 { 507 352 // TODO: deal with timezone 508 353 // currently assumes system and all times are in GMT 509 354 return posix_gmtime_r(timer, result); 510 }511 512 /**513 * Converts broken-down time to a string in format514 * "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 */519 char *posix_asctime(const struct posix_tm *timeptr)520 {521 static char buf[ASCTIME_BUF_LEN];522 return posix_asctime_r(timeptr, buf);523 355 } 524 356 … … 532 364 * @return Value of buf. 533 365 */ 534 char *posix_asctime_r(const struct posix_tm *restrict timeptr,366 char *posix_asctime_r(const struct tm *restrict timeptr, 535 367 char *restrict buf) 536 368 { … … 557 389 558 390 /** 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 */564 char *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 /**574 391 * Reentrant variant of ctime(). 575 392 * … … 581 398 char *posix_ctime_r(const time_t *timer, char *buf) 582 399 { 583 struct posix_tm loctime;400 struct tm loctime; 584 401 if (posix_localtime_r(timer, &loctime) == NULL) { 585 402 return NULL; 586 403 } 587 404 return posix_asctime_r(&loctime, buf); 588 }589 590 /**591 * Convert time and date to a string, based on a specified format and592 * 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 */600 size_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 locale608 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: padding665 format++;666 }667 while (isdigit(*format)) {668 // TODO: padding669 format++;670 }671 if (*format == 'O' || *format == 'E') {672 // TODO: locale's alternative format673 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 format687 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 format748 recurse("%Y-%m-%d"); break;749 case 'X':750 // TODO: locale-specific time format751 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: timezone758 break;759 case 'Z':760 // TODO: timezone761 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 append777 #undef recurse778 779 return maxsize - remaining;780 405 } 781 406 … … 894 519 stats_task_t *task_stats = stats_get_task(task_get_id()); 895 520 if (task_stats) { 896 total_cycles = (posix_clock_t) (task_stats->kcycles + task_stats->ucycles); 521 total_cycles = (posix_clock_t) (task_stats->kcycles + 522 task_stats->ucycles); 897 523 free(task_stats); 898 524 task_stats = 0; -
uspace/lib/posix/time.h
r3123d2a re1e4192 63 63 #endif 64 64 65 #undef ASCTIME_BUF_LEN66 #define ASCTIME_BUF_LEN 2667 68 65 #undef CLOCK_REALTIME 69 66 #define CLOCK_REALTIME ((posix_clockid_t) 0) 70 71 struct 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 };82 67 83 68 struct posix_timespec { … … 99 84 extern void posix_tzset(void); 100 85 101 /* Elapsed Time */102 extern double posix_difftime(time_t time1, time_t time0);103 104 86 /* Broken-down Time */ 105 extern time_t posix_mktime(struct posix_tm *tm); 106 extern struct posix_tm *posix_gmtime(const time_t *timer); 107 extern struct posix_tm *posix_gmtime_r(const time_t *restrict timer, 108 struct posix_tm *restrict result); 109 extern struct posix_tm *posix_localtime(const time_t *timer); 110 extern struct posix_tm *posix_localtime_r(const time_t *restrict timer, 111 struct posix_tm *restrict result); 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); 112 91 113 92 /* Formatting Calendar Time */ 114 extern char *posix_asctime(const struct posix_tm *timeptr); 115 extern char *posix_asctime_r(const struct posix_tm *restrict timeptr, 93 extern char *posix_asctime_r(const struct tm *restrict timeptr, 116 94 char *restrict buf); 117 extern char *posix_ctime(const time_t *timer);118 95 extern char *posix_ctime_r(const time_t *timer, char *buf); 119 extern size_t posix_strftime(char *restrict s, size_t maxsize,120 const char *restrict format, const struct posix_tm *restrict tm);121 96 122 97 /* Clocks */ … … 134 109 135 110 #ifndef LIBPOSIX_INTERNAL 136 #define tm posix_tm137 111 #define timespec posix_timespec 138 112 #define itimerspec posix_itimerspec … … 144 118 #define tzset posix_tzset 145 119 146 #define difftime posix_difftime147 148 #define mktime posix_mktime149 #define gmtime posix_gmtime150 120 #define gmtime_r posix_gmtime_r 151 #define localtime posix_localtime152 121 #define localtime_r posix_localtime_r 153 122 154 #define asctime posix_asctime155 123 #define asctime_r posix_asctime_r 156 #define ctime posix_ctime157 124 #define ctime_r posix_ctime_r 158 #define strftime posix_strftime159 125 160 126 #define clock_getres posix_clock_getres -
uspace/srv/locsrv/locsrv.c
r3123d2a re1e4192 1307 1307 categ_dir_add_cat(&cdir, cat); 1308 1308 1309 cat = category_new("clock"); 1310 categ_dir_add_cat(&cdir, cat); 1311 1309 1312 cat = category_new("test3"); 1310 1313 categ_dir_add_cat(&cdir, cat);
Note:
See TracChangeset
for help on using the changeset viewer.