Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(63)

Delta Between Two Patch Sets: Python/pytime.c

Issue 22043: Use a monotonic clock to compute timeouts
Left Patch Set: Created 3 years, 2 months ago
Right Patch Set: Created 3 years ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Modules/timemodule.c ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 #include "Python.h" 1 #include "Python.h"
2 #ifdef MS_WINDOWS 2 #ifdef MS_WINDOWS
3 #include <windows.h> 3 #include <windows.h>
4 #endif 4 #endif
5 5
6 #if defined(__APPLE__) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME) 6 #if defined(__APPLE__)
7 /* 7 #include <mach/mach_time.h> /* mach_absolute_time(), mach_timebase_info() */
8 * _PyTime_gettimeofday falls back to ftime when getttimeofday fails because t he latter 8 #endif
9 * might fail on some platforms. This fallback is unwanted on MacOSX because 9
10 * that makes it impossible to use a binary build on OSX 10.4 on earlier 10 #ifdef MS_WINDOWS
11 * releases of the OS. Therefore claim we don't support ftime. 11 static OSVERSIONINFOEX winver;
12 */ 12 #endif
13 # undef HAVE_FTIME 13
14 #endif 14 static int
15 15 pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info, int raise)
16 #if defined(HAVE_FTIME) && !defined(MS_WINDOWS)
17 #include <sys/timeb.h>
18 extern int ftime(struct timeb *);
19 #endif
20
21 /* one seconde in nanoseconds */
22 #define SEC_IN_NANOSECONDS 1000000000
Charles-François Natali 2014/07/31 07:33:20 Maybe add an explicit 'UL' suffix?
haypo 2014/07/31 11:17:44 Oh yes.
23
24 static void
25 pygettimeofday(_PyTime_timespec *ts, _Py_clock_info_t *info)
26 { 16 {
27 #ifdef MS_WINDOWS 17 #ifdef MS_WINDOWS
28 FILETIME system_time; 18 FILETIME system_time;
29 ULARGE_INTEGER large; 19 ULARGE_INTEGER large;
30 ULONGLONG nanoseconds; 20 ULONGLONG microseconds;
21
22 assert(info == NULL || raise);
31 23
32 GetSystemTimeAsFileTime(&system_time); 24 GetSystemTimeAsFileTime(&system_time);
33 large.u.LowPart = system_time.dwLowDateTime; 25 large.u.LowPart = system_time.dwLowDateTime;
34 large.u.HighPart = system_time.dwHighDateTime; 26 large.u.HighPart = system_time.dwHighDateTime;
35 /* 11,644,473,600,000,000,000: number of nanoseconds between 27 /* 11,644,473,600,000,000: number of microseconds between
36 the 1st january 1601 and the 1st january 1970 (369 years + 89 leap 28 the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
37 days). */ 29 days). */
38 nanoseconds = large.QuadPart * 100 - 11644473600000000000; 30 microseconds = large.QuadPart / 10 - 11644473600000000;
39 ts->tv_sec = nanoseconds / SEC_IN_NANOSECONDS; 31 tp->tv_sec = microseconds / 1000000;
40 ts->tv_nsec = nanoseconds % SEC_IN_NANOSECONDS; 32 tp->tv_usec = microseconds % 1000000;
41 if (info) { 33 if (info) {
42 DWORD timeAdjustment, timeIncrement; 34 DWORD timeAdjustment, timeIncrement;
43 BOOL isTimeAdjustmentDisabled; 35 BOOL isTimeAdjustmentDisabled, ok;
44 36
45 info->implementation = "GetSystemTimeAsFileTime()"; 37 info->implementation = "GetSystemTimeAsFileTime()";
46 info->monotonic = 0; 38 info->monotonic = 0;
47 (void) GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, 39 ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
48 &isTimeAdjustmentDisabled); 40 &isTimeAdjustmentDisabled);
41 if (!ok) {
42 PyErr_SetFromWindowsErr(0);
43 return -1;
44 }
49 info->resolution = timeIncrement * 1e-7; 45 info->resolution = timeIncrement * 1e-7;
50 info->adjustable = 1; 46 info->adjustable = 1;
51 } 47 }
52 #else 48 return 0;
53 /* There are four ways to get the time: 49
54 (1) clock_gettime() -- resolution in nanoseconds 50 #else /* MS_WINDOWS */
55 (2) gettimeofday() -- resolution in microseconds
56 (3) ftime() -- resolution in milliseconds
57 (4) time() -- resolution in seconds
58 In all cases the return value in a timeval struct.
59 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
60 fail, so we fall back on ftime() or time().
61 Note: clock resolution does not imply clock accuracy! */
62
63 #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETTIMEOFDAY)
64 int err; 51 int err;
65 #endif
66 #ifdef HAVE_CLOCK_GETTIME 52 #ifdef HAVE_CLOCK_GETTIME
67 struct timespec tp; 53 struct timespec ts;
68 #endif 54 #endif
69 #ifdef HAVE_GETTIMEOFDAY 55
70 struct timeval tv; 56 assert(info == NULL || raise);
71 #endif
72 #ifdef HAVE_FTIME
73 struct timeb tb;
74 #endif
75 57
76 #ifdef HAVE_CLOCK_GETTIME 58 #ifdef HAVE_CLOCK_GETTIME
77 err = clock_gettime(CLOCK_REALTIME, &tp); 59 err = clock_gettime(CLOCK_REALTIME, &ts);
78 if (err == 0) { 60 if (err) {
79 if (info) { 61 if (raise)
80 struct timespec res; 62 PyErr_SetFromErrno(PyExc_OSError);
81 info->implementation = "clock_gettime(CLOCK_REALTIME)"; 63 return -1;
82 info->monotonic = 0; 64 }
83 info->adjustable = 1; 65 tp->tv_sec = ts.tv_sec;
84 if (clock_getres(CLOCK_REALTIME, &res) == 0) 66 tp->tv_usec = ts.tv_nsec / 1000;
85 info->resolution = res.tv_sec + res.tv_nsec * 1e-9; 67
86 else 68 if (info) {
87 info->resolution = 1e-9; 69 struct timespec res;
88 } 70 info->implementation = "clock_gettime(CLOCK_REALTIME)";
89 ts->tv_sec = tp.tv_sec; 71 info->monotonic = 0;
90 ts->tv_nsec = tp.tv_nsec; 72 info->adjustable = 1;
91 return; 73 if (clock_getres(CLOCK_REALTIME, &res) == 0)
92 } 74 info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
93 #endif 75 else
94 76 info->resolution = 1e-9;
77 }
78 return 0;
79 #else /* HAVE_CLOCK_GETTIME */
80
81 /* test gettimeofday() */
95 #ifdef HAVE_GETTIMEOFDAY 82 #ifdef HAVE_GETTIMEOFDAY
96 #ifdef GETTIMEOFDAY_NO_TZ 83 #ifdef GETTIMEOFDAY_NO_TZ
97 err = gettimeofday(&tv); 84 err = gettimeofday(tp);
98 #else 85 #else
99 err = gettimeofday(&tv, (struct timezone *)NULL); 86 err = gettimeofday(tp, (struct timezone *)NULL);
100 #endif 87 #endif
101 if (err == 0) { 88 if (err) {
102 ts->tv_sec = tv.tv_sec; 89 if (raise)
103 ts->tv_nsec = tv.tv_usec * 1000; 90 PyErr_SetFromErrno(PyExc_OSError);
104 if (info) { 91 return -1;
105 info->implementation = "gettimeofday()"; 92 }
106 info->resolution = 1e-6; 93
107 info->monotonic = 0; 94 if (info) {
108 info->adjustable = 1; 95 info->implementation = "gettimeofday()";
109 } 96 info->resolution = 1e-6;
110 return;
111 }
112 #endif /* HAVE_GETTIMEOFDAY */
113
114 #ifdef HAVE_FTIME
115 ftime(&tb);
116 ts->tv_sec = tb.time;
117 ts->tv_nsec = tb.millitm * 1000000;
118 if (info) {
119 info->implementation = "ftime()";
120 info->resolution = 1e-3;
121 info->monotonic = 0; 97 info->monotonic = 0;
122 info->adjustable = 1; 98 info->adjustable = 1;
123 } 99 }
124 #else /* !HAVE_FTIME */ 100 return 0;
125 tp->tv_sec = time(NULL); 101 #endif /* HAVE_GETTIMEOFDAY */
126 tp->tv_nsec = 0; 102 #endif /* !HAVE_CLOCK_GETTIME */
127 if (info) { 103 #endif /* !MS_WINDOWS */
128 info->implementation = "time()";
129 info->resolution = 1.0;
130 info->monotonic = 0;
131 info->adjustable = 1;
132 }
133 #endif /* !HAVE_FTIME */
134
135 #endif /* MS_WINDOWS */
136 } 104 }
137 105
138 void 106 void
139 _PyTime_gettimeofday(_PyTime_timespec *tp) 107 _PyTime_gettimeofday(_PyTime_timeval *tp)
140 { 108 {
141 pygettimeofday(tp, NULL); 109 if (pygettimeofday(tp, NULL, 0) < 0) {
110 /* cannot happen, _PyTime_Init() checks that pygettimeofday() works */
111 assert(0);
112 tp->tv_sec = 0;
113 tp->tv_usec = 0;
114 }
115 }
116
117 int
118 _PyTime_gettimeofday_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
119 {
120 return pygettimeofday(tp, info, 1);
121 }
122
123 static int
124 pymonotonic(_PyTime_timeval *tp, _Py_clock_info_t *info, int raise)
125 {
126 #if defined(MS_WINDOWS)
127 static ULONGLONG (*GetTickCount64) (void) = NULL;
128 static ULONGLONG (CALLBACK *Py_GetTickCount64)(void);
129 static int has_gettickcount64 = -1;
130 ULONGLONG result;
131
132 assert(info == NULL || raise);
133
134 if (has_gettickcount64 == -1) {
135 /* GetTickCount64() was added to Windows Vista */
136 has_gettickcount64 = (winver.dwMajorVersion >= 6);
137 if (has_gettickcount64) {
138 HINSTANCE hKernel32;
139 hKernel32 = GetModuleHandleW(L"KERNEL32");
140 *(FARPROC*)&Py_GetTickCount64 = GetProcAddress(hKernel32,
141 "GetTickCount64");
142 assert(Py_GetTickCount64 != NULL);
143 }
144 }
145
146 if (has_gettickcount64) {
147 result = Py_GetTickCount64();
148 }
149 else {
150 static DWORD last_ticks = 0;
151 static DWORD n_overflow = 0;
152 DWORD ticks;
153
154 ticks = GetTickCount();
155 if (ticks < last_ticks)
156 n_overflow++;
157 last_ticks = ticks;
158
159 result = (ULONGLONG)n_overflow << 32;
160 result += ticks;
161 }
162
163 tp->tv_sec = result / 1000;
164 tp->tv_usec = (result % 1000) * 1000;
165
166 if (info) {
167 DWORD timeAdjustment, timeIncrement;
168 BOOL isTimeAdjustmentDisabled, ok;
169 if (has_gettickcount64)
170 info->implementation = "GetTickCount64()";
171 else
172 info->implementation = "GetTickCount()";
173 info->monotonic = 1;
174 ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
175 &isTimeAdjustmentDisabled);
176 if (!ok) {
177 PyErr_SetFromWindowsErr(0);
178 return -1;
179 }
180 info->resolution = timeIncrement * 1e-7;
181 info->adjustable = 0;
182 }
183 return 0;
184
185 #elif defined(__APPLE__)
186 static mach_timebase_info_data_t timebase;
187 uint64_t time;
188
189 if (timebase.denom == 0) {
190 /* According to the Technical Q&A QA1398, mach_timebase_info() cannot
191 fail: https://developer.apple.com/library/mac/#qa/qa1398/ */
192 (void)mach_timebase_info(&timebase);
193 }
194
195 time = mach_absolute_time();
196
197 /* nanoseconds => microseconds */
198 time /= 1000;
199 /* apply timebase factor */
200 time *= timebase.numer;
201 time /= timebase.denom;
202 tp->tv_sec = time / (1000 * 1000);
203 tp->tv_usec = time % (1000 * 1000);
204
205 if (info) {
206 info->implementation = "mach_absolute_time()";
207 info->resolution = (double)timebase.numer / timebase.denom * 1e-9;
208 info->monotonic = 1;
209 info->adjustable = 0;
210 }
211 return 0;
212
213 #else
214 struct timespec ts;
215 #ifdef CLOCK_HIGHRES
216 const clockid_t clk_id = CLOCK_HIGHRES;
217 const char *implementation = "clock_gettime(CLOCK_HIGHRES)";
218 #else
219 const clockid_t clk_id = CLOCK_MONOTONIC;
220 const char *implementation = "clock_gettime(CLOCK_MONOTONIC)";
221 #endif
222
223 assert(info == NULL || raise);
224
225 if (clock_gettime(clk_id, &ts) != 0) {
226 if (raise) {
227 PyErr_SetFromErrno(PyExc_OSError);
228 return -1;
229 }
230 tp->tv_sec = 0;
231 tp->tv_usec = 0;
232 return -1;
233 }
234
235 if (info) {
236 struct timespec res;
237 info->monotonic = 1;
238 info->implementation = implementation;
239 info->adjustable = 0;
240 if (clock_getres(clk_id, &res) != 0) {
241 PyErr_SetFromErrno(PyExc_OSError);
242 return -1;
243 }
244 info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
245 }
246 tp->tv_sec = ts.tv_sec;
247 tp->tv_usec = ts.tv_nsec / 1000;
248 return 0;
249 #endif
142 } 250 }
143 251
144 void 252 void
145 _PyTime_gettimeofday_info(_PyTime_timespec *tp, _Py_clock_info_t *info) 253 _PyTime_monotonic(_PyTime_timeval *tp)
146 { 254 {
147 pygettimeofday(tp, info); 255 if (pymonotonic(tp, NULL, 0) < 0) {
256 /* cannot happen, _PyTime_Init() checks that pymonotonic() works */
257 assert(0);
258 tp->tv_sec = 0;
259 tp->tv_usec = 0;
260 }
261 }
262
263 int
264 _PyTime_monotonic_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
265 {
266 return pymonotonic(tp, info, 1);
148 } 267 }
149 268
150 static void 269 static void
151 error_time_t_overflow(void) 270 error_time_t_overflow(void)
152 { 271 {
153 PyErr_SetString(PyExc_OverflowError, 272 PyErr_SetString(PyExc_OverflowError,
154 "timestamp out of range for platform time_t"); 273 "timestamp out of range for platform time_t");
155 } 274 }
156 275
157 time_t 276 time_t
(...skipping 20 matching lines...) Expand all
178 { 297 {
179 #if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG 298 #if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
180 return PyLong_FromLongLong((PY_LONG_LONG)t); 299 return PyLong_FromLongLong((PY_LONG_LONG)t);
181 #else 300 #else
182 assert(sizeof(time_t) <= sizeof(long)); 301 assert(sizeof(time_t) <= sizeof(long));
183 return PyLong_FromLong((long)t); 302 return PyLong_FromLong((long)t);
184 #endif 303 #endif
185 } 304 }
186 305
187 static int 306 static int
188 _PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator,
189 double denominator, _PyTime_round_t round,
190 int raise)
191 {
192 double intpart, err;
193 /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
194 volatile double floatpart;
195
196 floatpart = modf(d, &intpart);
197 if (floatpart < 0) {
198 floatpart = 1.0 + floatpart;
199 intpart -= 1.0;
200 }
201
202 floatpart *= denominator;
203 if (round == _PyTime_ROUND_UP) {
204 if (intpart >= 0) {
205 floatpart = ceil(floatpart);
206 if (floatpart >= denominator) {
207 floatpart -= denominator;
208 intpart += 1.0;
209 }
210 }
211 else {
212 floatpart = floor(floatpart);
213 }
214 }
215
216 *sec = (time_t)intpart;
217 err = intpart - (double)*sec;
218 if (err <= -1.0 || err >= 1.0) {
219 if (raise)
220 error_time_t_overflow();
221 return -1;
222 }
223
224 *numerator = (long)floatpart;
225 return 0;
226 }
227
228 static int
229 _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, 307 _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
230 double denominator, _PyTime_round_t round) 308 double denominator, _PyTime_round_t round)
231 { 309 {
232 assert(denominator <= LONG_MAX); 310 assert(denominator <= LONG_MAX);
233 if (PyFloat_Check(obj)) { 311 if (PyFloat_Check(obj)) {
234 double d = PyFloat_AsDouble(obj); 312 double d, intpart, err;
235 return _PyTime_DoubleToDenominator(d, sec, numerator, 313 /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
236 denominator, round, 1); 314 volatile double floatpart;
315
316 d = PyFloat_AsDouble(obj);
317 floatpart = modf(d, &intpart);
318 if (floatpart < 0) {
319 floatpart = 1.0 + floatpart;
320 intpart -= 1.0;
321 }
322
323 floatpart *= denominator;
324 if (round == _PyTime_ROUND_UP) {
325 if (intpart >= 0) {
326 floatpart = ceil(floatpart);
327 if (floatpart >= denominator) {
328 floatpart = 0.0;
329 intpart += 1.0;
330 }
331 }
332 else {
333 floatpart = floor(floatpart);
334 }
335 }
336
337 *sec = (time_t)intpart;
338 err = intpart - (double)*sec;
339 if (err <= -1.0 || err >= 1.0) {
340 error_time_t_overflow();
341 return -1;
342 }
343
344 *numerator = (long)floatpart;
345 return 0;
237 } 346 }
238 else { 347 else {
239 *sec = _PyLong_AsTime_t(obj); 348 *sec = _PyLong_AsTime_t(obj);
240 if (*sec == (time_t)-1 && PyErr_Occurred()) 349 if (*sec == (time_t)-1 && PyErr_Occurred())
241 return -1; 350 return -1;
242 *numerator = 0; 351 *numerator = 0;
243 return 0; 352 return 0;
244 } 353 }
245 } 354 }
246 355
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round); 391 return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round);
283 } 392 }
284 393
285 int 394 int
286 _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec, 395 _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
287 _PyTime_round_t round) 396 _PyTime_round_t round)
288 { 397 {
289 return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round); 398 return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
290 } 399 }
291 400
292 static int 401 int
293 pymonotonic(_PyTime_timespec *ts, _Py_clock_info_t *info, int raise) 402 _PyTime_Init(void)
294 { 403 {
295 #if defined(MS_WINDOWS) 404 _PyTime_timeval tv;
296 static ULONGLONG (*GetTickCount64) (void) = NULL; 405
297 static ULONGLONG (CALLBACK *Py_GetTickCount64)(void); 406 #ifdef MS_WINDOWS
298 static int has_getickcount64 = -1; 407 winver.dwOSVersionInfoSize = sizeof(winver);
299 double result; 408 if (!GetVersionEx((OSVERSIONINFO*)&winver)) {
300 409 PyErr_SetFromWindowsErr(0);
301 if (has_getickcount64 == -1) { 410 return -1;
302 /* GetTickCount64() was added to Windows Vista */ 411 }
303 if (winver.dwMajorVersion >= 6) { 412 #endif
304 HINSTANCE hKernel32; 413
305 hKernel32 = GetModuleHandleW(L"KERNEL32"); 414 /* ensure that the system clock works */
306 *(FARPROC*)&Py_GetTickCount64 = GetProcAddress(hKernel32, 415 if (_PyTime_gettimeofday_info(&tv, NULL) < 0)
307 "GetTickCount64"); 416 return -1;
308 has_getickcount64 = (Py_GetTickCount64 != NULL); 417
309 } 418 /* ensure that the operating system provides a monotonic clock */
310 else 419 if (_PyTime_monotonic_info(&tv, NULL) < 0)
311 has_getickcount64 = 0; 420 return -1;
312 } 421 return 0;
313 422 }
314 if (has_getickcount64) {
315 ULONGLONG ticks;
316 ticks = Py_GetTickCount64();
317 ts->tv_sec = ticks / 1000;
318 ts->tv_nsec = (ticks % 1000) * 1000000;
319 }
320 else {
321 static DWORD last_ticks = 0;
322 DWORD ticks;
323 static ULONGLONG delta = 0;
324 ULONGLONG result;
325
326 ticks = GetTickCount();
327 if (ticks < last_ticks)
328 delta += (ULONGLONG)1 << 32;
329 last_ticks = ticks;
330
331 result = (ULONGLONG)ticks + delta;
332
333 ts->tv_sec = result / 1000;
334 ts->tv_nsec = (result % 1000) * 1000000;
335 }
336
337 if (info) {
338 DWORD timeAdjustment, timeIncrement;
339 BOOL isTimeAdjustmentDisabled, ok;
340 if (has_getickcount64)
341 info->implementation = "GetTickCount64()";
342 else
343 info->implementation = "GetTickCount()";
344 info->monotonic = 1;
345 ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
346 &isTimeAdjustmentDisabled);
347 if (!ok) {
348 if (raise)
349 PyErr_SetFromWindowsErr(0);
350 goto error;
351 }
352 info->resolution = timeIncrement * 1e-7;
353 info->adjustable = 0;
354 }
355 return 0;
356
357 #elif defined(__APPLE__)
358 static mach_timebase_info_data_t timebase;
359 uint64_t time;
360 double secs;
361
362 if (timebase.denom == 0) {
363 /* According to the Technical Q&A QA1398, mach_timebase_info() cannot
364 fail: https://developer.apple.com/library/mac/#qa/qa1398/ */
365 (void)mach_timebase_info(&timebase);
366 }
367
368 time = mach_absolute_time();
369 secs = (double)time * timebase.numer / timebase.denom * 1e-9;
370
371 if (_PyTime_DoubleToDenominator(secs, &ts->tv_sec, &ts->nsec,
372 1e9, _PyTime_ROUND_DOWN, raise) < 0)
373 goto error;
374
375 if (info) {
376 info->implementation = "mach_absolute_time()";
377 info->resolution = (double)timebase.numer / timebase.denom * 1e-9;
378 info->monotonic = 1;
379 info->adjustable = 0;
380 }
381 return 0;
382
383 #elif defined(HAVE_CLOCK_GETTIME) && (defined(CLOCK_HIGHRES) || defined(CLOCK_MO NOTONIC))
384 struct timespec tp;
385 #ifdef CLOCK_HIGHRES
386 const clockid_t clk_id = CLOCK_HIGHRES;
387 const char *function = "clock_gettime(CLOCK_HIGHRES)";
388 #else
389 const clockid_t clk_id = CLOCK_MONOTONIC;
390 const char *function = "clock_gettime(CLOCK_MONOTONIC)";
391 #endif
392
393 if (clock_gettime(clk_id, &tp) != 0) {
394 if (raise)
395 PyErr_SetFromErrno(PyExc_OSError);
396 goto error;
397 }
398 ts->tv_sec = tp.tv_sec;
399 ts->tv_nsec = tp.tv_nsec;
400
401 if (info) {
402 struct timespec res;
403 info->monotonic = 1;
404 info->implementation = function;
405 info->adjustable = 0;
406 if (clock_getres(clk_id, &res) == 0)
407 info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
408 else
409 info->resolution = 1e-9;
410 }
411 return 0;
412 #endif
413
414 error:
415 ts->tv_sec = 0;
416 ts->tv_nsec = 0;
417 return -1;
418 }
419
420 void
421 _PyTime_monotonic(_PyTime_timespec *ts)
422 {
423 (void)pymonotonic(ts, NULL, 0);
424 }
Charles-François Natali 2014/07/31 07:33:20 I find the error handling a bit surprising: if pym
haypo 2014/07/31 11:17:44 Would it makes sense to call _PyTime_monotonic_inf
425
426 int
427 _PyTime_monotonic_info(_PyTime_timespec *ts, _Py_clock_info_t *info)
428 {
429 return pymonotonic(ts, info, 1);
430 }
431
432 void
433 _PyTime_Init()
434 {
435 /* Do nothing. Needed to force linking. */
436 }
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7