]>
Commit | Line | Data |
---|---|---|
eaa02bc9 | 1 | /* |
b93ebb4e | 2 | * Copyright (C) 2008-2017 Tobias Brunner |
eaa02bc9 | 3 | * Copyright (C) 2005-2008 Martin Willi |
b93ebb4e | 4 | * HSR Hochschule fuer Technik Rapperswil |
eaa02bc9 MW |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2 of the License, or (at your | |
9 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
13 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | * for more details. | |
15 | */ | |
16 | ||
17 | #ifdef WIN32 | |
18 | /* for GetTickCount64, Windows 7 */ | |
19 | # define _WIN32_WINNT 0x0601 | |
20 | #endif | |
21 | ||
22 | #define _GNU_SOURCE | |
23 | #include <utils/utils.h> | |
24 | ||
25 | #include <inttypes.h> | |
b93ebb4e | 26 | #include <ctype.h> |
eaa02bc9 | 27 | #include <time.h> |
b93ebb4e | 28 | #include <errno.h> |
eaa02bc9 MW |
29 | |
30 | /** | |
31 | * Return monotonic time | |
32 | */ | |
33 | time_t time_monotonic(timeval_t *tv) | |
34 | { | |
35 | #ifdef WIN32 | |
36 | ULONGLONG ms; | |
37 | time_t s; | |
38 | ||
39 | ms = GetTickCount64(); | |
40 | s = ms / 1000; | |
41 | if (tv) | |
42 | { | |
43 | tv->tv_sec = s; | |
44 | tv->tv_usec = (ms - (s * 1000)) * 1000; | |
45 | } | |
46 | return s; | |
47 | #else /* !WIN32 */ | |
48 | #if defined(HAVE_CLOCK_GETTIME) && \ | |
49 | (defined(HAVE_CONDATTR_CLOCK_MONOTONIC) || \ | |
50 | defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) | |
51 | /* as we use time_monotonic() for condvar operations, we use the | |
52 | * monotonic time source only if it is also supported by pthread. */ | |
53 | timespec_t ts; | |
54 | ||
3e358475 | 55 | if (clock_gettime(TIME_CLOCK_ID, &ts) == 0) |
eaa02bc9 MW |
56 | { |
57 | if (tv) | |
58 | { | |
59 | tv->tv_sec = ts.tv_sec; | |
60 | tv->tv_usec = ts.tv_nsec / 1000; | |
61 | } | |
62 | return ts.tv_sec; | |
63 | } | |
64 | #endif /* HAVE_CLOCK_GETTIME && (...) */ | |
65 | /* Fallback to non-monotonic timestamps: | |
66 | * On MAC OS X, creating monotonic timestamps is rather difficult. We | |
67 | * could use mach_absolute_time() and catch sleep/wakeup notifications. | |
68 | * We stick to the simpler (non-monotonic) gettimeofday() for now. | |
69 | * But keep in mind: we need the same time source here as in condvar! */ | |
70 | if (!tv) | |
71 | { | |
72 | return time(NULL); | |
73 | } | |
74 | if (gettimeofday(tv, NULL) != 0) | |
75 | { /* should actually never fail if passed pointers are valid */ | |
76 | return -1; | |
77 | } | |
78 | return tv->tv_sec; | |
79 | #endif /* !WIN32 */ | |
80 | } | |
81 | ||
b93ebb4e TB |
82 | /* |
83 | * Described in header | |
84 | */ | |
85 | bool timespan_from_string(char *str, char *defunit, time_t *val) | |
86 | { | |
87 | char *endptr, unit; | |
88 | time_t timeval; | |
89 | ||
90 | if (str) | |
91 | { | |
92 | errno = 0; | |
93 | timeval = strtoull(str, &endptr, 10); | |
94 | if (endptr == str) | |
95 | { | |
96 | return FALSE; | |
97 | } | |
98 | if (errno == 0) | |
99 | { | |
100 | while (isspace(*endptr)) | |
101 | { | |
102 | endptr++; | |
103 | } | |
104 | unit = *endptr; | |
105 | if (!unit && defunit) | |
106 | { | |
107 | unit = *defunit; | |
108 | } | |
109 | switch (unit) | |
110 | { | |
111 | case 'd': /* time in days */ | |
112 | timeval *= 24 * 3600; | |
113 | break; | |
114 | case 'h': /* time in hours */ | |
115 | timeval *= 3600; | |
116 | break; | |
117 | case 'm': /* time in minutes */ | |
118 | timeval *= 60; | |
119 | break; | |
120 | case 's': /* time in seconds */ | |
121 | case '\0': | |
122 | break; | |
123 | default: | |
124 | return FALSE; | |
125 | } | |
126 | if (val) | |
127 | { | |
128 | *val = timeval; | |
129 | } | |
130 | return TRUE; | |
131 | } | |
132 | } | |
133 | return FALSE; | |
134 | } | |
135 | ||
136 | /* | |
137 | * Described in header | |
eaa02bc9 MW |
138 | */ |
139 | int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, | |
140 | const void *const *args) | |
141 | { | |
142 | static const char* months[] = { | |
143 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", | |
144 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" | |
145 | }; | |
146 | time_t *time = *((time_t**)(args[0])); | |
147 | bool utc = *((int*)(args[1])); | |
148 | struct tm t, *ret = NULL; | |
149 | ||
150 | if (*time != UNDEFINED_TIME) | |
151 | { | |
152 | if (utc) | |
153 | { | |
154 | ret = gmtime_r(time, &t); | |
155 | } | |
156 | else | |
157 | { | |
158 | ret = localtime_r(time, &t); | |
159 | } | |
160 | } | |
161 | if (ret == NULL) | |
162 | { | |
163 | return print_in_hook(data, "--- -- --:--:--%s----", | |
164 | utc ? " UTC " : " "); | |
165 | } | |
166 | return print_in_hook(data, "%s %02d %02d:%02d:%02d%s%04d", | |
167 | months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min, | |
168 | t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900); | |
169 | } | |
170 | ||
b93ebb4e TB |
171 | /* |
172 | * Described in header | |
eaa02bc9 MW |
173 | */ |
174 | int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, | |
175 | const void *const *args) | |
176 | { | |
177 | char* unit = "second"; | |
178 | time_t *arg1 = *((time_t**)(args[0])); | |
179 | time_t *arg2 = *((time_t**)(args[1])); | |
b12c53ce | 180 | uint64_t delta = llabs(*arg1 - *arg2); |
eaa02bc9 MW |
181 | |
182 | if (delta > 2 * 60 * 60 * 24) | |
183 | { | |
184 | delta /= 60 * 60 * 24; | |
185 | unit = "day"; | |
186 | } | |
187 | else if (delta > 2 * 60 * 60) | |
188 | { | |
189 | delta /= 60 * 60; | |
190 | unit = "hour"; | |
191 | } | |
192 | else if (delta > 2 * 60) | |
193 | { | |
194 | delta /= 60; | |
195 | unit = "minute"; | |
196 | } | |
197 | return print_in_hook(data, "%" PRIu64 " %s%s", delta, unit, | |
198 | (delta == 1) ? "" : "s"); | |
199 | } |