Changes in / [90478727:371cb6c] in mainline
- Files:
-
- 12 deleted
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
boot/Makefile.common
r90478727 r371cb6c 187 187 $(USPACE_PATH)/app/vuhid/vuh \ 188 188 $(USPACE_PATH)/app/mkbd/mkbd \ 189 $(USPACE_PATH)/app/websrv/websrv \ 190 $(USPACE_PATH)/app/date/date 189 $(USPACE_PATH)/app/websrv/websrv 191 190 192 191 ifeq ($(CONFIG_PCC),y) -
boot/arch/amd64/Makefile.inc
r90478727 r371cb6c 42 42 char/ps2mouse \ 43 43 char/xtkbd \ 44 time/cmos-rtc \45 44 bus/usb/ehci\ 46 45 bus/usb/ohci \ -
uspace/Makefile
r90478727 r371cb6c 70 70 app/sysinfo \ 71 71 app/mkbd \ 72 app/date \73 72 app/websrv \ 74 73 srv/clipboard \ … … 125 124 drv/nic/ne2k \ 126 125 drv/nic/e1k \ 127 drv/nic/rtl8139 \126 drv/nic/rtl8139 128 127 129 128 ifeq ($(CONFIG_PCC),y) … … 154 153 drv/bus/isa \ 155 154 drv/char/ns8250 \ 156 drv/time/cmos-rtc \157 155 srv/hw/irc/apic \ 158 156 srv/hw/irc/i8259 … … 165 163 drv/bus/isa \ 166 164 drv/char/ns8250 \ 167 drv/time/cmos-rtc \168 165 srv/hw/irc/apic \ 169 166 srv/hw/irc/i8259 -
uspace/drv/bus/isa/isa.dev
r90478727 r371cb6c 27 27 dma 1 28 28 dma 5 29 30 cmos-rtc:31 match 100 isa/cmos-rtc32 io_range 70 2 -
uspace/lib/c/Makefile
r90478727 r371cb6c 69 69 generic/device/hw_res_parsed.c \ 70 70 generic/device/char_dev.c \ 71 generic/device/clock_dev.c \72 71 generic/device/nic.c \ 73 72 generic/device/pci.c \ -
uspace/lib/c/generic/time.c
r90478727 r371cb6c 1 1 /* 2 2 * Copyright (c) 2006 Ondrej Palkovsky 3 * Copyright (c) 2011 Petr Koupy4 * Copyright (c) 2011 Jiri Zarevucky5 3 * All rights reserved. 6 4 * … … 45 43 #include <ddi.h> 46 44 #include <libc.h> 47 #include <stdint.h>48 #include <stdio.h>49 #include <ctype.h>50 #include <assert.h>51 45 #include <unistd.h> 52 53 #define ASCTIME_BUF_LEN 2654 46 55 47 /** Pointer to kernel shared variables with time */ … … 59 51 volatile sysarg_t seconds2; 60 52 } *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 otherwise76 */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 year116 * it is.117 *118 * For example, given date 2011-01-03, the corresponding expression is:119 * _day_of_year(111, 0, 3) == 2120 *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 of223 * seconds.224 *225 * @param tm Broken-down time to normalize.226 * @param sec_add Seconds to add.227 * @return 0 on success, -1 on overflow228 */229 static int _normalize_time(struct tm *tm, time_t sec_add)230 {231 // TODO: DST correction232 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 previous357 * year, and the next week is week 1. Both January 4th and the first Thursday358 * 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 394 53 395 54 /** Add microseconds to given timeval. … … 570 229 } 571 230 572 /**573 * This function first normalizes the provided broken-down time574 * (moves all values to their proper bounds) and then tries to575 * 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 account583 // TODO: detect overflow584 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 and591 * 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 locale607 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: padding664 format++;665 }666 while (isdigit(*format)) {667 // TODO: padding668 format++;669 }670 if (*format == 'O' || *format == 'E') {671 // TODO: locale's alternative format672 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 format686 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 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 }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 format806 * "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 timezone845 // currently assumes system and all times are in GMT846 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 892 231 /** @} 893 232 */ -
uspace/lib/c/include/ipc/dev_iface.h
r90478727 r371cb6c 54 54 AHCI_DEV_IFACE, 55 55 56 /** Interface provided by Real Time Clock devices */57 CLOCK_DEV_IFACE,58 59 56 DEV_IFACE_MAX 60 57 } dev_inferface_idx_t; -
uspace/lib/c/include/sys/time.h
r90478727 r371cb6c 1 1 /* 2 2 * Copyright (c) 2006 Ondrej Palkovsky 3 * Copyright (c) 2011 Petr Koupy4 * Copyright (c) 2011 Jiri Zarevucky5 3 * All rights reserved. 6 4 * … … 41 39 42 40 #define DST_NONE 0 43 #define ASCTIME_BUF_LEN 2644 41 45 42 typedef long time_t; … … 48 45 typedef uint32_t useconds_t; 49 46 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 };62 47 63 48 struct timeval { … … 79 64 extern void udelay(useconds_t); 80 65 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 90 66 #endif 91 67 -
uspace/lib/drv/Makefile
r90478727 r371cb6c 45 45 generic/remote_usbhc.c \ 46 46 generic/remote_usbhid.c \ 47 generic/remote_clock_dev.c48 47 generic/remote_ahci.c 49 48 -
uspace/lib/drv/generic/dev_iface.c
r90478727 r371cb6c 41 41 #include "remote_hw_res.h" 42 42 #include "remote_char_dev.h" 43 #include "remote_clock_dev.h"44 43 #include "remote_nic.h" 45 44 #include "remote_usb.h" … … 58 57 &remote_usbhc_iface, 59 58 &remote_usbhid_iface, 60 &remote_clock_dev_iface,61 59 &remote_ahci_iface 62 60 } -
uspace/lib/posix/time.c
r90478727 r371cb6c 141 141 * Used by some functions in this file. 142 142 * 143 * @param op1 Dividen d.143 * @param op1 Divident. 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 d.160 * @param op1 Divident. 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 /** 198 211 * Which day of week the specified date is. 199 212 * … … 217 230 * @return 0 on success, -1 on overflow 218 231 */ 219 static int _normalize_time(struct tm *tm, time_t sec_add)232 static int _normalize_time(struct posix_tm *tm, time_t sec_add) 220 233 { 221 234 // TODO: DST correction … … 293 306 } 294 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 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 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 295 395 /******************************************************************************/ 296 396 … … 312 412 313 413 /** 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 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 */ 433 time_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 */ 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 /** 314 457 * Converts a time value to a broken-down UTC time. 315 458 * … … 318 461 * @return Value of result on success, NULL on overflow. 319 462 */ 320 struct tm *posix_gmtime_r(const time_t *restrict timer,321 struct tm *restrict result)463 struct posix_tm *posix_gmtime_r(const time_t *restrict timer, 464 struct posix_tm *restrict result) 322 465 { 323 466 assert(timer != NULL); … … 342 485 /** 343 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); 495 } 496 497 /** 498 * Converts a time value to a broken-down local time. 344 499 * 345 500 * @param timer Time to convert. … … 347 502 * @return Value of result on success, NULL on overflow. 348 503 */ 349 struct tm *posix_localtime_r(const time_t *restrict timer,350 struct tm *restrict result)504 struct posix_tm *posix_localtime_r(const time_t *restrict timer, 505 struct posix_tm *restrict result) 351 506 { 352 507 // TODO: deal with timezone 353 508 // currently assumes system and all times are in GMT 354 509 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 */ 519 char *posix_asctime(const struct posix_tm *timeptr) 520 { 521 static char buf[ASCTIME_BUF_LEN]; 522 return posix_asctime_r(timeptr, buf); 355 523 } 356 524 … … 364 532 * @return Value of buf. 365 533 */ 366 char *posix_asctime_r(const struct tm *restrict timeptr,534 char *posix_asctime_r(const struct posix_tm *restrict timeptr, 367 535 char *restrict buf) 368 536 { … … 389 557 390 558 /** 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 /** 391 574 * Reentrant variant of ctime(). 392 575 * … … 398 581 char *posix_ctime_r(const time_t *timer, char *buf) 399 582 { 400 struct tm loctime;583 struct posix_tm loctime; 401 584 if (posix_localtime_r(timer, &loctime) == NULL) { 402 585 return NULL; 403 586 } 404 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; 405 780 } 406 781 … … 519 894 stats_task_t *task_stats = stats_get_task(task_get_id()); 520 895 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); 523 897 free(task_stats); 524 898 task_stats = 0; -
uspace/lib/posix/time.h
r90478727 r371cb6c 63 63 #endif 64 64 65 #undef ASCTIME_BUF_LEN 66 #define ASCTIME_BUF_LEN 26 67 65 68 #undef CLOCK_REALTIME 66 69 #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 }; 67 82 68 83 struct posix_timespec { … … 84 99 extern void posix_tzset(void); 85 100 101 /* Elapsed Time */ 102 extern double posix_difftime(time_t time1, time_t time0); 103 86 104 /* 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); 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); 91 112 92 113 /* Formatting Calendar Time */ 93 extern char *posix_asctime_r(const struct tm *restrict timeptr, 114 extern char *posix_asctime(const struct posix_tm *timeptr); 115 extern char *posix_asctime_r(const struct posix_tm *restrict timeptr, 94 116 char *restrict buf); 117 extern char *posix_ctime(const time_t *timer); 95 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); 96 121 97 122 /* Clocks */ … … 109 134 110 135 #ifndef LIBPOSIX_INTERNAL 136 #define tm posix_tm 111 137 #define timespec posix_timespec 112 138 #define itimerspec posix_itimerspec … … 118 144 #define tzset posix_tzset 119 145 146 #define difftime posix_difftime 147 148 #define mktime posix_mktime 149 #define gmtime posix_gmtime 120 150 #define gmtime_r posix_gmtime_r 151 #define localtime posix_localtime 121 152 #define localtime_r posix_localtime_r 122 153 154 #define asctime posix_asctime 123 155 #define asctime_r posix_asctime_r 156 #define ctime posix_ctime 124 157 #define ctime_r posix_ctime_r 158 #define strftime posix_strftime 125 159 126 160 #define clock_getres posix_clock_getres -
uspace/srv/locsrv/locsrv.c
r90478727 r371cb6c 1353 1353 categ_dir_add_cat(&cdir, cat); 1354 1354 1355 cat = category_new("clock");1356 categ_dir_add_cat(&cdir, cat);1357 1358 1355 cat = category_new("test3"); 1359 1356 categ_dir_add_cat(&cdir, cat);
Note:
See TracChangeset
for help on using the changeset viewer.