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

Delta Between Two Patch Sets: Python/pytime.c

Issue 22043: Use a monotonic clock to compute timeouts
Left Patch Set: Created 3 years, 3 months ago
Right Patch Set: Created 3 years, 2 months 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 * pygettimeofday() falls back to ftime when getttimeofday fails because the 8 #endif
9 * latter might fail on some platforms. This fallback is unwanted on MacOSX 9
10 * because that makes it impossible to use a binary build on OSX 10.4 on 10 #ifdef MS_WINDOWS
11 * earlier releases of the OS. Therefore claim we don't support ftime. 11 static OSVERSIONINFOEX winver;
12 */ 12 #endif
13 # undef HAVE_FTIME
14 #endif
15
16 #if defined(HAVE_FTIME) && !defined(MS_WINDOWS)
17 #include <sys/timeb.h>
18 extern int ftime(struct timeb *);
19 #endif
20
21 #if SIZEOF_TIME_T == 8 && defined(HAVE_LONG_LONG)
22 # define TIME_T_MAX ((PY_LONG_LONG)0x7ffffffffffff)
Charles-François Natali 2014/07/31 19:50:26 I don't understand those values. Should it be UINT
haypo 2014/08/01 01:44:20 Done.
23 #elif SIZEOF_TIME_T == 8 && SIZEOF_LONG == 8
24 # define TIME_T_MAX 0x7ffffffffffffL
25 #elif SIZEOF_TIME_T == 4
26 # define TIME_T_MAX 0x7fffffff
27 #else
28 # error "unsupported size of time_t"
29 #endif
30
31 /* one second in milliseconds (ms, 10^-3) */
32 #define SEC_IN_MILLISECONDS (1000UL)
Charles-François Natali 2014/07/31 19:50:26 Why use the complete name for the denominator and
haypo 2014/08/01 01:44:20 Done.
33
34 /* one second in microseconds (us, 10^-6) */
35 #define SEC_IN_MICROSECONDS (1000000UL)
36
37 /* one second in nanoseconds (ns, 10^-9) */
38 #define SEC_IN_NANOSECONDS (1000000000UL)
39
40 /* one millisecond (ms, 10^-3) in nanoseconds (ns, 10^-9) */
41 #define MS_IN_NANOSECONDS (1000000UL)
42
43 /* one microsecond (us, 10^-6) in nanoseconds (ns, 10^-9) */
44 #define US_IN_NANOSECONDS (1000UL)
45
46 static void
47 error_time_t_overflow(void)
48 {
49 PyErr_SetString(PyExc_OverflowError,
50 "timestamp out of range for platform time_t");
51 }
52 13
53 static int 14 static int
54 _PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator, 15 pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info, int raise)
55 double denominator, _PyTime_round_t round,
56 int raise)
57 {
58 double intpart, err;
59 /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
60 volatile double floatpart;
61
62 assert(0 < denominator && denominator < 1.0);
63
64 floatpart = modf(d, &intpart);
65 if (floatpart < 0) {
66 floatpart = 1.0 + floatpart;
67 intpart -= 1.0;
68 }
69
70 floatpart *= denominator;
71 if (round == _PyTime_ROUND_UP) {
72 if (intpart >= 0) {
73 floatpart = ceil(floatpart);
74 if (floatpart >= denominator) {
75 floatpart -= denominator;
76 intpart += 1.0;
77 }
78 }
79 else {
80 floatpart = floor(floatpart);
81 }
82 }
83
84 *sec = (time_t)intpart;
85 err = intpart - (double)*sec;
86 if (err <= -1.0 || err >= 1.0) {
87 if (raise)
88 error_time_t_overflow();
89 return -1;
90 }
91
92 *numerator = (long)floatpart;
93 return 0;
94 }
95
96 static int
97 _PyTimeSpec_set_overflow(_PyTimeSpec *ts)
98 {
99 ts->tv_sec = TIME_T_MAX;
100 ts->tv_nsec = 999999999;
101 return -1;
102 }
103
104 static int
105 _PyTimeSpec_add(_PyTimeSpec *ts, time_t secs, long ns)
106 {
107 assert(ns < SEC_IN_NANOSECONDS);
108
109 if (ts->tv_sec > TIME_T_MAX - secs)
110 goto overflow;
111 ts->tv_sec += secs;
112
113 ts->tv_nsec += ns;
114 while (ts->tv_nsec >= SEC_IN_NANOSECONDS) {
115 ts->tv_nsec -= SEC_IN_NANOSECONDS;
116 if (ts->tv_sec == TIME_T_MAX)
117 goto overflow;
118 ts->tv_sec++;
119 }
120 return 0;
121
122 overflow:
123 return _PyTimeSpec_set_overflow(ts);
124 }
125
126
127 int
128 _PyTimeSpec_add_sec(_PyTimeSpec *ts, double seconds)
129 {
130 time_t secs;
131 long ns;
132
133 if (_PyTime_DoubleToDenominator(seconds, &secs,
134 &ns, 1e-9, _PyTime_ROUND_UP, 0) < 0)
135 return _PyTimeSpec_set_overflow(ts);
136
137 return _PyTimeSpec_add(ts, secs, ns);
138 }
139
140 int
141 _PyTimeSpec_add_us(_PyTimeSpec *ts,
142 _PyTime_unit_t microseconds)
143 {
144 _PyTime_unit_t secs, us;
145
146 us = microseconds % SEC_IN_MICROSECONDS;
147 secs = microseconds / SEC_IN_MICROSECONDS;
148 if (secs > TIME_T_MAX)
149 return _PyTimeSpec_set_overflow(ts);
150
151 return _PyTimeSpec_add(ts, (time_t)secs, us * US_IN_NANOSECONDS);
152 }
153
154 double
155 _PyTimeSpec_interval_sec(_PyTimeSpec *start, _PyTimeSpec *end)
156 {
157 double dt;
158 dt = end->tv_sec - start->tv_sec;
159 dt += (end->tv_nsec - start->tv_nsec) * 1e-9;
160 return dt;
161 }
162
163 _PyTime_unit_t
164 _PyTimeSpec_interval_us(_PyTimeSpec *start, _PyTimeSpec *end)
165 {
166 _PyTime_unit_t us;
167 time_t secs;
168
169 us = (end->tv_nsec - start->tv_nsec) / US_IN_NANOSECONDS;
170 secs = (end->tv_sec - start->tv_sec);
171 if (secs > (_PyTime_UNIT_MAX - us) * SEC_IN_MICROSECONDS)
172 goto overflow;
173 us += secs * SEC_IN_MICROSECONDS;
174 return us;
175
176 overflow:
177 return _PyTime_UNIT_MAX;
178 }
179
180 static int
181 pygettimeofday(_PyTimeSpec *ts, _Py_clock_info_t *info, int raise)
182 { 16 {
183 #ifdef MS_WINDOWS 17 #ifdef MS_WINDOWS
184 FILETIME system_time; 18 FILETIME system_time;
185 ULARGE_INTEGER large; 19 ULARGE_INTEGER large;
186 ULONGLONG nanoseconds; 20 ULONGLONG microseconds;
21
22 assert(info == NULL || raise);
187 23
188 GetSystemTimeAsFileTime(&system_time); 24 GetSystemTimeAsFileTime(&system_time);
189 large.u.LowPart = system_time.dwLowDateTime; 25 large.u.LowPart = system_time.dwLowDateTime;
190 large.u.HighPart = system_time.dwHighDateTime; 26 large.u.HighPart = system_time.dwHighDateTime;
191 /* 11,644,473,600,000,000,000: number of nanoseconds between 27 /* 11,644,473,600,000,000: number of microseconds between
192 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
193 days). */ 29 days). */
194 nanoseconds = large.QuadPart * 100 - 11644473600000000000; 30 microseconds = large.QuadPart / 10 - 11644473600000000;
195 ts->tv_sec = nanoseconds / SEC_IN_NANOSECONDS; 31 tp->tv_sec = microseconds / 1000000;
196 ts->tv_nsec = nanoseconds % SEC_IN_NANOSECONDS; 32 tp->tv_usec = microseconds % 1000000;
197 if (info) { 33 if (info) {
198 DWORD timeAdjustment, timeIncrement; 34 DWORD timeAdjustment, timeIncrement;
199 BOOL isTimeAdjustmentDisabled; 35 BOOL isTimeAdjustmentDisabled, ok;
200 36
201 info->implementation = "GetSystemTimeAsFileTime()"; 37 info->implementation = "GetSystemTimeAsFileTime()";
202 info->monotonic = 0; 38 info->monotonic = 0;
203 (void) GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, 39 ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
204 &isTimeAdjustmentDisabled); 40 &isTimeAdjustmentDisabled);
41 if (!ok) {
42 PyErr_SetFromWindowsErr(0);
43 return -1;
44 }
205 info->resolution = timeIncrement * 1e-7; 45 info->resolution = timeIncrement * 1e-7;
206 info->adjustable = 1; 46 info->adjustable = 1;
207 } 47 }
208 return 0; 48 return 0;
209 #else 49
210 /* There are four ways to get the time: 50 #else /* MS_WINDOWS */
211 (1) gettimeofday() -- resolution in microseconds
212 (2) ftime() -- resolution in milliseconds
213 (3) time() -- resolution in seconds
214 In all cases the return value in a timeval struct.
215 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
216 fail, so we fall back on ftime() or time().
217 Note: clock resolution does not imply clock accuracy! */
218
219 #if defined(HAVE_GETTIMEOFDAY) || defined(HAVE_FTIME)
220 int err; 51 int err;
221 #endif 52 #ifdef HAVE_CLOCK_GETTIME
222 #ifdef HAVE_GETTIMEOFDAY 53 struct timespec ts;
223 struct timeval tv; 54 #endif
224 #endif 55
225 #ifdef HAVE_FTIME 56 assert(info == NULL || raise);
226 struct timeb tb; 57
227 #endif 58 #ifdef HAVE_CLOCK_GETTIME
228 59 err = clock_gettime(CLOCK_REALTIME, &ts);
229 /* test gettimeofday() */ 60 if (err) {
61 if (raise)
62 PyErr_SetFromErrno(PyExc_OSError);
63 return -1;
64 }
65 tp->tv_sec = ts.tv_sec;
66 tp->tv_usec = ts.tv_nsec / 1000;
67
68 if (info) {
69 struct timespec res;
70 info->implementation = "clock_gettime(CLOCK_REALTIME)";
71 info->monotonic = 0;
72 info->adjustable = 1;
73 if (clock_getres(CLOCK_REALTIME, &res) == 0)
74 info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
75 else
76 info->resolution = 1e-9;
77 }
78 return 0;
79 #else /* HAVE_CLOCK_GETTIME */
80
81 /* test gettimeofday() */
230 #ifdef HAVE_GETTIMEOFDAY 82 #ifdef HAVE_GETTIMEOFDAY
231 #ifdef GETTIMEOFDAY_NO_TZ 83 #ifdef GETTIMEOFDAY_NO_TZ
232 err = gettimeofday(&tv); 84 err = gettimeofday(tp);
233 #else 85 #else
234 err = gettimeofday(&tv, (struct timezone *)NULL); 86 err = gettimeofday(tp, (struct timezone *)NULL);
235 #endif 87 #endif
236 if (err && raise) { 88 if (err) {
237 PyErr_SetFromErrno(PyExc_OSError);
238 goto error;
239 }
240 if (!err) {
241 ts->tv_sec = tv.tv_sec;
242 ts->tv_nsec = tv.tv_usec * US_IN_NANOSECONDS;
243 if (info) {
244 info->implementation = "gettimeofday()";
245 info->resolution = 1e-6;
246 info->monotonic = 0;
247 info->adjustable = 1;
248 }
249 return 0;
250 }
251 #endif /* HAVE_GETTIMEOFDAY */
252
253 /* test ftime() */
254 #ifdef HAVE_FTIME
255 err = ftime(&tb);
256 if (err && raise) {
257 PyErr_SetFromErrno(PyExc_OSError);
258 goto error;
259 }
260 if (!err) {
261 ts->tv_sec = tb.time;
262 ts->tv_nsec = tb.millitm * MS_IN_NANOSECONDS;
263 if (info) {
264 info->implementation = "ftime()";
265 info->resolution = 1e-3;
266 info->monotonic = 0;
267 info->adjustable = 1;
268 }
269 return 0;
270 }
271 #endif /* !HAVE_FTIME */
272
273 errno = 0;
274 ts->tv_sec = time(NULL);
275 if (ts->tv_sec == (time_t)-1 && errno != 0) {
276 if (raise) 89 if (raise)
277 PyErr_SetFromErrno(PyExc_OSError); 90 PyErr_SetFromErrno(PyExc_OSError);
278 goto error; 91 return -1;
279 } 92 }
280 ts->tv_nsec = 0; 93
281 if (info) { 94 if (info) {
282 info->implementation = "time()"; 95 info->implementation = "gettimeofday()";
283 info->resolution = 1.0; 96 info->resolution = 1e-6;
284 info->monotonic = 0; 97 info->monotonic = 0;
285 info->adjustable = 1; 98 info->adjustable = 1;
286 } 99 }
287 return 0; 100 return 0;
288 101 #endif /* HAVE_GETTIMEOFDAY */
289 error: 102 #endif /* !HAVE_CLOCK_GETTIME */
290 ts->tv_sec = 0; 103 #endif /* !MS_WINDOWS */
291 ts->tv_nsec = 0;
292 return -1;
293
294 #endif /* MS_WINDOWS */
295 } 104 }
296 105
297 void 106 void
298 _PyTimeSpec_get_time(_PyTimeSpec *tp) 107 _PyTime_gettimeofday(_PyTime_timeval *tp)
299 { 108 {
300 /* _PyTimeSpec_Init() checked that the system clock works. */ 109 if (pygettimeofday(tp, NULL, 0) < 0) {
301 (void)pygettimeofday(tp, NULL, 0); 110 /* cannot happen, _PyTime_Init() checks that pygettimeofday() works */
302 } 111 assert(0);
303 112 tp->tv_sec = 0;
304 int 113 tp->tv_usec = 0;
305 _PyTimeSpec_get_time_info(_PyTimeSpec *tp, _Py_clock_info_t *info) 114 }
306 { 115 }
307 /* _PyTimeSpec_Init() checked that the system clock works. */ 116
117 int
118 _PyTime_gettimeofday_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
119 {
308 return pygettimeofday(tp, info, 1); 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
250 }
251
252 void
253 _PyTime_monotonic(_PyTime_timeval *tp)
254 {
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);
267 }
268
269 static void
270 error_time_t_overflow(void)
271 {
272 PyErr_SetString(PyExc_OverflowError,
273 "timestamp out of range for platform time_t");
309 } 274 }
310 275
311 time_t 276 time_t
312 _PyLong_AsTime_t(PyObject *obj) 277 _PyLong_AsTime_t(PyObject *obj)
313 { 278 {
314 #if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG 279 #if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
315 PY_LONG_LONG val; 280 PY_LONG_LONG val;
316 val = PyLong_AsLongLong(obj); 281 val = PyLong_AsLongLong(obj);
317 #else 282 #else
318 long val; 283 long val;
(...skipping 18 matching lines...) Expand all
337 return PyLong_FromLong((long)t); 302 return PyLong_FromLong((long)t);
338 #endif 303 #endif
339 } 304 }
340 305
341 static int 306 static int
342 _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, 307 _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
343 double denominator, _PyTime_round_t round) 308 double denominator, _PyTime_round_t round)
344 { 309 {
345 assert(denominator <= LONG_MAX); 310 assert(denominator <= LONG_MAX);
346 if (PyFloat_Check(obj)) { 311 if (PyFloat_Check(obj)) {
347 double d = PyFloat_AsDouble(obj); 312 double d, intpart, err;
348 return _PyTime_DoubleToDenominator(d, sec, numerator, 313 /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
349 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;
350 } 346 }
351 else { 347 else {
352 *sec = _PyLong_AsTime_t(obj); 348 *sec = _PyLong_AsTime_t(obj);
353 if (*sec == (time_t)-1 && PyErr_Occurred()) 349 if (*sec == (time_t)-1 && PyErr_Occurred())
354 return -1; 350 return -1;
355 *numerator = 0; 351 *numerator = 0;
356 return 0; 352 return 0;
357 } 353 }
358 } 354 }
359 355
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 } 392 }
397 393
398 int 394 int
399 _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec, 395 _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
400 _PyTime_round_t round) 396 _PyTime_round_t round)
401 { 397 {
402 return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round); 398 return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
403 } 399 }
404 400
405 int 401 int
406 _PyTimeSpec_Init(void) 402 _PyTime_Init(void)
407 { 403 {
408 _PyTimeSpec ts; 404 _PyTime_timeval tv;
405
406 #ifdef MS_WINDOWS
407 winver.dwOSVersionInfoSize = sizeof(winver);
408 if (!GetVersionEx((OSVERSIONINFO*)&winver)) {
409 PyErr_SetFromWindowsErr(0);
410 return -1;
411 }
412 #endif
413
409 /* ensure that the system clock works */ 414 /* ensure that the system clock works */
410 if (_PyTimeSpec_get_time_info(&ts, NULL) < 0) 415 if (_PyTime_gettimeofday_info(&tv, NULL) < 0)
411 return -1; 416 return -1;
412 return 0; 417
413 } 418 /* ensure that the operating system provides a monotonic clock */
419 if (_PyTime_monotonic_info(&tv, NULL) < 0)
420 return -1;
421 return 0;
422 }
LEFTRIGHT

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