Changes in / [5d94b16c:4c84ada5] in mainline
- Files:
-
- 12 added
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
boot/Makefile.common
r5d94b16c r4c84ada5 196 196 $(USPACE_PATH)/app/mkbd/mkbd \ 197 197 $(USPACE_PATH)/app/websrv/websrv \ 198 $(USPACE_PATH)/app/date/date \ 199 $(USPACE_PATH)/app/vdemo/vdemo \ 200 $(USPACE_PATH)/app/vlaunch/vlaunch \ 201 $(USPACE_PATH)/app/vterm/vterm \ 198 202 $(USPACE_PATH)/app/vdemo/vdemo 199 203 -
boot/arch/amd64/Makefile.inc
r5d94b16c r4c84ada5 42 42 char/ps2mouse \ 43 43 char/xtkbd \ 44 time/cmos-rtc \ 44 45 bus/usb/ehci\ 45 46 bus/usb/ohci \ -
uspace/Makefile
r5d94b16c r4c84ada5 71 71 app/sysinfo \ 72 72 app/mkbd \ 73 app/date \ 73 74 app/websrv \ 74 75 app/vdemo \ … … 133 134 drv/nic/ne2k \ 134 135 drv/nic/e1k \ 135 drv/nic/rtl8139 136 drv/nic/rtl8139 \ 136 137 137 138 ifeq ($(CONFIG_PCC),y) … … 162 163 drv/bus/isa \ 163 164 drv/char/ns8250 \ 165 drv/time/cmos-rtc \ 164 166 srv/hw/irc/apic \ 165 167 srv/hw/irc/i8259 … … 172 174 drv/bus/isa \ 173 175 drv/char/ns8250 \ 176 drv/time/cmos-rtc \ 174 177 srv/hw/irc/apic \ 175 178 srv/hw/irc/i8259 -
uspace/drv/bus/isa/isa.dev
r5d94b16c r4c84ada5 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
r5d94b16c r4c84ada5 71 71 generic/device/hw_res_parsed.c \ 72 72 generic/device/char_dev.c \ 73 generic/device/clock_dev.c \ 73 74 generic/device/graph_dev.c \ 74 75 generic/device/nic.c \ -
uspace/lib/c/generic/async.c
r5d94b16c r4c84ada5 638 638 639 639 if (usecs) { 640 get timeofday(&conn->wdata.to_event.expires, NULL);640 getuptime(&conn->wdata.to_event.expires); 641 641 tv_add(&conn->wdata.to_event.expires, usecs); 642 642 } else … … 967 967 { 968 968 struct timeval tv; 969 get timeofday(&tv, NULL);969 getuptime(&tv); 970 970 971 971 futex_down(&async_futex); … … 1024 1024 1025 1025 struct timeval tv; 1026 get timeofday(&tv, NULL);1026 getuptime(&tv); 1027 1027 1028 1028 if (tv_gteq(&tv, &waiter->to_event.expires)) { … … 1331 1331 timeout = 0; 1332 1332 1333 get timeofday(&msg->wdata.to_event.expires, NULL);1333 getuptime(&msg->wdata.to_event.expires); 1334 1334 tv_add(&msg->wdata.to_event.expires, timeout); 1335 1335 … … 1413 1413 msg->wdata.fid = fibril_get_id(); 1414 1414 1415 get timeofday(&msg->wdata.to_event.expires, NULL);1415 getuptime(&msg->wdata.to_event.expires); 1416 1416 tv_add(&msg->wdata.to_event.expires, timeout); 1417 1417 -
uspace/lib/c/generic/fibril_synch.c
r5d94b16c r4c84ada5 379 379 futex_down(&async_futex); 380 380 if (timeout) { 381 get timeofday(&wdata.to_event.expires, NULL);381 getuptime(&wdata.to_event.expires); 382 382 tv_add(&wdata.to_event.expires, timeout); 383 383 async_insert_timeout(&wdata); -
uspace/lib/c/generic/time.c
r5d94b16c r4c84ada5 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 #include <loc.h> 53 #include <device/clock_dev.h> 54 #include <malloc.h> 55 56 #define ASCTIME_BUF_LEN 26 46 57 47 58 /** Pointer to kernel shared variables with time */ … … 52 63 } *ktime = NULL; 53 64 65 /* Helper functions ***********************************************************/ 66 67 #define HOURS_PER_DAY (24) 68 #define MINS_PER_HOUR (60) 69 #define SECS_PER_MIN (60) 70 #define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY) 71 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR) 72 #define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY) 73 74 /** 75 * Checks whether the year is a leap year. 76 * 77 * @param year Year since 1900 (e.g. for 1970, the value is 70). 78 * @return true if year is a leap year, false otherwise 79 */ 80 static bool _is_leap_year(time_t year) 81 { 82 year += 1900; 83 84 if (year % 400 == 0) 85 return true; 86 if (year % 100 == 0) 87 return false; 88 if (year % 4 == 0) 89 return true; 90 return false; 91 } 92 93 /** 94 * Returns how many days there are in the given month of the given year. 95 * Note that year is only taken into account if month is February. 96 * 97 * @param year Year since 1900 (can be negative). 98 * @param mon Month of the year. 0 for January, 11 for December. 99 * @return Number of days in the specified month. 100 */ 101 static int _days_in_month(time_t year, time_t mon) 102 { 103 assert(mon >= 0 && mon <= 11); 104 105 static int month_days[] = 106 { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 107 108 if (mon == 1) { 109 year += 1900; 110 /* february */ 111 return _is_leap_year(year) ? 29 : 28; 112 } else { 113 return month_days[mon]; 114 } 115 } 116 117 /** 118 * For specified year, month and day of month, returns which day of that year 119 * it is. 120 * 121 * For example, given date 2011-01-03, the corresponding expression is: 122 * _day_of_year(111, 0, 3) == 2 123 * 124 * @param year Year (year 1900 = 0, can be negative). 125 * @param mon Month (January = 0). 126 * @param mday Day of month (First day is 1). 127 * @return Day of year (First day is 0). 128 */ 129 static int _day_of_year(time_t year, time_t mon, time_t mday) 130 { 131 static int mdays[] = 132 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; 133 static int leap_mdays[] = 134 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; 135 136 return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1; 137 } 138 139 /** 140 * Integer division that rounds to negative infinity. 141 * Used by some functions in this file. 142 * 143 * @param op1 Dividend. 144 * @param op2 Divisor. 145 * @return Rounded quotient. 146 */ 147 static time_t _floor_div(time_t op1, time_t op2) 148 { 149 if (op1 >= 0 || op1 % op2 == 0) { 150 return op1 / op2; 151 } else { 152 return op1 / op2 - 1; 153 } 154 } 155 156 /** 157 * Modulo that rounds to negative infinity. 158 * Used by some functions in this file. 159 * 160 * @param op1 Dividend. 161 * @param op2 Divisor. 162 * @return Remainder. 163 */ 164 static time_t _floor_mod(time_t op1, time_t op2) 165 { 166 int div = _floor_div(op1, op2); 167 168 /* (a / b) * b + a % b == a */ 169 /* thus, a % b == a - (a / b) * b */ 170 171 int result = op1 - div * op2; 172 173 /* Some paranoid checking to ensure I didn't make a mistake here. */ 174 assert(result >= 0); 175 assert(result < op2); 176 assert(div * op2 + result == op1); 177 178 return result; 179 } 180 181 /** 182 * Number of days since the Epoch. 183 * Epoch is 1970-01-01, which is also equal to day 0. 184 * 185 * @param year Year (year 1900 = 0, may be negative). 186 * @param mon Month (January = 0). 187 * @param mday Day of month (first day = 1). 188 * @return Number of days since the Epoch. 189 */ 190 static time_t _days_since_epoch(time_t year, time_t mon, time_t mday) 191 { 192 return (year - 70) * 365 + _floor_div(year - 69, 4) - 193 _floor_div(year - 1, 100) + _floor_div(year + 299, 400) + 194 _day_of_year(year, mon, mday); 195 } 196 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 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 * Which day of week the specified date is. 212 * 213 * @param year Year (year 1900 = 0). 214 * @param mon Month (January = 0). 215 * @param mday Day of month (first = 1). 216 * @return Day of week (Sunday = 0). 217 */ 218 static int _day_of_week(time_t year, time_t mon, time_t mday) 219 { 220 /* 1970-01-01 is Thursday */ 221 return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7); 222 } 223 224 /** 225 * Normalizes the broken-down time and optionally adds specified amount of 226 * seconds. 227 * 228 * @param tm Broken-down time to normalize. 229 * @param sec_add Seconds to add. 230 * @return 0 on success, -1 on overflow 231 */ 232 static int _normalize_time(struct tm *tm, time_t sec_add) 233 { 234 // TODO: DST correction 235 236 /* Set initial values. */ 237 time_t sec = tm->tm_sec + sec_add; 238 time_t min = tm->tm_min; 239 time_t hour = tm->tm_hour; 240 time_t day = tm->tm_mday - 1; 241 time_t mon = tm->tm_mon; 242 time_t year = tm->tm_year; 243 244 /* Adjust time. */ 245 min += _floor_div(sec, SECS_PER_MIN); 246 sec = _floor_mod(sec, SECS_PER_MIN); 247 hour += _floor_div(min, MINS_PER_HOUR); 248 min = _floor_mod(min, MINS_PER_HOUR); 249 day += _floor_div(hour, HOURS_PER_DAY); 250 hour = _floor_mod(hour, HOURS_PER_DAY); 251 252 /* Adjust month. */ 253 year += _floor_div(mon, 12); 254 mon = _floor_mod(mon, 12); 255 256 /* Now the difficult part - days of month. */ 257 258 /* First, deal with whole cycles of 400 years = 146097 days. */ 259 year += _floor_div(day, 146097) * 400; 260 day = _floor_mod(day, 146097); 261 262 /* Then, go in one year steps. */ 263 if (mon <= 1) { 264 /* January and February. */ 265 while (day > 365) { 266 day -= _is_leap_year(year) ? 366 : 365; 267 year++; 268 } 269 } else { 270 /* Rest of the year. */ 271 while (day > 365) { 272 day -= _is_leap_year(year + 1) ? 366 : 365; 273 year++; 274 } 275 } 276 277 /* Finally, finish it off month per month. */ 278 while (day >= _days_in_month(year, mon)) { 279 day -= _days_in_month(year, mon); 280 mon++; 281 if (mon >= 12) { 282 mon -= 12; 283 year++; 284 } 285 } 286 287 /* Calculate the remaining two fields. */ 288 tm->tm_yday = _day_of_year(year, mon, day + 1); 289 tm->tm_wday = _day_of_week(year, mon, day + 1); 290 291 /* And put the values back to the struct. */ 292 tm->tm_sec = (int) sec; 293 tm->tm_min = (int) min; 294 tm->tm_hour = (int) hour; 295 tm->tm_mday = (int) day + 1; 296 tm->tm_mon = (int) mon; 297 298 /* Casts to work around libc brain-damage. */ 299 if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) { 300 tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX); 301 return -1; 302 } 303 304 tm->tm_year = (int) year; 305 return 0; 306 } 307 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 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 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 */ 366 static int _iso_week_number(const struct 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 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 /******************************************************************************/ 396 397 54 398 /** Add microseconds to given timeval. 55 399 * … … 139 483 */ 140 484 int gettimeofday(struct timeval *tv, struct timezone *tz) 485 { 486 int rc; 487 struct tm t; 488 category_id_t cat_id; 489 size_t svc_cnt; 490 service_id_t *svc_ids = NULL; 491 service_id_t svc_id; 492 char *svc_name = NULL; 493 494 static async_sess_t *clock_conn = NULL; 495 496 if (tz) { 497 tz->tz_minuteswest = 0; 498 tz->tz_dsttime = DST_NONE; 499 } 500 501 if (clock_conn == NULL) { 502 rc = loc_category_get_id("clock", &cat_id, IPC_FLAG_BLOCKING); 503 if (rc != EOK) 504 goto ret_uptime; 505 506 rc = loc_category_get_svcs(cat_id, &svc_ids, &svc_cnt); 507 if (rc != EOK) 508 goto ret_uptime; 509 510 if (svc_cnt == 0) 511 goto ret_uptime; 512 513 rc = loc_service_get_name(svc_ids[0], &svc_name); 514 if (rc != EOK) 515 goto ret_uptime; 516 517 rc = loc_service_get_id(svc_name, &svc_id, 0); 518 if (rc != EOK) 519 goto ret_uptime; 520 521 clock_conn = loc_service_connect(EXCHANGE_SERIALIZE, 522 svc_id, IPC_FLAG_BLOCKING); 523 if (!clock_conn) 524 goto ret_uptime; 525 } 526 527 rc = clock_dev_time_get(clock_conn, &t); 528 if (rc != EOK) 529 goto ret_uptime; 530 531 tv->tv_usec = 0; 532 tv->tv_sec = mktime(&t); 533 534 free(svc_name); 535 free(svc_ids); 536 537 return EOK; 538 539 ret_uptime: 540 541 free(svc_name); 542 free(svc_ids); 543 544 return getuptime(tv); 545 } 546 547 int getuptime(struct timeval *tv) 141 548 { 142 549 if (ktime == NULL) { … … 160 567 } 161 568 162 if (tz) {163 tz->tz_minuteswest = 0;164 tz->tz_dsttime = DST_NONE;165 }166 167 569 sysarg_t s2 = ktime->seconds2; 168 570 … … 178 580 } else 179 581 tv->tv_sec = s1; 180 582 181 583 return 0; 182 584 } … … 229 631 } 230 632 633 /** 634 * This function first normalizes the provided broken-down time 635 * (moves all values to their proper bounds) and then tries to 636 * calculate the appropriate time_t representation. 637 * 638 * @param tm Broken-down time. 639 * @return time_t representation of the time, undefined value on overflow. 640 */ 641 time_t mktime(struct tm *tm) 642 { 643 // TODO: take DST flag into account 644 // TODO: detect overflow 645 646 _normalize_time(tm, 0); 647 return _secs_since_epoch(tm); 648 } 649 650 /** 651 * Convert time and date to a string, based on a specified format and 652 * current locale. 653 * 654 * @param s Buffer to write string to. 655 * @param maxsize Size of the buffer. 656 * @param format Format of the output. 657 * @param tm Broken-down time to format. 658 * @return Number of bytes written. 659 */ 660 size_t strftime(char *restrict s, size_t maxsize, 661 const char *restrict format, const struct tm *restrict tm) 662 { 663 assert(s != NULL); 664 assert(format != NULL); 665 assert(tm != NULL); 666 667 // TODO: use locale 668 static const char *wday_abbr[] = { 669 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 670 }; 671 static const char *wday[] = { 672 "Sunday", "Monday", "Tuesday", "Wednesday", 673 "Thursday", "Friday", "Saturday" 674 }; 675 static const char *mon_abbr[] = { 676 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 677 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 678 }; 679 static const char *mon[] = { 680 "January", "February", "March", "April", "May", "June", "July", 681 "August", "September", "October", "November", "December" 682 }; 683 684 if (maxsize < 1) { 685 return 0; 686 } 687 688 char *ptr = s; 689 size_t consumed; 690 size_t remaining = maxsize; 691 692 #define append(...) { \ 693 /* FIXME: this requires POSIX-correct snprintf */ \ 694 /* otherwise it won't work with non-ascii chars */ \ 695 consumed = snprintf(ptr, remaining, __VA_ARGS__); \ 696 if (consumed >= remaining) { \ 697 return 0; \ 698 } \ 699 ptr += consumed; \ 700 remaining -= consumed; \ 701 } 702 703 #define recurse(fmt) { \ 704 consumed = strftime(ptr, remaining, fmt, tm); \ 705 if (consumed == 0) { \ 706 return 0; \ 707 } \ 708 ptr += consumed; \ 709 remaining -= consumed; \ 710 } 711 712 #define TO_12H(hour) (((hour) > 12) ? ((hour) - 12) : \ 713 (((hour) == 0) ? 12 : (hour))) 714 715 while (*format != '\0') { 716 if (*format != '%') { 717 append("%c", *format); 718 format++; 719 continue; 720 } 721 722 format++; 723 if (*format == '0' || *format == '+') { 724 // TODO: padding 725 format++; 726 } 727 while (isdigit(*format)) { 728 // TODO: padding 729 format++; 730 } 731 if (*format == 'O' || *format == 'E') { 732 // TODO: locale's alternative format 733 format++; 734 } 735 736 switch (*format) { 737 case 'a': 738 append("%s", wday_abbr[tm->tm_wday]); break; 739 case 'A': 740 append("%s", wday[tm->tm_wday]); break; 741 case 'b': 742 append("%s", mon_abbr[tm->tm_mon]); break; 743 case 'B': 744 append("%s", mon[tm->tm_mon]); break; 745 case 'c': 746 // TODO: locale-specific datetime format 747 recurse("%Y-%m-%d %H:%M:%S"); break; 748 case 'C': 749 append("%02d", (1900 + tm->tm_year) / 100); break; 750 case 'd': 751 append("%02d", tm->tm_mday); break; 752 case 'D': 753 recurse("%m/%d/%y"); break; 754 case 'e': 755 append("%2d", tm->tm_mday); break; 756 case 'F': 757 recurse("%+4Y-%m-%d"); break; 758 case 'g': 759 append("%02d", _wbyear(tm) % 100); break; 760 case 'G': 761 append("%d", _wbyear(tm)); break; 762 case 'h': 763 recurse("%b"); break; 764 case 'H': 765 append("%02d", tm->tm_hour); break; 766 case 'I': 767 append("%02d", TO_12H(tm->tm_hour)); break; 768 case 'j': 769 append("%03d", tm->tm_yday); break; 770 case 'k': 771 append("%2d", tm->tm_hour); break; 772 case 'l': 773 append("%2d", TO_12H(tm->tm_hour)); break; 774 case 'm': 775 append("%02d", tm->tm_mon); break; 776 case 'M': 777 append("%02d", tm->tm_min); break; 778 case 'n': 779 append("\n"); break; 780 case 'p': 781 append("%s", tm->tm_hour < 12 ? "AM" : "PM"); break; 782 case 'P': 783 append("%s", tm->tm_hour < 12 ? "am" : "PM"); break; 784 case 'r': 785 recurse("%I:%M:%S %p"); break; 786 case 'R': 787 recurse("%H:%M"); break; 788 case 's': 789 append("%ld", _secs_since_epoch(tm)); break; 790 case 'S': 791 append("%02d", tm->tm_sec); break; 792 case 't': 793 append("\t"); break; 794 case 'T': 795 recurse("%H:%M:%S"); break; 796 case 'u': 797 append("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday); 798 break; 799 case 'U': 800 append("%02d", _sun_week_number(tm)); break; 801 case 'V': 802 append("%02d", _iso_week_number(tm)); break; 803 case 'w': 804 append("%d", tm->tm_wday); break; 805 case 'W': 806 append("%02d", _mon_week_number(tm)); break; 807 case 'x': 808 // TODO: locale-specific date format 809 recurse("%Y-%m-%d"); break; 810 case 'X': 811 // TODO: locale-specific time format 812 recurse("%H:%M:%S"); break; 813 case 'y': 814 append("%02d", tm->tm_year % 100); break; 815 case 'Y': 816 append("%d", 1900 + tm->tm_year); break; 817 case 'z': 818 // TODO: timezone 819 break; 820 case 'Z': 821 // TODO: timezone 822 break; 823 case '%': 824 append("%%"); 825 break; 826 default: 827 /* Invalid specifier, print verbatim. */ 828 while (*format != '%') { 829 format--; 830 } 831 append("%%"); 832 break; 833 } 834 format++; 835 } 836 837 #undef append 838 #undef recurse 839 840 return maxsize - remaining; 841 } 842 843 844 /** Converts a time value to a broken-down UTC time 845 * 846 * @param time Time to convert 847 * @param result Structure to store the result to 848 * 849 * @return EOK or a negative error code 850 */ 851 int time_utc2tm(const time_t time, struct tm *restrict result) 852 { 853 assert(result != NULL); 854 855 /* Set result to epoch. */ 856 result->tm_sec = 0; 857 result->tm_min = 0; 858 result->tm_hour = 0; 859 result->tm_mday = 1; 860 result->tm_mon = 0; 861 result->tm_year = 70; /* 1970 */ 862 863 if (_normalize_time(result, time) == -1) 864 return EOVERFLOW; 865 866 return EOK; 867 } 868 869 /** Converts a time value to a null terminated string of the form 870 * "Wed Jun 30 21:49:08 1993\n" expressed in UTC. 871 * 872 * @param time Time to convert. 873 * @param buf Buffer to store the string to, must be at least 874 * ASCTIME_BUF_LEN bytes long. 875 * 876 * @return EOK or a negative error code. 877 */ 878 int time_utc2str(const time_t time, char *restrict buf) 879 { 880 struct tm t; 881 int r; 882 883 if ((r = time_utc2tm(time, &t)) != EOK) 884 return r; 885 886 time_tm2str(&t, buf); 887 return EOK; 888 } 889 890 891 /** 892 * Converts broken-down time to a string in format 893 * "Sun Jan 1 00:00:00 1970\n". (Obsolete) 894 * 895 * @param timeptr Broken-down time structure. 896 * @param buf Buffer to store string to, must be at least ASCTIME_BUF_LEN 897 * bytes long. 898 */ 899 void time_tm2str(const struct tm *restrict timeptr, char *restrict buf) 900 { 901 assert(timeptr != NULL); 902 assert(buf != NULL); 903 904 static const char *wday[] = { 905 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 906 }; 907 static const char *mon[] = { 908 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 909 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 910 }; 911 912 snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n", 913 wday[timeptr->tm_wday], 914 mon[timeptr->tm_mon], 915 timeptr->tm_mday, timeptr->tm_hour, 916 timeptr->tm_min, timeptr->tm_sec, 917 1900 + timeptr->tm_year); 918 } 919 920 /** 921 * Converts a time value to a broken-down local time, expressed relative 922 * to the user's specified timezone. 923 * 924 * @param timer Time to convert. 925 * @param result Structure to store the result to. 926 * 927 * @return EOK on success or a negative error code. 928 */ 929 int time_local2tm(const time_t time, struct tm *restrict result) 930 { 931 // TODO: deal with timezone 932 // currently assumes system and all times are in GMT 933 934 /* Set result to epoch. */ 935 result->tm_sec = 0; 936 result->tm_min = 0; 937 result->tm_hour = 0; 938 result->tm_mday = 1; 939 result->tm_mon = 0; 940 result->tm_year = 70; /* 1970 */ 941 942 if (_normalize_time(result, time) == -1) 943 return EOVERFLOW; 944 945 return EOK; 946 } 947 948 /** 949 * Converts the calendar time to a null terminated string 950 * of the form "Wed Jun 30 21:49:08 1993\n" expressed relative to the 951 * user's specified timezone. 952 * 953 * @param timer Time to convert. 954 * @param buf Buffer to store the string to. Must be at least 955 * ASCTIME_BUF_LEN bytes long. 956 * 957 * @return EOK on success or a negative error code. 958 */ 959 int time_local2str(const time_t time, char *buf) 960 { 961 struct tm loctime; 962 int r; 963 964 if ((r = time_local2tm(time, &loctime)) != EOK) 965 return r; 966 967 time_tm2str(&loctime, buf); 968 969 return EOK; 970 } 971 972 /** 973 * Calculate the difference between two times, in seconds. 974 * 975 * @param time1 First time. 976 * @param time0 Second time. 977 * @return Time in seconds. 978 */ 979 double difftime(time_t time1, time_t time0) 980 { 981 return (double) (time1 - time0); 982 } 983 231 984 /** @} 232 985 */ -
uspace/lib/c/include/ipc/dev_iface.h
r5d94b16c r4c84ada5 54 54 /** Interface provided by USB HID devices. */ 55 55 USBHID_DEV_IFACE, 56 /** Interface provided by Real Time Clock devices */ 57 CLOCK_DEV_IFACE, 56 58 /** Interface provided by AHCI devices. */ 57 59 AHCI_DEV_IFACE, -
uspace/lib/c/include/sys/time.h
r5d94b16c r4c84ada5 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 { … … 61 76 extern int tv_gteq(struct timeval *tv1, struct timeval *tv2); 62 77 extern int gettimeofday(struct timeval *tv, struct timezone *tz); 78 extern int getuptime(struct timeval *tv); 63 79 64 80 extern void udelay(useconds_t); 81 82 extern time_t mktime(struct tm *tm); 83 extern int time_utc2tm(const time_t time, struct tm *result); 84 extern int time_utc2str(const time_t time, char *buf); 85 extern void time_tm2str(const struct tm *timeptr, char *buf); 86 extern int time_local2tm(const time_t time, struct tm *result); 87 extern int time_local2str(const time_t time, char *buf); 88 extern double difftime(time_t time1, time_t time0); 89 extern size_t strftime(char *restrict s, size_t maxsize, 90 const char *restrict format, const struct tm *restrict tm); 65 91 66 92 #endif -
uspace/lib/drv/Makefile
r5d94b16c r4c84ada5 46 46 generic/remote_usbhc.c \ 47 47 generic/remote_usbhid.c \ 48 generic/remote_clock_dev.c \ 48 49 generic/remote_ahci.c 49 50 -
uspace/lib/drv/generic/dev_iface.c
r5d94b16c r4c84ada5 41 41 #include "remote_hw_res.h" 42 42 #include "remote_char_dev.h" 43 #include "remote_clock_dev.h" 43 44 #include "remote_graph_dev.h" 44 45 #include "remote_nic.h" … … 59 60 &remote_usbhc_iface, 60 61 &remote_usbhid_iface, 62 &remote_clock_dev_iface, 61 63 &remote_ahci_iface 62 64 } -
uspace/lib/posix/time.c
r5d94b16c r4c84ada5 61 61 */ 62 62 63 64 65 /* Helper functions ***********************************************************/66 67 #define HOURS_PER_DAY (24)68 #define MINS_PER_HOUR (60)69 #define SECS_PER_MIN (60)70 #define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY)71 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)72 #define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY)73 74 /**75 * Checks whether the year is a leap year.76 *77 * @param year Year since 1900 (e.g. for 1970, the value is 70).78 * @return true if year is a leap year, false otherwise79 */80 static bool _is_leap_year(time_t year)81 {82 year += 1900;83 84 if (year % 400 == 0)85 return true;86 if (year % 100 == 0)87 return false;88 if (year % 4 == 0)89 return true;90 return false;91 }92 93 /**94 * Returns how many days there are in the given month of the given year.95 * Note that year is only taken into account if month is February.96 *97 * @param year Year since 1900 (can be negative).98 * @param mon Month of the year. 0 for January, 11 for December.99 * @return Number of days in the specified month.100 */101 static int _days_in_month(time_t year, time_t mon)102 {103 assert(mon >= 0 && mon <= 11);104 105 static int month_days[] =106 { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };107 108 if (mon == 1) {109 year += 1900;110 /* february */111 return _is_leap_year(year) ? 29 : 28;112 } else {113 return month_days[mon];114 }115 }116 117 /**118 * For specified year, month and day of month, returns which day of that year119 * it is.120 *121 * For example, given date 2011-01-03, the corresponding expression is:122 * _day_of_year(111, 0, 3) == 2123 *124 * @param year Year (year 1900 = 0, can be negative).125 * @param mon Month (January = 0).126 * @param mday Day of month (First day is 1).127 * @return Day of year (First day is 0).128 */129 static int _day_of_year(time_t year, time_t mon, time_t mday)130 {131 static int mdays[] =132 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };133 static int leap_mdays[] =134 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };135 136 return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1;137 }138 139 /**140 * Integer division that rounds to negative infinity.141 * Used by some functions in this file.142 *143 * @param op1 Divident.144 * @param op2 Divisor.145 * @return Rounded quotient.146 */147 static time_t _floor_div(time_t op1, time_t op2)148 {149 if (op1 >= 0 || op1 % op2 == 0) {150 return op1 / op2;151 } else {152 return op1 / op2 - 1;153 }154 }155 156 /**157 * Modulo that rounds to negative infinity.158 * Used by some functions in this file.159 *160 * @param op1 Divident.161 * @param op2 Divisor.162 * @return Remainder.163 */164 static time_t _floor_mod(time_t op1, time_t op2)165 {166 int div = _floor_div(op1, op2);167 168 /* (a / b) * b + a % b == a */169 /* thus, a % b == a - (a / b) * b */170 171 int result = op1 - div * op2;172 173 /* Some paranoid checking to ensure I didn't make a mistake here. */174 assert(result >= 0);175 assert(result < op2);176 assert(div * op2 + result == op1);177 178 return result;179 }180 181 /**182 * Number of days since the Epoch.183 * Epoch is 1970-01-01, which is also equal to day 0.184 *185 * @param year Year (year 1900 = 0, may be negative).186 * @param mon Month (January = 0).187 * @param mday Day of month (first day = 1).188 * @return Number of days since the Epoch.189 */190 static time_t _days_since_epoch(time_t year, time_t mon, time_t mday)191 {192 return (year - 70) * 365 + _floor_div(year - 69, 4) -193 _floor_div(year - 1, 100) + _floor_div(year + 299, 400) +194 _day_of_year(year, mon, mday);195 }196 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 * Which day of week the specified date is.212 *213 * @param year Year (year 1900 = 0).214 * @param mon Month (January = 0).215 * @param mday Day of month (first = 1).216 * @return Day of week (Sunday = 0).217 */218 static int _day_of_week(time_t year, time_t mon, time_t mday)219 {220 /* 1970-01-01 is Thursday */221 return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7);222 }223 224 /**225 * Normalizes the broken-down time and optionally adds specified amount of226 * seconds.227 *228 * @param tm Broken-down time to normalize.229 * @param sec_add Seconds to add.230 * @return 0 on success, -1 on overflow231 */232 static int _normalize_time(struct posix_tm *tm, time_t sec_add)233 {234 // TODO: DST correction235 236 /* Set initial values. */237 time_t sec = tm->tm_sec + sec_add;238 time_t min = tm->tm_min;239 time_t hour = tm->tm_hour;240 time_t day = tm->tm_mday - 1;241 time_t mon = tm->tm_mon;242 time_t year = tm->tm_year;243 244 /* Adjust time. */245 min += _floor_div(sec, SECS_PER_MIN);246 sec = _floor_mod(sec, SECS_PER_MIN);247 hour += _floor_div(min, MINS_PER_HOUR);248 min = _floor_mod(min, MINS_PER_HOUR);249 day += _floor_div(hour, HOURS_PER_DAY);250 hour = _floor_mod(hour, HOURS_PER_DAY);251 252 /* Adjust month. */253 year += _floor_div(mon, 12);254 mon = _floor_mod(mon, 12);255 256 /* Now the difficult part - days of month. */257 258 /* First, deal with whole cycles of 400 years = 146097 days. */259 year += _floor_div(day, 146097) * 400;260 day = _floor_mod(day, 146097);261 262 /* Then, go in one year steps. */263 if (mon <= 1) {264 /* January and February. */265 while (day > 365) {266 day -= _is_leap_year(year) ? 366 : 365;267 year++;268 }269 } else {270 /* Rest of the year. */271 while (day > 365) {272 day -= _is_leap_year(year + 1) ? 366 : 365;273 year++;274 }275 }276 277 /* Finally, finish it off month per month. */278 while (day >= _days_in_month(year, mon)) {279 day -= _days_in_month(year, mon);280 mon++;281 if (mon >= 12) {282 mon -= 12;283 year++;284 }285 }286 287 /* Calculate the remaining two fields. */288 tm->tm_yday = _day_of_year(year, mon, day + 1);289 tm->tm_wday = _day_of_week(year, mon, day + 1);290 291 /* And put the values back to the struct. */292 tm->tm_sec = (int) sec;293 tm->tm_min = (int) min;294 tm->tm_hour = (int) hour;295 tm->tm_mday = (int) day + 1;296 tm->tm_mon = (int) mon;297 298 /* Casts to work around libc brain-damage. */299 if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) {300 tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX);301 return -1;302 }303 304 tm->tm_year = (int) year;305 return 0;306 }307 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 /******************************************************************************/396 397 63 int posix_daylight; 398 64 long posix_timezone; … … 412 78 413 79 /** 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 80 * Converts a time value to a broken-down UTC time. 458 81 * … … 461 84 * @return Value of result on success, NULL on overflow. 462 85 */ 463 struct posix_tm *posix_gmtime_r(const time_t *restrict timer, 464 struct posix_tm *restrict result) 465 { 466 assert(timer != NULL); 467 assert(result != NULL); 468 469 /* Set result to epoch. */ 470 result->tm_sec = 0; 471 result->tm_min = 0; 472 result->tm_hour = 0; 473 result->tm_mday = 1; 474 result->tm_mon = 0; 475 result->tm_year = 70; /* 1970 */ 476 477 if (_normalize_time(result, *timer) == -1) { 478 errno = EOVERFLOW; 86 struct tm *posix_gmtime_r(const time_t *restrict timer, 87 struct tm *restrict result) 88 { 89 int rc = time_utc2tm(*timer, result); 90 if (rc != EOK) { 91 errno = rc; 479 92 return NULL; 480 93 } … … 484 97 485 98 /** 486 * 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); 99 * Converts a time value to a broken-down UTC time. 100 * (non reentrant version) 101 * 102 * @param timep Time to convert 103 * @return Pointer to a statically allocated structure that stores 104 * the result, NULL in case of error. 105 */ 106 struct tm *posix_gmtime(const time_t *restrict timep) 107 { 108 static struct tm result; 109 110 return posix_gmtime_r(timep, &result); 495 111 } 496 112 … … 502 118 * @return Value of result on success, NULL on overflow. 503 119 */ 504 struct posix_tm *posix_localtime_r(const time_t *restrict timer,505 struct posix_tm *restrict result)120 struct tm *posix_localtime_r(const time_t *restrict timer, 121 struct tm *restrict result) 506 122 { 507 123 // TODO: deal with timezone … … 511 127 512 128 /** 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 */ 519 char *posix_asctime(const struct posix_tm *timeptr) 520 { 521 static char buf[ASCTIME_BUF_LEN]; 522 return posix_asctime_r(timeptr, buf); 129 * Converts a time value to a broken-down local time. 130 * (non reentrant version) 131 * 132 * @param timep Time to convert. 133 * @return Pointer to a statically allocated structure that stores 134 * the result, NULL in case of error. 135 */ 136 struct tm *posix_localtime(const time_t *restrict timep) 137 { 138 static struct tm result; 139 140 return posix_localtime_r(timep, &result); 523 141 } 524 142 … … 532 150 * @return Value of buf. 533 151 */ 534 char *posix_asctime_r(const struct posix_tm *restrict timeptr,152 char *posix_asctime_r(const struct tm *restrict timeptr, 535 153 char *restrict buf) 536 154 { 537 assert(timeptr != NULL); 538 assert(buf != NULL); 539 540 static const char *wday[] = { 541 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 542 }; 543 static const char *mon[] = { 544 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 545 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 546 }; 547 548 snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n", 549 wday[timeptr->tm_wday], 550 mon[timeptr->tm_mon], 551 timeptr->tm_mday, timeptr->tm_hour, 552 timeptr->tm_min, timeptr->tm_sec, 553 1900 + timeptr->tm_year); 554 155 time_tm2str(timeptr, buf); 555 156 return buf; 556 157 } 557 158 558 159 /** 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 * Reentrant variant of ctime(). 160 * Convers broken-down time to a string in format 161 * "Sun Jan 1 00:00:00 1970\n". (Obsolete) 162 * (non reentrant version) 163 * 164 * @param timeptr Broken-down time structure. 165 * @return Pointer to a statically allocated buffer that stores 166 * the result, NULL in case of error. 167 */ 168 char *posix_asctime(const struct tm *restrict timeptr) 169 { 170 static char buf[ASCTIME_BUF_LEN]; 171 172 return posix_asctime_r(timeptr, buf); 173 } 174 175 /** 176 * Converts the calendar time to a string in format 177 * "Sun Jan 1 00:00:00 1970\n" (Obsolete) 575 178 * 576 179 * @param timer Time to convert. 577 180 * @param buf Buffer to store string to. Must be at least ASCTIME_BUF_LEN 578 181 * bytes long. 579 * @return Pointer to buf on success, NULL on fa lure.182 * @return Pointer to buf on success, NULL on failure. 580 183 */ 581 184 char *posix_ctime_r(const time_t *timer, char *buf) 582 185 { 583 struct posix_tm loctime; 584 if (posix_localtime_r(timer, &loctime) == NULL) { 186 int r = time_local2str(*timer, buf); 187 if (r != EOK) { 188 errno = r; 585 189 return NULL; 586 190 } 587 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 */ 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 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; 191 192 return buf; 193 } 194 195 /** 196 * Converts the calendar time to a string in format 197 * "Sun Jan 1 00:00:00 1970\n" (Obsolete) 198 * (non reentrant version) 199 * 200 * @param timep Time to convert. 201 * @return Pointer to a statically allocated buffer that stores 202 * the result, NULL in case of error. 203 */ 204 char *posix_ctime(const time_t *timep) 205 { 206 static char buf[ASCTIME_BUF_LEN]; 207 208 return posix_ctime_r(timep, buf); 780 209 } 781 210 … … 894 323 stats_task_t *task_stats = stats_get_task(task_get_id()); 895 324 if (task_stats) { 896 total_cycles = (posix_clock_t) (task_stats->kcycles + task_stats->ucycles); 325 total_cycles = (posix_clock_t) (task_stats->kcycles + 326 task_stats->ucycles); 897 327 free(task_stats); 898 328 task_stats = 0; -
uspace/lib/posix/time.h
r5d94b16c r4c84ada5 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_gmtime(const time_t *restrict timep); 90 extern struct tm *posix_localtime_r(const time_t *restrict timer, 91 struct tm *restrict result); 92 extern struct tm *posix_localtime(const time_t *restrict timep); 112 93 113 94 /* 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, 95 extern char *posix_asctime_r(const struct tm *restrict timeptr, 116 96 char *restrict buf); 97 extern char *posix_asctime(const struct tm *restrict timeptr); 98 extern char *posix_ctime_r(const time_t *timer, char *buf); 117 99 extern char *posix_ctime(const time_t *timer); 118 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 100 122 101 /* Clocks */ … … 134 113 135 114 #ifndef LIBPOSIX_INTERNAL 136 #define tm posix_tm 137 #define timespec posix_timespec 138 #define itimerspec posix_itimerspec 139 #define timer_t posix_timer_t 115 #define timespec posix_timespec 116 #define itimerspec posix_itimerspec 117 #define timer_t posix_timer_t 140 118 141 #define daylight posix_daylight142 #define timezone posix_timezone143 #define tzname posix_tzname144 #define tzset posix_tzset119 #define daylight posix_daylight 120 #define timezone posix_timezone 121 #define tzname posix_tzname 122 #define tzset posix_tzset 145 123 146 #define difftime posix_difftime 124 #define gmtime_r posix_gmtime_r 125 #define gmtime posix_gmtime 126 #define localtime_r posix_localtime_r 127 #define localtime posix_localtime 147 128 148 #define mktime posix_mktime 149 #define gmtime posix_gmtime 150 #define gmtime_r posix_gmtime_r 151 #define localtime posix_localtime 152 #define localtime_r posix_localtime_r 153 154 #define asctime posix_asctime 155 #define asctime_r posix_asctime_r 156 #define ctime posix_ctime 157 #define ctime_r posix_ctime_r 158 #define strftime posix_strftime 129 #define asctime_r posix_asctime_r 130 #define asctime posix_asctime 131 #define ctime_r posix_ctime_r 132 #define ctime posix_ctime 159 133 160 134 #define clock_getres posix_clock_getres -
uspace/srv/locsrv/locsrv.c
r5d94b16c r4c84ada5 1353 1353 categ_dir_add_cat(&cdir, cat); 1354 1354 1355 cat = category_new("clock"); 1356 categ_dir_add_cat(&cdir, cat); 1357 1355 1358 cat = category_new("test3"); 1356 1359 categ_dir_add_cat(&cdir, cat);
Note:
See TracChangeset
for help on using the changeset viewer.