Branch data Line data Source code
1 : : /* Time module */
2 : :
3 : : #include "Python.h"
4 : : #include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
5 : : #include "pycore_moduleobject.h" // _PyModule_GetState()
6 : : #include "pycore_namespace.h" // _PyNamespace_New()
7 : : #include "pycore_runtime.h" // _Py_ID()
8 : :
9 : : #include <ctype.h>
10 : :
11 : : #ifdef HAVE_SYS_TIMES_H
12 : : # include <sys/times.h>
13 : : #endif
14 : : #ifdef HAVE_SYS_TYPES_H
15 : : # include <sys/types.h>
16 : : #endif
17 : : #if defined(HAVE_SYS_RESOURCE_H)
18 : : # include <sys/resource.h>
19 : : #endif
20 : : #ifdef QUICKWIN
21 : : # include <io.h>
22 : : #endif
23 : : #if defined(HAVE_PTHREAD_H)
24 : : # include <pthread.h>
25 : : #endif
26 : : #if defined(_AIX)
27 : : # include <sys/thread.h>
28 : : #endif
29 : : #if defined(__WATCOMC__) && !defined(__QNX__)
30 : : # include <i86.h>
31 : : #else
32 : : # ifdef MS_WINDOWS
33 : : # define WIN32_LEAN_AND_MEAN
34 : : # include <windows.h>
35 : : # endif /* MS_WINDOWS */
36 : : #endif /* !__WATCOMC__ || __QNX__ */
37 : :
38 : : #ifdef _Py_MEMORY_SANITIZER
39 : : # include <sanitizer/msan_interface.h>
40 : : #endif
41 : :
42 : : #ifdef _MSC_VER
43 : : # define _Py_timezone _timezone
44 : : # define _Py_daylight _daylight
45 : : # define _Py_tzname _tzname
46 : : #else
47 : : # define _Py_timezone timezone
48 : : # define _Py_daylight daylight
49 : : # define _Py_tzname tzname
50 : : #endif
51 : :
52 : : #if defined(__APPLE__ ) && defined(__has_builtin)
53 : : # if __has_builtin(__builtin_available)
54 : : # define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
55 : : # endif
56 : : #endif
57 : : #ifndef HAVE_CLOCK_GETTIME_RUNTIME
58 : : # define HAVE_CLOCK_GETTIME_RUNTIME 1
59 : : #endif
60 : :
61 : :
62 : : #define SEC_TO_NS (1000 * 1000 * 1000)
63 : :
64 : :
65 : : /* Forward declarations */
66 : : static int pysleep(_PyTime_t timeout);
67 : :
68 : :
69 : : typedef struct {
70 : : PyTypeObject *struct_time_type;
71 : : } time_module_state;
72 : :
73 : : static inline time_module_state*
74 : 100731 : get_time_state(PyObject *module)
75 : : {
76 : 100731 : void *state = _PyModule_GetState(module);
77 : : assert(state != NULL);
78 : 100731 : return (time_module_state *)state;
79 : : }
80 : :
81 : :
82 : : static PyObject*
83 : 340026 : _PyFloat_FromPyTime(_PyTime_t t)
84 : : {
85 : 340026 : double d = _PyTime_AsSecondsDouble(t);
86 : 340026 : return PyFloat_FromDouble(d);
87 : : }
88 : :
89 : :
90 : : static int
91 : 86523 : get_system_time(_PyTime_t *t)
92 : : {
93 : : // Avoid _PyTime_GetSystemClock() which silently ignores errors.
94 : 86523 : return _PyTime_GetSystemClockWithInfo(t, NULL);
95 : : }
96 : :
97 : :
98 : : static PyObject *
99 : 85498 : time_time(PyObject *self, PyObject *unused)
100 : : {
101 : : _PyTime_t t;
102 [ - + ]: 85498 : if (get_system_time(&t) < 0) {
103 : 0 : return NULL;
104 : : }
105 : 85498 : return _PyFloat_FromPyTime(t);
106 : : }
107 : :
108 : :
109 : : PyDoc_STRVAR(time_doc,
110 : : "time() -> floating point number\n\
111 : : \n\
112 : : Return the current time in seconds since the Epoch.\n\
113 : : Fractions of a second may be present if the system clock provides them.");
114 : :
115 : : static PyObject *
116 : 1025 : time_time_ns(PyObject *self, PyObject *unused)
117 : : {
118 : : _PyTime_t t;
119 [ - + ]: 1025 : if (get_system_time(&t) < 0) {
120 : 0 : return NULL;
121 : : }
122 : 1025 : return _PyTime_AsNanosecondsObject(t);
123 : : }
124 : :
125 : : PyDoc_STRVAR(time_ns_doc,
126 : : "time_ns() -> int\n\
127 : : \n\
128 : : Return the current time in nanoseconds since the Epoch.");
129 : :
130 : : #if defined(HAVE_CLOCK)
131 : :
132 : : #ifndef CLOCKS_PER_SEC
133 : : # ifdef CLK_TCK
134 : : # define CLOCKS_PER_SEC CLK_TCK
135 : : # else
136 : : # define CLOCKS_PER_SEC 1000000
137 : : # endif
138 : : #endif
139 : :
140 : : static int
141 : 0 : _PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
142 : : {
143 : : static int initialized = 0;
144 : :
145 [ # # ]: 0 : if (!initialized) {
146 : 0 : initialized = 1;
147 : :
148 : : /* Make sure that _PyTime_MulDiv(ticks, SEC_TO_NS, CLOCKS_PER_SEC)
149 : : above cannot overflow */
150 : : if ((_PyTime_t)CLOCKS_PER_SEC > _PyTime_MAX / SEC_TO_NS) {
151 : : PyErr_SetString(PyExc_OverflowError,
152 : : "CLOCKS_PER_SEC is too large");
153 : : return -1;
154 : : }
155 : : }
156 : :
157 [ # # ]: 0 : if (info) {
158 : 0 : info->implementation = "clock()";
159 : 0 : info->resolution = 1.0 / (double)CLOCKS_PER_SEC;
160 : 0 : info->monotonic = 1;
161 : 0 : info->adjustable = 0;
162 : : }
163 : :
164 : 0 : clock_t ticks = clock();
165 [ # # ]: 0 : if (ticks == (clock_t)-1) {
166 : 0 : PyErr_SetString(PyExc_RuntimeError,
167 : : "the processor time used is not available "
168 : : "or its value cannot be represented");
169 : 0 : return -1;
170 : : }
171 : 0 : _PyTime_t ns = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)CLOCKS_PER_SEC);
172 : 0 : *tp = _PyTime_FromNanoseconds(ns);
173 : 0 : return 0;
174 : : }
175 : : #endif /* HAVE_CLOCK */
176 : :
177 : :
178 : : #ifdef HAVE_CLOCK_GETTIME
179 : :
180 : : #ifdef __APPLE__
181 : : /*
182 : : * The clock_* functions will be removed from the module
183 : : * dict entirely when the C API is not available.
184 : : */
185 : : #pragma clang diagnostic push
186 : : #pragma clang diagnostic ignored "-Wunguarded-availability"
187 : : #endif
188 : :
189 : : static PyObject *
190 : 8 : time_clock_gettime(PyObject *self, PyObject *args)
191 : : {
192 : : int ret;
193 : : struct timespec tp;
194 : :
195 : : #if defined(_AIX) && (SIZEOF_LONG == 8)
196 : : long clk_id;
197 : : if (!PyArg_ParseTuple(args, "l:clock_gettime", &clk_id)) {
198 : : #else
199 : : int clk_id;
200 [ - + ]: 8 : if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) {
201 : : #endif
202 : 0 : return NULL;
203 : : }
204 : :
205 : 8 : ret = clock_gettime((clockid_t)clk_id, &tp);
206 [ - + ]: 8 : if (ret != 0) {
207 : 0 : PyErr_SetFromErrno(PyExc_OSError);
208 : 0 : return NULL;
209 : : }
210 : 8 : return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
211 : : }
212 : :
213 : : PyDoc_STRVAR(clock_gettime_doc,
214 : : "clock_gettime(clk_id) -> float\n\
215 : : \n\
216 : : Return the time of the specified clock clk_id.");
217 : :
218 : : static PyObject *
219 : 1 : time_clock_gettime_ns(PyObject *self, PyObject *args)
220 : : {
221 : : int ret;
222 : : int clk_id;
223 : : struct timespec ts;
224 : : _PyTime_t t;
225 : :
226 [ - + ]: 1 : if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) {
227 : 0 : return NULL;
228 : : }
229 : :
230 : 1 : ret = clock_gettime((clockid_t)clk_id, &ts);
231 [ - + ]: 1 : if (ret != 0) {
232 : 0 : PyErr_SetFromErrno(PyExc_OSError);
233 : 0 : return NULL;
234 : : }
235 [ - + ]: 1 : if (_PyTime_FromTimespec(&t, &ts) < 0) {
236 : 0 : return NULL;
237 : : }
238 : 1 : return _PyTime_AsNanosecondsObject(t);
239 : : }
240 : :
241 : : PyDoc_STRVAR(clock_gettime_ns_doc,
242 : : "clock_gettime_ns(clk_id) -> int\n\
243 : : \n\
244 : : Return the time of the specified clock clk_id as nanoseconds.");
245 : : #endif /* HAVE_CLOCK_GETTIME */
246 : :
247 : : #ifdef HAVE_CLOCK_SETTIME
248 : : static PyObject *
249 : 3 : time_clock_settime(PyObject *self, PyObject *args)
250 : : {
251 : : int clk_id;
252 : : PyObject *obj;
253 : : _PyTime_t t;
254 : : struct timespec tp;
255 : : int ret;
256 : :
257 [ - + ]: 3 : if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj))
258 : 0 : return NULL;
259 : :
260 [ - + ]: 3 : if (_PyTime_FromSecondsObject(&t, obj, _PyTime_ROUND_FLOOR) < 0)
261 : 0 : return NULL;
262 : :
263 [ - + ]: 3 : if (_PyTime_AsTimespec(t, &tp) == -1)
264 : 0 : return NULL;
265 : :
266 : 3 : ret = clock_settime((clockid_t)clk_id, &tp);
267 [ + - ]: 3 : if (ret != 0) {
268 : 3 : PyErr_SetFromErrno(PyExc_OSError);
269 : 3 : return NULL;
270 : : }
271 : 0 : Py_RETURN_NONE;
272 : : }
273 : :
274 : : PyDoc_STRVAR(clock_settime_doc,
275 : : "clock_settime(clk_id, time)\n\
276 : : \n\
277 : : Set the time of the specified clock clk_id.");
278 : :
279 : : static PyObject *
280 : 0 : time_clock_settime_ns(PyObject *self, PyObject *args)
281 : : {
282 : : int clk_id;
283 : : PyObject *obj;
284 : : _PyTime_t t;
285 : : struct timespec ts;
286 : : int ret;
287 : :
288 [ # # ]: 0 : if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) {
289 : 0 : return NULL;
290 : : }
291 : :
292 [ # # ]: 0 : if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
293 : 0 : return NULL;
294 : : }
295 [ # # ]: 0 : if (_PyTime_AsTimespec(t, &ts) == -1) {
296 : 0 : return NULL;
297 : : }
298 : :
299 : 0 : ret = clock_settime((clockid_t)clk_id, &ts);
300 [ # # ]: 0 : if (ret != 0) {
301 : 0 : PyErr_SetFromErrno(PyExc_OSError);
302 : 0 : return NULL;
303 : : }
304 : 0 : Py_RETURN_NONE;
305 : : }
306 : :
307 : : PyDoc_STRVAR(clock_settime_ns_doc,
308 : : "clock_settime_ns(clk_id, time)\n\
309 : : \n\
310 : : Set the time of the specified clock clk_id with nanoseconds.");
311 : : #endif /* HAVE_CLOCK_SETTIME */
312 : :
313 : : #ifdef HAVE_CLOCK_GETRES
314 : : static PyObject *
315 : 1 : time_clock_getres(PyObject *self, PyObject *args)
316 : : {
317 : : int ret;
318 : : int clk_id;
319 : : struct timespec tp;
320 : :
321 [ - + ]: 1 : if (!PyArg_ParseTuple(args, "i:clock_getres", &clk_id))
322 : 0 : return NULL;
323 : :
324 : 1 : ret = clock_getres((clockid_t)clk_id, &tp);
325 [ - + ]: 1 : if (ret != 0) {
326 : 0 : PyErr_SetFromErrno(PyExc_OSError);
327 : 0 : return NULL;
328 : : }
329 : :
330 : 1 : return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
331 : : }
332 : :
333 : : PyDoc_STRVAR(clock_getres_doc,
334 : : "clock_getres(clk_id) -> floating point number\n\
335 : : \n\
336 : : Return the resolution (precision) of the specified clock clk_id.");
337 : :
338 : : #ifdef __APPLE__
339 : : #pragma clang diagnostic pop
340 : : #endif
341 : :
342 : : #endif /* HAVE_CLOCK_GETRES */
343 : :
344 : : #ifdef HAVE_PTHREAD_GETCPUCLOCKID
345 : : static PyObject *
346 : 1 : time_pthread_getcpuclockid(PyObject *self, PyObject *args)
347 : : {
348 : : unsigned long thread_id;
349 : : int err;
350 : : clockid_t clk_id;
351 [ - + ]: 1 : if (!PyArg_ParseTuple(args, "k:pthread_getcpuclockid", &thread_id)) {
352 : 0 : return NULL;
353 : : }
354 : 1 : err = pthread_getcpuclockid((pthread_t)thread_id, &clk_id);
355 [ - + ]: 1 : if (err) {
356 : 0 : errno = err;
357 : 0 : PyErr_SetFromErrno(PyExc_OSError);
358 : 0 : return NULL;
359 : : }
360 : : #ifdef _Py_MEMORY_SANITIZER
361 : : __msan_unpoison(&clk_id, sizeof(clk_id));
362 : : #endif
363 : 1 : return PyLong_FromLong(clk_id);
364 : : }
365 : :
366 : : PyDoc_STRVAR(pthread_getcpuclockid_doc,
367 : : "pthread_getcpuclockid(thread_id) -> int\n\
368 : : \n\
369 : : Return the clk_id of a thread's CPU time clock.");
370 : : #endif /* HAVE_PTHREAD_GETCPUCLOCKID */
371 : :
372 : : static PyObject *
373 : 64988 : time_sleep(PyObject *self, PyObject *timeout_obj)
374 : : {
375 : : _PyTime_t timeout;
376 [ + + ]: 64988 : if (_PyTime_FromSecondsObject(&timeout, timeout_obj, _PyTime_ROUND_TIMEOUT))
377 : 1 : return NULL;
378 [ + + ]: 64987 : if (timeout < 0) {
379 : 2 : PyErr_SetString(PyExc_ValueError,
380 : : "sleep length must be non-negative");
381 : 2 : return NULL;
382 : : }
383 [ - + ]: 64985 : if (pysleep(timeout) != 0) {
384 : 0 : return NULL;
385 : : }
386 : 64949 : Py_RETURN_NONE;
387 : : }
388 : :
389 : : PyDoc_STRVAR(sleep_doc,
390 : : "sleep(seconds)\n\
391 : : \n\
392 : : Delay execution for a given number of seconds. The argument may be\n\
393 : : a floating point number for subsecond precision.");
394 : :
395 : : static PyStructSequence_Field struct_time_type_fields[] = {
396 : : {"tm_year", "year, for example, 1993"},
397 : : {"tm_mon", "month of year, range [1, 12]"},
398 : : {"tm_mday", "day of month, range [1, 31]"},
399 : : {"tm_hour", "hours, range [0, 23]"},
400 : : {"tm_min", "minutes, range [0, 59]"},
401 : : {"tm_sec", "seconds, range [0, 61])"},
402 : : {"tm_wday", "day of week, range [0, 6], Monday is 0"},
403 : : {"tm_yday", "day of year, range [1, 366]"},
404 : : {"tm_isdst", "1 if summer time is in effect, 0 if not, and -1 if unknown"},
405 : : {"tm_zone", "abbreviation of timezone name"},
406 : : {"tm_gmtoff", "offset from UTC in seconds"},
407 : : {0}
408 : : };
409 : :
410 : : static PyStructSequence_Desc struct_time_type_desc = {
411 : : "time.struct_time",
412 : : "The time value as returned by gmtime(), localtime(), and strptime(), and\n"
413 : : " accepted by asctime(), mktime() and strftime(). May be considered as a\n"
414 : : " sequence of 9 integers.\n\n"
415 : : " Note that several fields' values are not the same as those defined by\n"
416 : : " the C language standard for struct tm. For example, the value of the\n"
417 : : " field tm_year is the actual year, not year - 1900. See individual\n"
418 : : " fields' descriptions for details.",
419 : : struct_time_type_fields,
420 : : 9,
421 : : };
422 : :
423 : : #if defined(MS_WINDOWS)
424 : : #ifndef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
425 : : #define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION 0x00000002
426 : : #endif
427 : :
428 : : static DWORD timer_flags = (DWORD)-1;
429 : : #endif
430 : :
431 : : static PyObject *
432 : 16254 : tmtotuple(time_module_state *state, struct tm *p
433 : : #ifndef HAVE_STRUCT_TM_TM_ZONE
434 : : , const char *zone, time_t gmtoff
435 : : #endif
436 : : )
437 : : {
438 : 16254 : PyObject *v = PyStructSequence_New(state->struct_time_type);
439 [ - + ]: 16254 : if (v == NULL)
440 : 0 : return NULL;
441 : :
442 : : #define SET(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val))
443 : :
444 : 16254 : SET(0, p->tm_year + 1900);
445 : 16254 : SET(1, p->tm_mon + 1); /* Want January == 1 */
446 : 16254 : SET(2, p->tm_mday);
447 : 16254 : SET(3, p->tm_hour);
448 : 16254 : SET(4, p->tm_min);
449 : 16254 : SET(5, p->tm_sec);
450 : 16254 : SET(6, (p->tm_wday + 6) % 7); /* Want Monday == 0 */
451 : 16254 : SET(7, p->tm_yday + 1); /* Want January, 1 == 1 */
452 : 16254 : SET(8, p->tm_isdst);
453 : : #ifdef HAVE_STRUCT_TM_TM_ZONE
454 : 16254 : PyStructSequence_SET_ITEM(v, 9,
455 : : PyUnicode_DecodeLocale(p->tm_zone, "surrogateescape"));
456 : 16254 : SET(10, p->tm_gmtoff);
457 : : #else
458 : : PyStructSequence_SET_ITEM(v, 9,
459 : : PyUnicode_DecodeLocale(zone, "surrogateescape"));
460 : : PyStructSequence_SET_ITEM(v, 10, _PyLong_FromTime_t(gmtoff));
461 : : #endif /* HAVE_STRUCT_TM_TM_ZONE */
462 : : #undef SET
463 [ - + ]: 16254 : if (PyErr_Occurred()) {
464 : 0 : Py_XDECREF(v);
465 : 0 : return NULL;
466 : : }
467 : :
468 : 16254 : return v;
469 : : }
470 : :
471 : : /* Parse arg tuple that can contain an optional float-or-None value;
472 : : format needs to be "|O:name".
473 : : Returns non-zero on success (parallels PyArg_ParseTuple).
474 : : */
475 : : static int
476 : 16523 : parse_time_t_args(PyObject *args, const char *format, time_t *pwhen)
477 : : {
478 : 16523 : PyObject *ot = NULL;
479 : : time_t whent;
480 : :
481 [ - + ]: 16523 : if (!PyArg_ParseTuple(args, format, &ot))
482 : 0 : return 0;
483 [ + + + + ]: 16523 : if (ot == NULL || ot == Py_None) {
484 : 728 : whent = time(NULL);
485 : : }
486 : : else {
487 [ + + ]: 15795 : if (_PyTime_ObjectToTime_t(ot, &whent, _PyTime_ROUND_FLOOR) == -1)
488 : 22 : return 0;
489 : : }
490 : 16501 : *pwhen = whent;
491 : 16501 : return 1;
492 : : }
493 : :
494 : : static PyObject *
495 : 1904 : time_gmtime(PyObject *module, PyObject *args)
496 : : {
497 : : time_t when;
498 : : struct tm buf;
499 : :
500 [ + + ]: 1904 : if (!parse_time_t_args(args, "|O:gmtime", &when))
501 : 8 : return NULL;
502 : :
503 : 1896 : errno = 0;
504 [ - + ]: 1896 : if (_PyTime_gmtime(when, &buf) != 0)
505 : 0 : return NULL;
506 : :
507 : 1896 : time_module_state *state = get_time_state(module);
508 : : #ifdef HAVE_STRUCT_TM_TM_ZONE
509 : 1896 : return tmtotuple(state, &buf);
510 : : #else
511 : : return tmtotuple(state, &buf, "UTC", 0);
512 : : #endif
513 : : }
514 : :
515 : : #ifndef HAVE_TIMEGM
516 : : static time_t
517 : : timegm(struct tm *p)
518 : : {
519 : : /* XXX: the following implementation will not work for tm_year < 1970.
520 : : but it is likely that platforms that don't have timegm do not support
521 : : negative timestamps anyways. */
522 : : return p->tm_sec + p->tm_min*60 + p->tm_hour*3600 + p->tm_yday*86400 +
523 : : (p->tm_year-70)*31536000 + ((p->tm_year-69)/4)*86400 -
524 : : ((p->tm_year-1)/100)*86400 + ((p->tm_year+299)/400)*86400;
525 : : }
526 : : #endif
527 : :
528 : : PyDoc_STRVAR(gmtime_doc,
529 : : "gmtime([seconds]) -> (tm_year, tm_mon, tm_mday, tm_hour, tm_min,\n\
530 : : tm_sec, tm_wday, tm_yday, tm_isdst)\n\
531 : : \n\
532 : : Convert seconds since the Epoch to a time tuple expressing UTC (a.k.a.\n\
533 : : GMT). When 'seconds' is not passed in, convert the current time instead.\n\
534 : : \n\
535 : : If the platform supports the tm_gmtoff and tm_zone, they are available as\n\
536 : : attributes only.");
537 : :
538 : : static PyObject *
539 : 14371 : time_localtime(PyObject *module, PyObject *args)
540 : : {
541 : : time_t when;
542 : : struct tm buf;
543 : :
544 [ + + ]: 14371 : if (!parse_time_t_args(args, "|O:localtime", &when))
545 : 11 : return NULL;
546 [ + + ]: 14360 : if (_PyTime_localtime(when, &buf) != 0)
547 : 2 : return NULL;
548 : :
549 : 14358 : time_module_state *state = get_time_state(module);
550 : : #ifdef HAVE_STRUCT_TM_TM_ZONE
551 : 14358 : return tmtotuple(state, &buf);
552 : : #else
553 : : {
554 : : struct tm local = buf;
555 : : char zone[100];
556 : : time_t gmtoff;
557 : : strftime(zone, sizeof(zone), "%Z", &buf);
558 : : gmtoff = timegm(&buf) - when;
559 : : return tmtotuple(state, &local, zone, gmtoff);
560 : : }
561 : : #endif
562 : : }
563 : :
564 : : #if defined(__linux__) && !defined(__GLIBC__)
565 : : static const char *utc_string = NULL;
566 : : #endif
567 : :
568 : : PyDoc_STRVAR(localtime_doc,
569 : : "localtime([seconds]) -> (tm_year,tm_mon,tm_mday,tm_hour,tm_min,\n\
570 : : tm_sec,tm_wday,tm_yday,tm_isdst)\n\
571 : : \n\
572 : : Convert seconds since the Epoch to a time tuple expressing local time.\n\
573 : : When 'seconds' is not passed in, convert the current time instead.");
574 : :
575 : : /* Convert 9-item tuple to tm structure. Return 1 on success, set
576 : : * an exception and return 0 on error.
577 : : */
578 : : static int
579 : 16165 : gettmarg(time_module_state *state, PyObject *args,
580 : : struct tm *p, const char *format)
581 : : {
582 : : int y;
583 : :
584 : 16165 : memset((void *) p, '\0', sizeof(struct tm));
585 : :
586 [ + + ]: 16165 : if (!PyTuple_Check(args)) {
587 : 1 : PyErr_SetString(PyExc_TypeError,
588 : : "Tuple or struct_time argument required");
589 : 1 : return 0;
590 : : }
591 : :
592 [ + + ]: 16164 : if (!PyArg_ParseTuple(args, format,
593 : : &y, &p->tm_mon, &p->tm_mday,
594 : : &p->tm_hour, &p->tm_min, &p->tm_sec,
595 : : &p->tm_wday, &p->tm_yday, &p->tm_isdst))
596 : 4 : return 0;
597 : :
598 [ + + ]: 16160 : if (y < INT_MIN + 1900) {
599 : 5 : PyErr_SetString(PyExc_OverflowError, "year out of range");
600 : 5 : return 0;
601 : : }
602 : :
603 : 16155 : p->tm_year = y - 1900;
604 : 16155 : p->tm_mon--;
605 : 16155 : p->tm_wday = (p->tm_wday + 1) % 7;
606 : 16155 : p->tm_yday--;
607 : : #ifdef HAVE_STRUCT_TM_TM_ZONE
608 [ + + ]: 16155 : if (Py_IS_TYPE(args, state->struct_time_type)) {
609 : : PyObject *item;
610 : 15725 : item = PyStructSequence_GET_ITEM(args, 9);
611 [ + + ]: 15725 : if (item != Py_None) {
612 : 10359 : p->tm_zone = (char *)PyUnicode_AsUTF8(item);
613 [ - + ]: 10359 : if (p->tm_zone == NULL) {
614 : 0 : return 0;
615 : : }
616 : : #if defined(__linux__) && !defined(__GLIBC__)
617 : : // Make an attempt to return the C library's own timezone strings to
618 : : // it. musl refuses to process a tm_zone field unless it produced
619 : : // it. See issue #34672.
620 : : if (utc_string && strcmp(p->tm_zone, utc_string) == 0) {
621 : : p->tm_zone = utc_string;
622 : : }
623 : : else if (tzname[0] && strcmp(p->tm_zone, tzname[0]) == 0) {
624 : : p->tm_zone = tzname[0];
625 : : }
626 : : else if (tzname[1] && strcmp(p->tm_zone, tzname[1]) == 0) {
627 : : p->tm_zone = tzname[1];
628 : : }
629 : : #endif
630 : : }
631 : 15725 : item = PyStructSequence_GET_ITEM(args, 10);
632 [ + + ]: 15725 : if (item != Py_None) {
633 : 10359 : p->tm_gmtoff = PyLong_AsLong(item);
634 [ - + ]: 10359 : if (PyErr_Occurred())
635 : 0 : return 0;
636 : : }
637 : : }
638 : : #endif /* HAVE_STRUCT_TM_TM_ZONE */
639 : 16155 : return 1;
640 : : }
641 : :
642 : : /* Check values of the struct tm fields before it is passed to strftime() and
643 : : * asctime(). Return 1 if all values are valid, otherwise set an exception
644 : : * and returns 0.
645 : : */
646 : : static int
647 : 15844 : checktm(struct tm* buf)
648 : : {
649 : : /* Checks added to make sure strftime() and asctime() does not crash Python by
650 : : indexing blindly into some array for a textual representation
651 : : by some bad index (fixes bug #897625 and #6608).
652 : :
653 : : Also support values of zero from Python code for arguments in which
654 : : that is out of range by forcing that value to the lowest value that
655 : : is valid (fixed bug #1520914).
656 : :
657 : : Valid ranges based on what is allowed in struct tm:
658 : :
659 : : - tm_year: [0, max(int)] (1)
660 : : - tm_mon: [0, 11] (2)
661 : : - tm_mday: [1, 31]
662 : : - tm_hour: [0, 23]
663 : : - tm_min: [0, 59]
664 : : - tm_sec: [0, 60]
665 : : - tm_wday: [0, 6] (1)
666 : : - tm_yday: [0, 365] (2)
667 : : - tm_isdst: [-max(int), max(int)]
668 : :
669 : : (1) gettmarg() handles bounds-checking.
670 : : (2) Python's acceptable range is one greater than the range in C,
671 : : thus need to check against automatic decrement by gettmarg().
672 : : */
673 [ + + ]: 15844 : if (buf->tm_mon == -1)
674 : 41 : buf->tm_mon = 0;
675 [ + + + + ]: 15803 : else if (buf->tm_mon < 0 || buf->tm_mon > 11) {
676 : 4 : PyErr_SetString(PyExc_ValueError, "month out of range");
677 : 4 : return 0;
678 : : }
679 [ + + ]: 15840 : if (buf->tm_mday == 0)
680 : 41 : buf->tm_mday = 1;
681 [ + + + + ]: 15799 : else if (buf->tm_mday < 0 || buf->tm_mday > 31) {
682 : 4 : PyErr_SetString(PyExc_ValueError, "day of month out of range");
683 : 4 : return 0;
684 : : }
685 [ + + + + ]: 15836 : if (buf->tm_hour < 0 || buf->tm_hour > 23) {
686 : 4 : PyErr_SetString(PyExc_ValueError, "hour out of range");
687 : 4 : return 0;
688 : : }
689 [ + + + + ]: 15832 : if (buf->tm_min < 0 || buf->tm_min > 59) {
690 : 4 : PyErr_SetString(PyExc_ValueError, "minute out of range");
691 : 4 : return 0;
692 : : }
693 [ + + + + ]: 15828 : if (buf->tm_sec < 0 || buf->tm_sec > 61) {
694 : 4 : PyErr_SetString(PyExc_ValueError, "seconds out of range");
695 : 4 : return 0;
696 : : }
697 : : /* tm_wday does not need checking of its upper-bound since taking
698 : : ``% 7`` in gettmarg() automatically restricts the range. */
699 [ + + ]: 15824 : if (buf->tm_wday < 0) {
700 : 2 : PyErr_SetString(PyExc_ValueError, "day of week out of range");
701 : 2 : return 0;
702 : : }
703 [ + + ]: 15822 : if (buf->tm_yday == -1)
704 : 48 : buf->tm_yday = 0;
705 [ + + + + ]: 15774 : else if (buf->tm_yday < 0 || buf->tm_yday > 365) {
706 : 4 : PyErr_SetString(PyExc_ValueError, "day of year out of range");
707 : 4 : return 0;
708 : : }
709 : 15818 : return 1;
710 : : }
711 : :
712 : : #ifdef MS_WINDOWS
713 : : /* wcsftime() doesn't format correctly time zones, see issue #10653 */
714 : : # undef HAVE_WCSFTIME
715 : : #endif
716 : : #define STRFTIME_FORMAT_CODES \
717 : : "Commonly used format codes:\n\
718 : : \n\
719 : : %Y Year with century as a decimal number.\n\
720 : : %m Month as a decimal number [01,12].\n\
721 : : %d Day of the month as a decimal number [01,31].\n\
722 : : %H Hour (24-hour clock) as a decimal number [00,23].\n\
723 : : %M Minute as a decimal number [00,59].\n\
724 : : %S Second as a decimal number [00,61].\n\
725 : : %z Time zone offset from UTC.\n\
726 : : %a Locale's abbreviated weekday name.\n\
727 : : %A Locale's full weekday name.\n\
728 : : %b Locale's abbreviated month name.\n\
729 : : %B Locale's full month name.\n\
730 : : %c Locale's appropriate date and time representation.\n\
731 : : %I Hour (12-hour clock) as a decimal number [01,12].\n\
732 : : %p Locale's equivalent of either AM or PM.\n\
733 : : \n\
734 : : Other codes may be available on your platform. See documentation for\n\
735 : : the C library strftime function.\n"
736 : :
737 : : #ifdef HAVE_STRFTIME
738 : : #ifdef HAVE_WCSFTIME
739 : : #define time_char wchar_t
740 : : #define format_time wcsftime
741 : : #define time_strlen wcslen
742 : : #else
743 : : #define time_char char
744 : : #define format_time strftime
745 : : #define time_strlen strlen
746 : : #endif
747 : :
748 : : static PyObject *
749 : 16474 : time_strftime(PyObject *module, PyObject *args)
750 : : {
751 : 16474 : PyObject *tup = NULL;
752 : : struct tm buf;
753 : : const time_char *fmt;
754 : : #ifdef HAVE_WCSFTIME
755 : : wchar_t *format;
756 : : #else
757 : : PyObject *format;
758 : : #endif
759 : : PyObject *format_arg;
760 : : size_t fmtlen, buflen;
761 : 16474 : time_char *outbuf = NULL;
762 : : size_t i;
763 : 16474 : PyObject *ret = NULL;
764 : :
765 : 16474 : memset((void *) &buf, '\0', sizeof(buf));
766 : :
767 : : /* Will always expect a unicode string to be passed as format.
768 : : Given that there's no str type anymore in py3k this seems safe.
769 : : */
770 [ + + ]: 16474 : if (!PyArg_ParseTuple(args, "U|O:strftime", &format_arg, &tup))
771 : 1 : return NULL;
772 : :
773 : 16473 : time_module_state *state = get_time_state(module);
774 [ + + ]: 16473 : if (tup == NULL) {
775 : 1613 : time_t tt = time(NULL);
776 [ - + ]: 1613 : if (_PyTime_localtime(tt, &buf) != 0)
777 : 0 : return NULL;
778 : : }
779 [ + + ]: 14860 : else if (!gettmarg(state, tup, &buf,
780 [ + + ]: 14857 : "iiiiiiiii;strftime(): illegal time tuple argument") ||
781 : 14857 : !checktm(&buf))
782 : : {
783 : 16 : return NULL;
784 : : }
785 : :
786 : : #if defined(_MSC_VER) || (defined(__sun) && defined(__SVR4)) || defined(_AIX) || defined(__VXWORKS__)
787 : : if (buf.tm_year + 1900 < 1 || 9999 < buf.tm_year + 1900) {
788 : : PyErr_SetString(PyExc_ValueError,
789 : : "strftime() requires year in [1; 9999]");
790 : : return NULL;
791 : : }
792 : : #endif
793 : :
794 : : /* Normalize tm_isdst just in case someone foolishly implements %Z
795 : : based on the assumption that tm_isdst falls within the range of
796 : : [-1, 1] */
797 [ - + ]: 16457 : if (buf.tm_isdst < -1)
798 : 0 : buf.tm_isdst = -1;
799 [ - + ]: 16457 : else if (buf.tm_isdst > 1)
800 : 0 : buf.tm_isdst = 1;
801 : :
802 : : #ifdef HAVE_WCSFTIME
803 : 16457 : format = PyUnicode_AsWideCharString(format_arg, NULL);
804 [ + + ]: 16457 : if (format == NULL)
805 : 1 : return NULL;
806 : 16456 : fmt = format;
807 : : #else
808 : : /* Convert the unicode string to an ascii one */
809 : : format = PyUnicode_EncodeLocale(format_arg, "surrogateescape");
810 : : if (format == NULL)
811 : : return NULL;
812 : : fmt = PyBytes_AS_STRING(format);
813 : : #endif
814 : :
815 : : #if defined(MS_WINDOWS) && !defined(HAVE_WCSFTIME)
816 : : /* check that the format string contains only valid directives */
817 : : for (outbuf = strchr(fmt, '%');
818 : : outbuf != NULL;
819 : : outbuf = strchr(outbuf+2, '%'))
820 : : {
821 : : if (outbuf[1] == '#')
822 : : ++outbuf; /* not documented by python, */
823 : : if (outbuf[1] == '\0')
824 : : break;
825 : : if ((outbuf[1] == 'y') && buf.tm_year < 0) {
826 : : PyErr_SetString(PyExc_ValueError,
827 : : "format %y requires year >= 1900 on Windows");
828 : : Py_DECREF(format);
829 : : return NULL;
830 : : }
831 : : }
832 : : #elif (defined(_AIX) || (defined(__sun) && defined(__SVR4))) && defined(HAVE_WCSFTIME)
833 : : for (outbuf = wcschr(fmt, '%');
834 : : outbuf != NULL;
835 : : outbuf = wcschr(outbuf+2, '%'))
836 : : {
837 : : if (outbuf[1] == L'\0')
838 : : break;
839 : : /* Issue #19634: On AIX, wcsftime("y", (1899, 1, 1, 0, 0, 0, 0, 0, 0))
840 : : returns "0/" instead of "99" */
841 : : if (outbuf[1] == L'y' && buf.tm_year < 0) {
842 : : PyErr_SetString(PyExc_ValueError,
843 : : "format %y requires year >= 1900 on AIX");
844 : : PyMem_Free(format);
845 : : return NULL;
846 : : }
847 : : }
848 : : #endif
849 : :
850 : 16456 : fmtlen = time_strlen(fmt);
851 : :
852 : : /* I hate these functions that presume you know how big the output
853 : : * will be ahead of time...
854 : : */
855 : 16456 : for (i = 1024; ; i += i) {
856 : 16456 : outbuf = (time_char *)PyMem_Malloc(i*sizeof(time_char));
857 [ - + ]: 16456 : if (outbuf == NULL) {
858 : : PyErr_NoMemory();
859 : 0 : break;
860 : : }
861 : : #if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
862 : : errno = 0;
863 : : #endif
864 : : _Py_BEGIN_SUPPRESS_IPH
865 : 16456 : buflen = format_time(outbuf, i, fmt, &buf);
866 : : _Py_END_SUPPRESS_IPH
867 : : #if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
868 : : /* VisualStudio .NET 2005 does this properly */
869 : : if (buflen == 0 && errno == EINVAL) {
870 : : PyErr_SetString(PyExc_ValueError, "Invalid format string");
871 : : PyMem_Free(outbuf);
872 : : break;
873 : : }
874 : : #endif
875 [ + + + - ]: 16456 : if (buflen > 0 || i >= 256 * fmtlen) {
876 : : /* If the buffer is 256 times as long as the format,
877 : : it's probably not failing for lack of room!
878 : : More likely, the format yields an empty result,
879 : : e.g. an empty format, or %Z when the timezone
880 : : is unknown. */
881 : : #ifdef HAVE_WCSFTIME
882 : 16456 : ret = PyUnicode_FromWideChar(outbuf, buflen);
883 : : #else
884 : : ret = PyUnicode_DecodeLocaleAndSize(outbuf, buflen, "surrogateescape");
885 : : #endif
886 : 16456 : PyMem_Free(outbuf);
887 : 16456 : break;
888 : : }
889 : 0 : PyMem_Free(outbuf);
890 : : }
891 : : #ifdef HAVE_WCSFTIME
892 : 16456 : PyMem_Free(format);
893 : : #else
894 : : Py_DECREF(format);
895 : : #endif
896 : 16456 : return ret;
897 : : }
898 : :
899 : : #undef time_char
900 : : #undef format_time
901 : : PyDoc_STRVAR(strftime_doc,
902 : : "strftime(format[, tuple]) -> string\n\
903 : : \n\
904 : : Convert a time tuple to a string according to a format specification.\n\
905 : : See the library reference manual for formatting codes. When the time tuple\n\
906 : : is not present, current time as returned by localtime() is used.\n\
907 : : \n" STRFTIME_FORMAT_CODES);
908 : : #endif /* HAVE_STRFTIME */
909 : :
910 : : static PyObject *
911 : 145 : time_strptime(PyObject *self, PyObject *args)
912 : : {
913 : : PyObject *func, *result;
914 : :
915 : 145 : func = _PyImport_GetModuleAttrString("_strptime", "_strptime_time");
916 [ - + ]: 145 : if (!func) {
917 : 0 : return NULL;
918 : : }
919 : :
920 : 145 : result = PyObject_Call(func, args, NULL);
921 : 145 : Py_DECREF(func);
922 : 145 : return result;
923 : : }
924 : :
925 : :
926 : : PyDoc_STRVAR(strptime_doc,
927 : : "strptime(string, format) -> struct_time\n\
928 : : \n\
929 : : Parse a string to a time tuple according to a format specification.\n\
930 : : See the library reference manual for formatting codes (same as\n\
931 : : strftime()).\n\
932 : : \n" STRFTIME_FORMAT_CODES);
933 : :
934 : : static PyObject *
935 : 1218 : _asctime(struct tm *timeptr)
936 : : {
937 : : /* Inspired by Open Group reference implementation available at
938 : : * http://pubs.opengroup.org/onlinepubs/009695399/functions/asctime.html */
939 : : static const char wday_name[7][4] = {
940 : : "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
941 : : };
942 : : static const char mon_name[12][4] = {
943 : : "Jan", "Feb", "Mar", "Apr", "May", "Jun",
944 : : "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
945 : : };
946 : 2436 : return PyUnicode_FromFormat(
947 : : "%s %s%3d %.2d:%.2d:%.2d %d",
948 : 1218 : wday_name[timeptr->tm_wday],
949 : 1218 : mon_name[timeptr->tm_mon],
950 : : timeptr->tm_mday, timeptr->tm_hour,
951 : : timeptr->tm_min, timeptr->tm_sec,
952 : 1218 : 1900 + timeptr->tm_year);
953 : : }
954 : :
955 : : static PyObject *
956 : 994 : time_asctime(PyObject *module, PyObject *args)
957 : : {
958 : 994 : PyObject *tup = NULL;
959 : : struct tm buf;
960 : :
961 [ - + ]: 994 : if (!PyArg_UnpackTuple(args, "asctime", 0, 1, &tup))
962 : 0 : return NULL;
963 : :
964 : 994 : time_module_state *state = get_time_state(module);
965 [ - + ]: 994 : if (tup == NULL) {
966 : 0 : time_t tt = time(NULL);
967 [ # # ]: 0 : if (_PyTime_localtime(tt, &buf) != 0)
968 : 0 : return NULL;
969 : : }
970 [ + + ]: 994 : else if (!gettmarg(state, tup, &buf,
971 [ + + ]: 987 : "iiiiiiiii;asctime(): illegal time tuple argument") ||
972 : 987 : !checktm(&buf))
973 : : {
974 : 20 : return NULL;
975 : : }
976 : 974 : return _asctime(&buf);
977 : : }
978 : :
979 : : PyDoc_STRVAR(asctime_doc,
980 : : "asctime([tuple]) -> string\n\
981 : : \n\
982 : : Convert a time tuple to a string, e.g. 'Sat Jun 06 16:26:11 1998'.\n\
983 : : When the time tuple is not present, current time as returned by localtime()\n\
984 : : is used.");
985 : :
986 : : static PyObject *
987 : 248 : time_ctime(PyObject *self, PyObject *args)
988 : : {
989 : : time_t tt;
990 : : struct tm buf;
991 [ + + ]: 248 : if (!parse_time_t_args(args, "|O:ctime", &tt))
992 : 3 : return NULL;
993 [ + + ]: 245 : if (_PyTime_localtime(tt, &buf) != 0)
994 : 1 : return NULL;
995 : 244 : return _asctime(&buf);
996 : : }
997 : :
998 : : PyDoc_STRVAR(ctime_doc,
999 : : "ctime(seconds) -> string\n\
1000 : : \n\
1001 : : Convert a time in seconds since the Epoch to a string in local time.\n\
1002 : : This is equivalent to asctime(localtime(seconds)). When the time tuple is\n\
1003 : : not present, current time as returned by localtime() is used.");
1004 : :
1005 : : #ifdef HAVE_MKTIME
1006 : : static PyObject *
1007 : 311 : time_mktime(PyObject *module, PyObject *tm_tuple)
1008 : : {
1009 : : struct tm tm;
1010 : : time_t tt;
1011 : :
1012 : 311 : time_module_state *state = get_time_state(module);
1013 [ - + ]: 311 : if (!gettmarg(state, tm_tuple, &tm,
1014 : : "iiiiiiiii;mktime(): illegal time tuple argument"))
1015 : : {
1016 : 0 : return NULL;
1017 : : }
1018 : :
1019 : : #if defined(_AIX) || (defined(__VXWORKS__) && !defined(_WRS_CONFIG_LP64))
1020 : : /* bpo-19748: AIX mktime() valid range is 00:00:00 UTC, January 1, 1970
1021 : : to 03:14:07 UTC, January 19, 2038. Thanks to the workaround below,
1022 : : it is possible to support years in range [1902; 2037] */
1023 : : if (tm.tm_year < 2 || tm.tm_year > 137) {
1024 : : /* bpo-19748: On AIX, mktime() does not report overflow error
1025 : : for timestamp < -2^31 or timestamp > 2**31-1. VxWorks has the
1026 : : same issue when working in 32 bit mode. */
1027 : : PyErr_SetString(PyExc_OverflowError,
1028 : : "mktime argument out of range");
1029 : : return NULL;
1030 : : }
1031 : : #endif
1032 : :
1033 : : #ifdef _AIX
1034 : : /* bpo-34373: AIX mktime() has an integer overflow for years in range
1035 : : [1902; 1969]. Workaround the issue by using a year greater or equal than
1036 : : 1970 (tm_year >= 70): mktime() behaves correctly in that case
1037 : : (ex: properly report errors). tm_year and tm_wday are adjusted after
1038 : : mktime() call. */
1039 : : int orig_tm_year = tm.tm_year;
1040 : : int delta_days = 0;
1041 : : while (tm.tm_year < 70) {
1042 : : /* Use 4 years to account properly leap years */
1043 : : tm.tm_year += 4;
1044 : : delta_days -= (366 + (365 * 3));
1045 : : }
1046 : : #endif
1047 : :
1048 : 311 : tm.tm_wday = -1; /* sentinel; original value ignored */
1049 : 311 : tt = mktime(&tm);
1050 : :
1051 : : /* Return value of -1 does not necessarily mean an error, but tm_wday
1052 : : * cannot remain set to -1 if mktime succeeded. */
1053 [ + + ]: 311 : if (tt == (time_t)(-1)
1054 : : /* Return value of -1 does not necessarily mean an error, but
1055 : : * tm_wday cannot remain set to -1 if mktime succeeded. */
1056 [ - + ]: 1 : && tm.tm_wday == -1)
1057 : : {
1058 : 0 : PyErr_SetString(PyExc_OverflowError,
1059 : : "mktime argument out of range");
1060 : 0 : return NULL;
1061 : : }
1062 : :
1063 : : #ifdef _AIX
1064 : : if (delta_days != 0) {
1065 : : tm.tm_year = orig_tm_year;
1066 : : if (tm.tm_wday != -1) {
1067 : : tm.tm_wday = (tm.tm_wday + delta_days) % 7;
1068 : : }
1069 : : tt += delta_days * (24 * 3600);
1070 : : }
1071 : : #endif
1072 : :
1073 : 311 : return PyFloat_FromDouble((double)tt);
1074 : : }
1075 : :
1076 : : PyDoc_STRVAR(mktime_doc,
1077 : : "mktime(tuple) -> floating point number\n\
1078 : : \n\
1079 : : Convert a time tuple in local time to seconds since the Epoch.\n\
1080 : : Note that mktime(gmtime(0)) will not generally return zero for most\n\
1081 : : time zones; instead the returned value will either be equal to that\n\
1082 : : of the timezone or altzone attributes on the time module.");
1083 : : #endif /* HAVE_MKTIME */
1084 : :
1085 : : #ifdef HAVE_WORKING_TZSET
1086 : : static int init_timezone(PyObject *module);
1087 : :
1088 : : static PyObject *
1089 : 132 : time_tzset(PyObject *self, PyObject *unused)
1090 : : {
1091 : : PyObject* m;
1092 : :
1093 : 132 : m = PyImport_ImportModule("time");
1094 [ - + ]: 132 : if (m == NULL) {
1095 : 0 : return NULL;
1096 : : }
1097 : :
1098 : 132 : tzset();
1099 : :
1100 : : /* Reset timezone, altzone, daylight and tzname */
1101 [ - + ]: 132 : if (init_timezone(m) < 0) {
1102 : 0 : return NULL;
1103 : : }
1104 : 132 : Py_DECREF(m);
1105 [ - + ]: 132 : if (PyErr_Occurred())
1106 : 0 : return NULL;
1107 : :
1108 : 132 : Py_RETURN_NONE;
1109 : : }
1110 : :
1111 : : PyDoc_STRVAR(tzset_doc,
1112 : : "tzset()\n\
1113 : : \n\
1114 : : Initialize, or reinitialize, the local timezone to the value stored in\n\
1115 : : os.environ['TZ']. The TZ environment variable should be specified in\n\
1116 : : standard Unix timezone format as documented in the tzset man page\n\
1117 : : (eg. 'US/Eastern', 'Europe/Amsterdam'). Unknown timezones will silently\n\
1118 : : fall back to UTC. If the TZ environment variable is not set, the local\n\
1119 : : timezone is set to the systems best guess of wallclock time.\n\
1120 : : Changing the TZ environment variable without calling tzset *may* change\n\
1121 : : the local timezone used by methods such as localtime, but this behaviour\n\
1122 : : should not be relied on.");
1123 : : #endif /* HAVE_WORKING_TZSET */
1124 : :
1125 : :
1126 : : static int
1127 : 271730 : get_monotonic(_PyTime_t *t)
1128 : : {
1129 : : // Avoid _PyTime_GetMonotonicClock() which silently ignores errors.
1130 : 271730 : return _PyTime_GetMonotonicClockWithInfo(t, NULL);
1131 : : }
1132 : :
1133 : :
1134 : : static PyObject *
1135 : 206744 : time_monotonic(PyObject *self, PyObject *unused)
1136 : : {
1137 : : _PyTime_t t;
1138 [ - + ]: 206744 : if (get_monotonic(&t) < 0) {
1139 : 0 : return NULL;
1140 : : }
1141 : 206744 : return _PyFloat_FromPyTime(t);
1142 : : }
1143 : :
1144 : : PyDoc_STRVAR(monotonic_doc,
1145 : : "monotonic() -> float\n\
1146 : : \n\
1147 : : Monotonic clock, cannot go backward.");
1148 : :
1149 : : static PyObject *
1150 : 1 : time_monotonic_ns(PyObject *self, PyObject *unused)
1151 : : {
1152 : : _PyTime_t t;
1153 [ - + ]: 1 : if (get_monotonic(&t) < 0) {
1154 : 0 : return NULL;
1155 : : }
1156 : 1 : return _PyTime_AsNanosecondsObject(t);
1157 : : }
1158 : :
1159 : : PyDoc_STRVAR(monotonic_ns_doc,
1160 : : "monotonic_ns() -> int\n\
1161 : : \n\
1162 : : Monotonic clock, cannot go backward, as nanoseconds.");
1163 : :
1164 : :
1165 : : static int
1166 : 41269 : get_perf_counter(_PyTime_t *t)
1167 : : {
1168 : : // Avoid _PyTime_GetPerfCounter() which silently ignores errors.
1169 : 41269 : return _PyTime_GetPerfCounterWithInfo(t, NULL);
1170 : : }
1171 : :
1172 : :
1173 : : static PyObject *
1174 : 41268 : time_perf_counter(PyObject *self, PyObject *unused)
1175 : : {
1176 : : _PyTime_t t;
1177 [ - + ]: 41268 : if (get_perf_counter(&t) < 0) {
1178 : 0 : return NULL;
1179 : : }
1180 : 41268 : return _PyFloat_FromPyTime(t);
1181 : : }
1182 : :
1183 : : PyDoc_STRVAR(perf_counter_doc,
1184 : : "perf_counter() -> float\n\
1185 : : \n\
1186 : : Performance counter for benchmarking.");
1187 : :
1188 : :
1189 : : static PyObject *
1190 : 1 : time_perf_counter_ns(PyObject *self, PyObject *unused)
1191 : : {
1192 : : _PyTime_t t;
1193 [ - + ]: 1 : if (get_perf_counter(&t) < 0) {
1194 : 0 : return NULL;
1195 : : }
1196 : 1 : return _PyTime_AsNanosecondsObject(t);
1197 : : }
1198 : :
1199 : : PyDoc_STRVAR(perf_counter_ns_doc,
1200 : : "perf_counter_ns() -> int\n\
1201 : : \n\
1202 : : Performance counter for benchmarking as nanoseconds.");
1203 : :
1204 : : static int
1205 : 6516 : _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
1206 : : {
1207 : : #if defined(MS_WINDOWS)
1208 : : HANDLE process;
1209 : : FILETIME creation_time, exit_time, kernel_time, user_time;
1210 : : ULARGE_INTEGER large;
1211 : : _PyTime_t ktime, utime, t;
1212 : : BOOL ok;
1213 : :
1214 : : process = GetCurrentProcess();
1215 : : ok = GetProcessTimes(process, &creation_time, &exit_time,
1216 : : &kernel_time, &user_time);
1217 : : if (!ok) {
1218 : : PyErr_SetFromWindowsErr(0);
1219 : : return -1;
1220 : : }
1221 : :
1222 : : if (info) {
1223 : : info->implementation = "GetProcessTimes()";
1224 : : info->resolution = 1e-7;
1225 : : info->monotonic = 1;
1226 : : info->adjustable = 0;
1227 : : }
1228 : :
1229 : : large.u.LowPart = kernel_time.dwLowDateTime;
1230 : : large.u.HighPart = kernel_time.dwHighDateTime;
1231 : : ktime = large.QuadPart;
1232 : :
1233 : : large.u.LowPart = user_time.dwLowDateTime;
1234 : : large.u.HighPart = user_time.dwHighDateTime;
1235 : : utime = large.QuadPart;
1236 : :
1237 : : /* ktime and utime have a resolution of 100 nanoseconds */
1238 : : t = _PyTime_FromNanoseconds((ktime + utime) * 100);
1239 : : *tp = t;
1240 : : return 0;
1241 : : #else
1242 : :
1243 : : /* clock_gettime */
1244 : : #if defined(HAVE_CLOCK_GETTIME) \
1245 : : && (defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_PROF))
1246 : : struct timespec ts;
1247 : :
1248 : : if (HAVE_CLOCK_GETTIME_RUNTIME) {
1249 : :
1250 : : #ifdef CLOCK_PROF
1251 : : const clockid_t clk_id = CLOCK_PROF;
1252 : : const char *function = "clock_gettime(CLOCK_PROF)";
1253 : : #else
1254 : 6516 : const clockid_t clk_id = CLOCK_PROCESS_CPUTIME_ID;
1255 : 6516 : const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)";
1256 : : #endif
1257 : :
1258 [ + - ]: 6516 : if (clock_gettime(clk_id, &ts) == 0) {
1259 [ + + ]: 6516 : if (info) {
1260 : : struct timespec res;
1261 : 2 : info->implementation = function;
1262 : 2 : info->monotonic = 1;
1263 : 2 : info->adjustable = 0;
1264 [ - + ]: 2 : if (clock_getres(clk_id, &res)) {
1265 : 0 : PyErr_SetFromErrno(PyExc_OSError);
1266 : 0 : return -1;
1267 : : }
1268 : 2 : info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
1269 : : }
1270 : :
1271 [ - + ]: 6516 : if (_PyTime_FromTimespec(tp, &ts) < 0) {
1272 : 0 : return -1;
1273 : : }
1274 : 6516 : return 0;
1275 : : }
1276 : : }
1277 : : #endif
1278 : :
1279 : : /* getrusage(RUSAGE_SELF) */
1280 : : #if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRUSAGE)
1281 : : struct rusage ru;
1282 : :
1283 [ # # ]: 0 : if (getrusage(RUSAGE_SELF, &ru) == 0) {
1284 : : _PyTime_t utime, stime;
1285 : :
1286 [ # # ]: 0 : if (info) {
1287 : 0 : info->implementation = "getrusage(RUSAGE_SELF)";
1288 : 0 : info->monotonic = 1;
1289 : 0 : info->adjustable = 0;
1290 : 0 : info->resolution = 1e-6;
1291 : : }
1292 : :
1293 [ # # ]: 0 : if (_PyTime_FromTimeval(&utime, &ru.ru_utime) < 0) {
1294 : 0 : return -1;
1295 : : }
1296 [ # # ]: 0 : if (_PyTime_FromTimeval(&stime, &ru.ru_stime) < 0) {
1297 : 0 : return -1;
1298 : : }
1299 : :
1300 : 0 : _PyTime_t total = utime + stime;
1301 : 0 : *tp = total;
1302 : 0 : return 0;
1303 : : }
1304 : : #endif
1305 : :
1306 : : /* times() */
1307 : : #ifdef HAVE_TIMES
1308 : : struct tms t;
1309 : :
1310 [ # # ]: 0 : if (times(&t) != (clock_t)-1) {
1311 : : static long ticks_per_second = -1;
1312 : :
1313 [ # # ]: 0 : if (ticks_per_second == -1) {
1314 : : long freq;
1315 : : #if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
1316 : 0 : freq = sysconf(_SC_CLK_TCK);
1317 [ # # ]: 0 : if (freq < 1) {
1318 : 0 : freq = -1;
1319 : : }
1320 : : #elif defined(HZ)
1321 : : freq = HZ;
1322 : : #else
1323 : : freq = 60; /* magic fallback value; may be bogus */
1324 : : #endif
1325 : :
1326 [ # # ]: 0 : if (freq != -1) {
1327 : : /* check that _PyTime_MulDiv(t, SEC_TO_NS, ticks_per_second)
1328 : : cannot overflow below */
1329 : : #if LONG_MAX > _PyTime_MAX / SEC_TO_NS
1330 [ # # ]: 0 : if ((_PyTime_t)freq > _PyTime_MAX / SEC_TO_NS) {
1331 : 0 : PyErr_SetString(PyExc_OverflowError,
1332 : : "_SC_CLK_TCK is too large");
1333 : 0 : return -1;
1334 : : }
1335 : : #endif
1336 : :
1337 : 0 : ticks_per_second = freq;
1338 : : }
1339 : : }
1340 : :
1341 [ # # ]: 0 : if (ticks_per_second != -1) {
1342 [ # # ]: 0 : if (info) {
1343 : 0 : info->implementation = "times()";
1344 : 0 : info->monotonic = 1;
1345 : 0 : info->adjustable = 0;
1346 : 0 : info->resolution = 1.0 / (double)ticks_per_second;
1347 : : }
1348 : :
1349 : : _PyTime_t ns;
1350 : 0 : ns = _PyTime_MulDiv(t.tms_utime, SEC_TO_NS, ticks_per_second);
1351 : 0 : ns += _PyTime_MulDiv(t.tms_stime, SEC_TO_NS, ticks_per_second);
1352 : 0 : *tp = _PyTime_FromNanoseconds(ns);
1353 : 0 : return 0;
1354 : : }
1355 : : }
1356 : : #endif
1357 : :
1358 : : /* clock */
1359 : : /* Currently, Python 3 requires clock() to build: see issue #22624 */
1360 : 0 : return _PyTime_GetClockWithInfo(tp, info);
1361 : : #endif
1362 : : }
1363 : :
1364 : : static PyObject *
1365 : 6513 : time_process_time(PyObject *self, PyObject *unused)
1366 : : {
1367 : : _PyTime_t t;
1368 [ - + ]: 6513 : if (_PyTime_GetProcessTimeWithInfo(&t, NULL) < 0) {
1369 : 0 : return NULL;
1370 : : }
1371 : 6513 : return _PyFloat_FromPyTime(t);
1372 : : }
1373 : :
1374 : : PyDoc_STRVAR(process_time_doc,
1375 : : "process_time() -> float\n\
1376 : : \n\
1377 : : Process time for profiling: sum of the kernel and user-space CPU time.");
1378 : :
1379 : : static PyObject *
1380 : 1 : time_process_time_ns(PyObject *self, PyObject *unused)
1381 : : {
1382 : : _PyTime_t t;
1383 [ - + ]: 1 : if (_PyTime_GetProcessTimeWithInfo(&t, NULL) < 0) {
1384 : 0 : return NULL;
1385 : : }
1386 : 1 : return _PyTime_AsNanosecondsObject(t);
1387 : : }
1388 : :
1389 : : PyDoc_STRVAR(process_time_ns_doc,
1390 : : "process_time() -> int\n\
1391 : : \n\
1392 : : Process time for profiling as nanoseconds:\n\
1393 : : sum of the kernel and user-space CPU time.");
1394 : :
1395 : :
1396 : : #if defined(MS_WINDOWS)
1397 : : #define HAVE_THREAD_TIME
1398 : : static int
1399 : : _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
1400 : : {
1401 : : HANDLE thread;
1402 : : FILETIME creation_time, exit_time, kernel_time, user_time;
1403 : : ULARGE_INTEGER large;
1404 : : _PyTime_t ktime, utime, t;
1405 : : BOOL ok;
1406 : :
1407 : : thread = GetCurrentThread();
1408 : : ok = GetThreadTimes(thread, &creation_time, &exit_time,
1409 : : &kernel_time, &user_time);
1410 : : if (!ok) {
1411 : : PyErr_SetFromWindowsErr(0);
1412 : : return -1;
1413 : : }
1414 : :
1415 : : if (info) {
1416 : : info->implementation = "GetThreadTimes()";
1417 : : info->resolution = 1e-7;
1418 : : info->monotonic = 1;
1419 : : info->adjustable = 0;
1420 : : }
1421 : :
1422 : : large.u.LowPart = kernel_time.dwLowDateTime;
1423 : : large.u.HighPart = kernel_time.dwHighDateTime;
1424 : : ktime = large.QuadPart;
1425 : :
1426 : : large.u.LowPart = user_time.dwLowDateTime;
1427 : : large.u.HighPart = user_time.dwHighDateTime;
1428 : : utime = large.QuadPart;
1429 : :
1430 : : /* ktime and utime have a resolution of 100 nanoseconds */
1431 : : t = _PyTime_FromNanoseconds((ktime + utime) * 100);
1432 : : *tp = t;
1433 : : return 0;
1434 : : }
1435 : :
1436 : : #elif defined(_AIX)
1437 : : #define HAVE_THREAD_TIME
1438 : : static int
1439 : : _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
1440 : : {
1441 : : /* bpo-40192: On AIX, thread_cputime() is preferred: it has nanosecond
1442 : : resolution, whereas clock_gettime(CLOCK_THREAD_CPUTIME_ID)
1443 : : has a resolution of 10 ms. */
1444 : : thread_cputime_t tc;
1445 : : if (thread_cputime(-1, &tc) != 0) {
1446 : : PyErr_SetFromErrno(PyExc_OSError);
1447 : : return -1;
1448 : : }
1449 : :
1450 : : if (info) {
1451 : : info->implementation = "thread_cputime()";
1452 : : info->monotonic = 1;
1453 : : info->adjustable = 0;
1454 : : info->resolution = 1e-9;
1455 : : }
1456 : : *tp = _PyTime_FromNanoseconds(tc.stime + tc.utime);
1457 : : return 0;
1458 : : }
1459 : :
1460 : : #elif defined(__sun) && defined(__SVR4)
1461 : : #define HAVE_THREAD_TIME
1462 : : static int
1463 : : _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
1464 : : {
1465 : : /* bpo-35455: On Solaris, CLOCK_THREAD_CPUTIME_ID clock is not always
1466 : : available; use gethrvtime() to substitute this functionality. */
1467 : : if (info) {
1468 : : info->implementation = "gethrvtime()";
1469 : : info->resolution = 1e-9;
1470 : : info->monotonic = 1;
1471 : : info->adjustable = 0;
1472 : : }
1473 : : *tp = _PyTime_FromNanoseconds(gethrvtime());
1474 : : return 0;
1475 : : }
1476 : :
1477 : : #elif defined(HAVE_CLOCK_GETTIME) && \
1478 : : defined(CLOCK_PROCESS_CPUTIME_ID) && \
1479 : : !defined(__EMSCRIPTEN__) && !defined(__wasi__)
1480 : : #define HAVE_THREAD_TIME
1481 : :
1482 : : #if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability)
1483 : : static int
1484 : : _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
1485 : : __attribute__((availability(macos, introduced=10.12)))
1486 : : __attribute__((availability(ios, introduced=10.0)))
1487 : : __attribute__((availability(tvos, introduced=10.0)))
1488 : : __attribute__((availability(watchos, introduced=3.0)));
1489 : : #endif
1490 : :
1491 : : static int
1492 : 6 : _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
1493 : : {
1494 : : struct timespec ts;
1495 : 6 : const clockid_t clk_id = CLOCK_THREAD_CPUTIME_ID;
1496 : 6 : const char *function = "clock_gettime(CLOCK_THREAD_CPUTIME_ID)";
1497 : :
1498 [ - + ]: 6 : if (clock_gettime(clk_id, &ts)) {
1499 : 0 : PyErr_SetFromErrno(PyExc_OSError);
1500 : 0 : return -1;
1501 : : }
1502 [ + + ]: 6 : if (info) {
1503 : : struct timespec res;
1504 : 2 : info->implementation = function;
1505 : 2 : info->monotonic = 1;
1506 : 2 : info->adjustable = 0;
1507 [ - + ]: 2 : if (clock_getres(clk_id, &res)) {
1508 : 0 : PyErr_SetFromErrno(PyExc_OSError);
1509 : 0 : return -1;
1510 : : }
1511 : 2 : info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
1512 : : }
1513 : :
1514 [ - + ]: 6 : if (_PyTime_FromTimespec(tp, &ts) < 0) {
1515 : 0 : return -1;
1516 : : }
1517 : 6 : return 0;
1518 : : }
1519 : : #endif
1520 : :
1521 : : #ifdef HAVE_THREAD_TIME
1522 : : #ifdef __APPLE__
1523 : : /*
1524 : : * The clock_* functions will be removed from the module
1525 : : * dict entirely when the C API is not available.
1526 : : */
1527 : : #pragma clang diagnostic push
1528 : : #pragma clang diagnostic ignored "-Wunguarded-availability"
1529 : : #endif
1530 : :
1531 : : static PyObject *
1532 : 3 : time_thread_time(PyObject *self, PyObject *unused)
1533 : : {
1534 : : _PyTime_t t;
1535 [ - + ]: 3 : if (_PyTime_GetThreadTimeWithInfo(&t, NULL) < 0) {
1536 : 0 : return NULL;
1537 : : }
1538 : 3 : return _PyFloat_FromPyTime(t);
1539 : : }
1540 : :
1541 : : PyDoc_STRVAR(thread_time_doc,
1542 : : "thread_time() -> float\n\
1543 : : \n\
1544 : : Thread time for profiling: sum of the kernel and user-space CPU time.");
1545 : :
1546 : : static PyObject *
1547 : 1 : time_thread_time_ns(PyObject *self, PyObject *unused)
1548 : : {
1549 : : _PyTime_t t;
1550 [ - + ]: 1 : if (_PyTime_GetThreadTimeWithInfo(&t, NULL) < 0) {
1551 : 0 : return NULL;
1552 : : }
1553 : 1 : return _PyTime_AsNanosecondsObject(t);
1554 : : }
1555 : :
1556 : : PyDoc_STRVAR(thread_time_ns_doc,
1557 : : "thread_time() -> int\n\
1558 : : \n\
1559 : : Thread time for profiling as nanoseconds:\n\
1560 : : sum of the kernel and user-space CPU time.");
1561 : :
1562 : : #ifdef __APPLE__
1563 : : #pragma clang diagnostic pop
1564 : : #endif
1565 : :
1566 : : #endif
1567 : :
1568 : :
1569 : : static PyObject *
1570 : 3015 : time_get_clock_info(PyObject *self, PyObject *args)
1571 : : {
1572 : : char *name;
1573 : : _Py_clock_info_t info;
1574 : 3015 : PyObject *obj = NULL, *dict, *ns;
1575 : : _PyTime_t t;
1576 : :
1577 [ - + ]: 3015 : if (!PyArg_ParseTuple(args, "s:get_clock_info", &name)) {
1578 : 0 : return NULL;
1579 : : }
1580 : :
1581 : : #ifdef Py_DEBUG
1582 : : info.implementation = NULL;
1583 : : info.monotonic = -1;
1584 : : info.adjustable = -1;
1585 : : info.resolution = -1.0;
1586 : : #else
1587 : 3015 : info.implementation = "";
1588 : 3015 : info.monotonic = 0;
1589 : 3015 : info.adjustable = 0;
1590 : 3015 : info.resolution = 1.0;
1591 : : #endif
1592 : :
1593 [ + + ]: 3015 : if (strcmp(name, "time") == 0) {
1594 [ - + ]: 2 : if (_PyTime_GetSystemClockWithInfo(&t, &info) < 0) {
1595 : 0 : return NULL;
1596 : : }
1597 : : }
1598 [ + + ]: 3013 : else if (strcmp(name, "monotonic") == 0) {
1599 [ - + ]: 3007 : if (_PyTime_GetMonotonicClockWithInfo(&t, &info) < 0) {
1600 : 0 : return NULL;
1601 : : }
1602 : : }
1603 [ + + ]: 6 : else if (strcmp(name, "perf_counter") == 0) {
1604 [ - + ]: 1 : if (_PyTime_GetPerfCounterWithInfo(&t, &info) < 0) {
1605 : 0 : return NULL;
1606 : : }
1607 : : }
1608 [ + + ]: 5 : else if (strcmp(name, "process_time") == 0) {
1609 [ - + ]: 2 : if (_PyTime_GetProcessTimeWithInfo(&t, &info) < 0) {
1610 : 0 : return NULL;
1611 : : }
1612 : : }
1613 : : #ifdef HAVE_THREAD_TIME
1614 [ + + ]: 3 : else if (strcmp(name, "thread_time") == 0) {
1615 : :
1616 : : #ifdef __APPLE__
1617 : : if (HAVE_CLOCK_GETTIME_RUNTIME) {
1618 : : #endif
1619 [ - + ]: 2 : if (_PyTime_GetThreadTimeWithInfo(&t, &info) < 0) {
1620 : 0 : return NULL;
1621 : : }
1622 : : #ifdef __APPLE__
1623 : : } else {
1624 : : PyErr_SetString(PyExc_ValueError, "unknown clock");
1625 : : return NULL;
1626 : : }
1627 : : #endif
1628 : : }
1629 : : #endif
1630 : : else {
1631 : 1 : PyErr_SetString(PyExc_ValueError, "unknown clock");
1632 : 1 : return NULL;
1633 : : }
1634 : :
1635 : 3014 : dict = PyDict_New();
1636 [ - + ]: 3014 : if (dict == NULL) {
1637 : 0 : return NULL;
1638 : : }
1639 : :
1640 : : assert(info.implementation != NULL);
1641 : 3014 : obj = PyUnicode_FromString(info.implementation);
1642 [ - + ]: 3014 : if (obj == NULL) {
1643 : 0 : goto error;
1644 : : }
1645 [ - + ]: 3014 : if (PyDict_SetItemString(dict, "implementation", obj) == -1) {
1646 : 0 : goto error;
1647 : : }
1648 [ + - ]: 3014 : Py_CLEAR(obj);
1649 : :
1650 : : assert(info.monotonic != -1);
1651 : 3014 : obj = PyBool_FromLong(info.monotonic);
1652 [ - + ]: 3014 : if (obj == NULL) {
1653 : 0 : goto error;
1654 : : }
1655 [ - + ]: 3014 : if (PyDict_SetItemString(dict, "monotonic", obj) == -1) {
1656 : 0 : goto error;
1657 : : }
1658 [ + - ]: 3014 : Py_CLEAR(obj);
1659 : :
1660 : : assert(info.adjustable != -1);
1661 : 3014 : obj = PyBool_FromLong(info.adjustable);
1662 [ - + ]: 3014 : if (obj == NULL) {
1663 : 0 : goto error;
1664 : : }
1665 [ - + ]: 3014 : if (PyDict_SetItemString(dict, "adjustable", obj) == -1) {
1666 : 0 : goto error;
1667 : : }
1668 [ + - ]: 3014 : Py_CLEAR(obj);
1669 : :
1670 : : assert(info.resolution > 0.0);
1671 : : assert(info.resolution <= 1.0);
1672 : 3014 : obj = PyFloat_FromDouble(info.resolution);
1673 [ - + ]: 3014 : if (obj == NULL) {
1674 : 0 : goto error;
1675 : : }
1676 [ - + ]: 3014 : if (PyDict_SetItemString(dict, "resolution", obj) == -1) {
1677 : 0 : goto error;
1678 : : }
1679 [ + - ]: 3014 : Py_CLEAR(obj);
1680 : :
1681 : 3014 : ns = _PyNamespace_New(dict);
1682 : 3014 : Py_DECREF(dict);
1683 : 3014 : return ns;
1684 : :
1685 : 0 : error:
1686 : 0 : Py_DECREF(dict);
1687 : 0 : Py_XDECREF(obj);
1688 : 0 : return NULL;
1689 : : }
1690 : :
1691 : : PyDoc_STRVAR(get_clock_info_doc,
1692 : : "get_clock_info(name: str) -> dict\n\
1693 : : \n\
1694 : : Get information of the specified clock.");
1695 : :
1696 : : #ifndef HAVE_DECL_TZNAME
1697 : : static void
1698 : 6544 : get_zone(char *zone, int n, struct tm *p)
1699 : : {
1700 : : #ifdef HAVE_STRUCT_TM_TM_ZONE
1701 [ + - ]: 6544 : strncpy(zone, p->tm_zone ? p->tm_zone : " ", n);
1702 : : #else
1703 : : tzset();
1704 : : strftime(zone, n, "%Z", p);
1705 : : #endif
1706 : 6544 : }
1707 : :
1708 : : static time_t
1709 : 6544 : get_gmtoff(time_t t, struct tm *p)
1710 : : {
1711 : : #ifdef HAVE_STRUCT_TM_TM_ZONE
1712 : 6544 : return p->tm_gmtoff;
1713 : : #else
1714 : : return timegm(p) - t;
1715 : : #endif
1716 : : }
1717 : : #endif // !HAVE_DECL_TZNAME
1718 : :
1719 : : static int
1720 : 3272 : init_timezone(PyObject *m)
1721 : : {
1722 : : assert(!PyErr_Occurred());
1723 : :
1724 : : /* This code moved from PyInit_time wholesale to allow calling it from
1725 : : time_tzset. In the future, some parts of it can be moved back
1726 : : (for platforms that don't HAVE_WORKING_TZSET, when we know what they
1727 : : are), and the extraneous calls to tzset(3) should be removed.
1728 : : I haven't done this yet, as I don't want to change this code as
1729 : : little as possible when introducing the time.tzset and time.tzsetwall
1730 : : methods. This should simply be a method of doing the following once,
1731 : : at the top of this function and removing the call to tzset() from
1732 : : time_tzset():
1733 : :
1734 : : #ifdef HAVE_TZSET
1735 : : tzset()
1736 : : #endif
1737 : :
1738 : : And I'm lazy and hate C so nyer.
1739 : : */
1740 : : #ifdef HAVE_DECL_TZNAME
1741 : : PyObject *otz0, *otz1;
1742 : : tzset();
1743 : : PyModule_AddIntConstant(m, "timezone", _Py_timezone);
1744 : : #ifdef HAVE_ALTZONE
1745 : : PyModule_AddIntConstant(m, "altzone", altzone);
1746 : : #else
1747 : : PyModule_AddIntConstant(m, "altzone", _Py_timezone-3600);
1748 : : #endif
1749 : : PyModule_AddIntConstant(m, "daylight", _Py_daylight);
1750 : : #ifdef MS_WINDOWS
1751 : : TIME_ZONE_INFORMATION tzinfo = {0};
1752 : : GetTimeZoneInformation(&tzinfo);
1753 : : otz0 = PyUnicode_FromWideChar(tzinfo.StandardName, -1);
1754 : : if (otz0 == NULL) {
1755 : : return -1;
1756 : : }
1757 : : otz1 = PyUnicode_FromWideChar(tzinfo.DaylightName, -1);
1758 : : if (otz1 == NULL) {
1759 : : Py_DECREF(otz0);
1760 : : return -1;
1761 : : }
1762 : : #else
1763 : : otz0 = PyUnicode_DecodeLocale(_Py_tzname[0], "surrogateescape");
1764 : : if (otz0 == NULL) {
1765 : : return -1;
1766 : : }
1767 : : otz1 = PyUnicode_DecodeLocale(_Py_tzname[1], "surrogateescape");
1768 : : if (otz1 == NULL) {
1769 : : Py_DECREF(otz0);
1770 : : return -1;
1771 : : }
1772 : : #endif // MS_WINDOWS
1773 : : PyObject *tzname_obj = Py_BuildValue("(NN)", otz0, otz1);
1774 : : if (tzname_obj == NULL) {
1775 : : return -1;
1776 : : }
1777 : : PyModule_AddObject(m, "tzname", tzname_obj);
1778 : : #else // !HAVE_DECL_TZNAME
1779 : : static const time_t YEAR = (365 * 24 + 6) * 3600;
1780 : : time_t t;
1781 : : struct tm p;
1782 : : time_t janzone_t, julyzone_t;
1783 : : char janname[10], julyname[10];
1784 : 3272 : t = (time((time_t *)0) / YEAR) * YEAR;
1785 : 3272 : _PyTime_localtime(t, &p);
1786 : 3272 : get_zone(janname, 9, &p);
1787 : 3272 : janzone_t = -get_gmtoff(t, &p);
1788 : 3272 : janname[9] = '\0';
1789 : 3272 : t += YEAR/2;
1790 : 3272 : _PyTime_localtime(t, &p);
1791 : 3272 : get_zone(julyname, 9, &p);
1792 : 3272 : julyzone_t = -get_gmtoff(t, &p);
1793 : 3272 : julyname[9] = '\0';
1794 : :
1795 : : /* Sanity check, don't check for the validity of timezones.
1796 : : In practice, it should be more in range -12 hours .. +14 hours. */
1797 : : #define MAX_TIMEZONE (48 * 3600)
1798 [ + - + - ]: 3272 : if (janzone_t < -MAX_TIMEZONE || janzone_t > MAX_TIMEZONE
1799 [ + - - + ]: 3272 : || julyzone_t < -MAX_TIMEZONE || julyzone_t > MAX_TIMEZONE)
1800 : : {
1801 : 0 : PyErr_SetString(PyExc_RuntimeError, "invalid GMT offset");
1802 : 0 : return -1;
1803 : : }
1804 : 3272 : int janzone = (int)janzone_t;
1805 : 3272 : int julyzone = (int)julyzone_t;
1806 : :
1807 : : PyObject *tzname_obj;
1808 [ + + ]: 3272 : if (janzone < julyzone) {
1809 : : /* DST is reversed in the southern hemisphere */
1810 : 5 : PyModule_AddIntConstant(m, "timezone", julyzone);
1811 : 5 : PyModule_AddIntConstant(m, "altzone", janzone);
1812 : 5 : PyModule_AddIntConstant(m, "daylight", janzone != julyzone);
1813 : 5 : tzname_obj = Py_BuildValue("(zz)", julyname, janname);
1814 : : } else {
1815 : 3267 : PyModule_AddIntConstant(m, "timezone", janzone);
1816 : 3267 : PyModule_AddIntConstant(m, "altzone", julyzone);
1817 : 3267 : PyModule_AddIntConstant(m, "daylight", janzone != julyzone);
1818 : 3267 : tzname_obj = Py_BuildValue("(zz)", janname, julyname);
1819 : : }
1820 [ - + ]: 3272 : if (tzname_obj == NULL) {
1821 : 0 : return -1;
1822 : : }
1823 : 3272 : PyModule_AddObject(m, "tzname", tzname_obj);
1824 : : #endif // !HAVE_DECL_TZNAME
1825 : :
1826 [ - + ]: 3272 : if (PyErr_Occurred()) {
1827 : 0 : return -1;
1828 : : }
1829 : 3272 : return 0;
1830 : : }
1831 : :
1832 : :
1833 : : static PyMethodDef time_methods[] = {
1834 : : {"time", time_time, METH_NOARGS, time_doc},
1835 : : {"time_ns", time_time_ns, METH_NOARGS, time_ns_doc},
1836 : : #ifdef HAVE_CLOCK_GETTIME
1837 : : {"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc},
1838 : : {"clock_gettime_ns",time_clock_gettime_ns, METH_VARARGS, clock_gettime_ns_doc},
1839 : : #endif
1840 : : #ifdef HAVE_CLOCK_SETTIME
1841 : : {"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc},
1842 : : {"clock_settime_ns",time_clock_settime_ns, METH_VARARGS, clock_settime_ns_doc},
1843 : : #endif
1844 : : #ifdef HAVE_CLOCK_GETRES
1845 : : {"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc},
1846 : : #endif
1847 : : #ifdef HAVE_PTHREAD_GETCPUCLOCKID
1848 : : {"pthread_getcpuclockid", time_pthread_getcpuclockid, METH_VARARGS, pthread_getcpuclockid_doc},
1849 : : #endif
1850 : : {"sleep", time_sleep, METH_O, sleep_doc},
1851 : : {"gmtime", time_gmtime, METH_VARARGS, gmtime_doc},
1852 : : {"localtime", time_localtime, METH_VARARGS, localtime_doc},
1853 : : {"asctime", time_asctime, METH_VARARGS, asctime_doc},
1854 : : {"ctime", time_ctime, METH_VARARGS, ctime_doc},
1855 : : #ifdef HAVE_MKTIME
1856 : : {"mktime", time_mktime, METH_O, mktime_doc},
1857 : : #endif
1858 : : #ifdef HAVE_STRFTIME
1859 : : {"strftime", time_strftime, METH_VARARGS, strftime_doc},
1860 : : #endif
1861 : : {"strptime", time_strptime, METH_VARARGS, strptime_doc},
1862 : : #ifdef HAVE_WORKING_TZSET
1863 : : {"tzset", time_tzset, METH_NOARGS, tzset_doc},
1864 : : #endif
1865 : : {"monotonic", time_monotonic, METH_NOARGS, monotonic_doc},
1866 : : {"monotonic_ns", time_monotonic_ns, METH_NOARGS, monotonic_ns_doc},
1867 : : {"process_time", time_process_time, METH_NOARGS, process_time_doc},
1868 : : {"process_time_ns", time_process_time_ns, METH_NOARGS, process_time_ns_doc},
1869 : : #ifdef HAVE_THREAD_TIME
1870 : : {"thread_time", time_thread_time, METH_NOARGS, thread_time_doc},
1871 : : {"thread_time_ns", time_thread_time_ns, METH_NOARGS, thread_time_ns_doc},
1872 : : #endif
1873 : : {"perf_counter", time_perf_counter, METH_NOARGS, perf_counter_doc},
1874 : : {"perf_counter_ns", time_perf_counter_ns, METH_NOARGS, perf_counter_ns_doc},
1875 : : {"get_clock_info", time_get_clock_info, METH_VARARGS, get_clock_info_doc},
1876 : : {NULL, NULL} /* sentinel */
1877 : : };
1878 : :
1879 : :
1880 : : PyDoc_STRVAR(module_doc,
1881 : : "This module provides various functions to manipulate time values.\n\
1882 : : \n\
1883 : : There are two standard representations of time. One is the number\n\
1884 : : of seconds since the Epoch, in UTC (a.k.a. GMT). It may be an integer\n\
1885 : : or a floating point number (to represent fractions of seconds).\n\
1886 : : The Epoch is system-defined; on Unix, it is generally January 1st, 1970.\n\
1887 : : The actual value can be retrieved by calling gmtime(0).\n\
1888 : : \n\
1889 : : The other representation is a tuple of 9 integers giving local time.\n\
1890 : : The tuple items are:\n\
1891 : : year (including century, e.g. 1998)\n\
1892 : : month (1-12)\n\
1893 : : day (1-31)\n\
1894 : : hours (0-23)\n\
1895 : : minutes (0-59)\n\
1896 : : seconds (0-59)\n\
1897 : : weekday (0-6, Monday is 0)\n\
1898 : : Julian day (day in the year, 1-366)\n\
1899 : : DST (Daylight Savings Time) flag (-1, 0 or 1)\n\
1900 : : If the DST flag is 0, the time is given in the regular time zone;\n\
1901 : : if it is 1, the time is given in the DST time zone;\n\
1902 : : if it is -1, mktime() should guess based on the date and time.\n");
1903 : :
1904 : :
1905 : : static int
1906 : 3140 : time_exec(PyObject *module)
1907 : : {
1908 : 3140 : time_module_state *state = get_time_state(module);
1909 : : #if defined(__APPLE__) && defined(HAVE_CLOCK_GETTIME)
1910 : : if (HAVE_CLOCK_GETTIME_RUNTIME) {
1911 : : /* pass: ^^^ cannot use '!' here */
1912 : : } else {
1913 : : PyObject* dct = PyModule_GetDict(module);
1914 : : if (dct == NULL) {
1915 : : return -1;
1916 : : }
1917 : :
1918 : : if (PyDict_DelItemString(dct, "clock_gettime") == -1) {
1919 : : PyErr_Clear();
1920 : : }
1921 : : if (PyDict_DelItemString(dct, "clock_gettime_ns") == -1) {
1922 : : PyErr_Clear();
1923 : : }
1924 : : if (PyDict_DelItemString(dct, "clock_settime") == -1) {
1925 : : PyErr_Clear();
1926 : : }
1927 : : if (PyDict_DelItemString(dct, "clock_settime_ns") == -1) {
1928 : : PyErr_Clear();
1929 : : }
1930 : : if (PyDict_DelItemString(dct, "clock_getres") == -1) {
1931 : : PyErr_Clear();
1932 : : }
1933 : : }
1934 : : #endif
1935 : : #if defined(__APPLE__) && defined(HAVE_THREAD_TIME)
1936 : : if (HAVE_CLOCK_GETTIME_RUNTIME) {
1937 : : /* pass: ^^^ cannot use '!' here */
1938 : : } else {
1939 : : PyObject* dct = PyModule_GetDict(module);
1940 : :
1941 : : if (PyDict_DelItemString(dct, "thread_time") == -1) {
1942 : : PyErr_Clear();
1943 : : }
1944 : : if (PyDict_DelItemString(dct, "thread_time_ns") == -1) {
1945 : : PyErr_Clear();
1946 : : }
1947 : : }
1948 : : #endif
1949 : : /* Set, or reset, module variables like time.timezone */
1950 [ - + ]: 3140 : if (init_timezone(module) < 0) {
1951 : 0 : return -1;
1952 : : }
1953 : :
1954 : : #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES)
1955 : : if (HAVE_CLOCK_GETTIME_RUNTIME) {
1956 : :
1957 : : #ifdef CLOCK_REALTIME
1958 [ - + ]: 3140 : if (PyModule_AddIntMacro(module, CLOCK_REALTIME) < 0) {
1959 : 0 : return -1;
1960 : : }
1961 : : #endif
1962 : :
1963 : : #ifdef CLOCK_MONOTONIC
1964 : :
1965 [ - + ]: 3140 : if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC) < 0) {
1966 : 0 : return -1;
1967 : : }
1968 : :
1969 : : #endif
1970 : : #ifdef CLOCK_MONOTONIC_RAW
1971 [ - + ]: 3140 : if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC_RAW) < 0) {
1972 : 0 : return -1;
1973 : : }
1974 : : #endif
1975 : :
1976 : : #ifdef CLOCK_HIGHRES
1977 : : if (PyModule_AddIntMacro(module, CLOCK_HIGHRES) < 0) {
1978 : : return -1;
1979 : : }
1980 : : #endif
1981 : : #ifdef CLOCK_PROCESS_CPUTIME_ID
1982 [ - + ]: 3140 : if (PyModule_AddIntMacro(module, CLOCK_PROCESS_CPUTIME_ID) < 0) {
1983 : 0 : return -1;
1984 : : }
1985 : : #endif
1986 : :
1987 : : #ifdef CLOCK_THREAD_CPUTIME_ID
1988 [ - + ]: 3140 : if (PyModule_AddIntMacro(module, CLOCK_THREAD_CPUTIME_ID) < 0) {
1989 : 0 : return -1;
1990 : : }
1991 : : #endif
1992 : : #ifdef CLOCK_PROF
1993 : : if (PyModule_AddIntMacro(module, CLOCK_PROF) < 0) {
1994 : : return -1;
1995 : : }
1996 : : #endif
1997 : : #ifdef CLOCK_BOOTTIME
1998 [ - + ]: 3140 : if (PyModule_AddIntMacro(module, CLOCK_BOOTTIME) < 0) {
1999 : 0 : return -1;
2000 : : }
2001 : : #endif
2002 : : #ifdef CLOCK_TAI
2003 [ - + ]: 3140 : if (PyModule_AddIntMacro(module, CLOCK_TAI) < 0) {
2004 : 0 : return -1;
2005 : : }
2006 : : #endif
2007 : : #ifdef CLOCK_UPTIME
2008 : : if (PyModule_AddIntMacro(module, CLOCK_UPTIME) < 0) {
2009 : : return -1;
2010 : : }
2011 : : #endif
2012 : : #ifdef CLOCK_UPTIME_RAW
2013 : :
2014 : : if (PyModule_AddIntMacro(module, CLOCK_UPTIME_RAW) < 0) {
2015 : : return -1;
2016 : : }
2017 : : #endif
2018 : : }
2019 : :
2020 : : #endif /* defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES) */
2021 : :
2022 [ - + ]: 3140 : if (PyModule_AddIntConstant(module, "_STRUCT_TM_ITEMS", 11)) {
2023 : 0 : return -1;
2024 : : }
2025 : :
2026 : : // struct_time type
2027 : 3140 : state->struct_time_type = PyStructSequence_NewType(&struct_time_type_desc);
2028 [ - + ]: 3140 : if (state->struct_time_type == NULL) {
2029 : 0 : return -1;
2030 : : }
2031 [ - + ]: 3140 : if (PyModule_AddType(module, state->struct_time_type)) {
2032 : 0 : return -1;
2033 : : }
2034 : :
2035 : : #if defined(__linux__) && !defined(__GLIBC__)
2036 : : struct tm tm;
2037 : : const time_t zero = 0;
2038 : : if (gmtime_r(&zero, &tm) != NULL)
2039 : : utc_string = tm.tm_zone;
2040 : : #endif
2041 : :
2042 : : #if defined(MS_WINDOWS)
2043 : : if (timer_flags == (DWORD)-1) {
2044 : : DWORD test_flags = CREATE_WAITABLE_TIMER_HIGH_RESOLUTION;
2045 : : HANDLE timer = CreateWaitableTimerExW(NULL, NULL, test_flags,
2046 : : TIMER_ALL_ACCESS);
2047 : : if (timer == NULL) {
2048 : : // CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is not supported.
2049 : : timer_flags = 0;
2050 : : }
2051 : : else {
2052 : : // CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is supported.
2053 : : timer_flags = CREATE_WAITABLE_TIMER_HIGH_RESOLUTION;
2054 : : CloseHandle(timer);
2055 : : }
2056 : : }
2057 : : #endif
2058 : :
2059 : 3140 : return 0;
2060 : : }
2061 : :
2062 : :
2063 : : static int
2064 : 59810 : time_module_traverse(PyObject *module, visitproc visit, void *arg)
2065 : : {
2066 : 59810 : time_module_state *state = get_time_state(module);
2067 [ + - - + ]: 59810 : Py_VISIT(state->struct_time_type);
2068 : 59810 : return 0;
2069 : : }
2070 : :
2071 : :
2072 : : static int
2073 : 3749 : time_module_clear(PyObject *module)
2074 : : {
2075 : 3749 : time_module_state *state = get_time_state(module);
2076 [ + + ]: 3749 : Py_CLEAR(state->struct_time_type);
2077 : 3749 : return 0;
2078 : : }
2079 : :
2080 : :
2081 : : static void
2082 : 3080 : time_module_free(void *module)
2083 : : {
2084 : 3080 : time_module_clear((PyObject *)module);
2085 : 3080 : }
2086 : :
2087 : :
2088 : : static struct PyModuleDef_Slot time_slots[] = {
2089 : : {Py_mod_exec, time_exec},
2090 : : {0, NULL}
2091 : : };
2092 : :
2093 : : static struct PyModuleDef timemodule = {
2094 : : PyModuleDef_HEAD_INIT,
2095 : : .m_name = "time",
2096 : : .m_doc = module_doc,
2097 : : .m_size = sizeof(time_module_state),
2098 : : .m_methods = time_methods,
2099 : : .m_slots = time_slots,
2100 : : .m_traverse = time_module_traverse,
2101 : : .m_clear = time_module_clear,
2102 : : .m_free = time_module_free,
2103 : : };
2104 : :
2105 : : PyMODINIT_FUNC
2106 : 3140 : PyInit_time(void)
2107 : : {
2108 : 3140 : return PyModuleDef_Init(&timemodule);
2109 : : }
2110 : :
2111 : :
2112 : : // time.sleep() implementation.
2113 : : // On error, raise an exception and return -1.
2114 : : // On success, return 0.
2115 : : static int
2116 : 64985 : pysleep(_PyTime_t timeout)
2117 : : {
2118 : : assert(timeout >= 0);
2119 : :
2120 : : #ifndef MS_WINDOWS
2121 : : #ifdef HAVE_CLOCK_NANOSLEEP
2122 : : struct timespec timeout_abs;
2123 : : #elif defined(HAVE_NANOSLEEP)
2124 : : struct timespec timeout_ts;
2125 : : #else
2126 : : struct timeval timeout_tv;
2127 : : #endif
2128 : : _PyTime_t deadline, monotonic;
2129 : 64985 : int err = 0;
2130 : :
2131 [ - + ]: 64985 : if (get_monotonic(&monotonic) < 0) {
2132 : 0 : return -1;
2133 : : }
2134 : 64985 : deadline = monotonic + timeout;
2135 : : #ifdef HAVE_CLOCK_NANOSLEEP
2136 [ - + ]: 64985 : if (_PyTime_AsTimespec(deadline, &timeout_abs) < 0) {
2137 : 0 : return -1;
2138 : : }
2139 : : #endif
2140 : :
2141 : 8 : do {
2142 : : #ifdef HAVE_CLOCK_NANOSLEEP
2143 : : // use timeout_abs
2144 : : #elif defined(HAVE_NANOSLEEP)
2145 : : if (_PyTime_AsTimespec(timeout, &timeout_ts) < 0) {
2146 : : return -1;
2147 : : }
2148 : : #else
2149 : : if (_PyTime_AsTimeval(timeout, &timeout_tv, _PyTime_ROUND_CEILING) < 0) {
2150 : : return -1;
2151 : : }
2152 : : #endif
2153 : :
2154 : : int ret;
2155 : 64993 : Py_BEGIN_ALLOW_THREADS
2156 : : #ifdef HAVE_CLOCK_NANOSLEEP
2157 : 64993 : ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL);
2158 : 64982 : err = ret;
2159 : : #elif defined(HAVE_NANOSLEEP)
2160 : : ret = nanosleep(&timeout_ts, NULL);
2161 : : err = errno;
2162 : : #else
2163 : : ret = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout_tv);
2164 : : err = errno;
2165 : : #endif
2166 : 64982 : Py_END_ALLOW_THREADS
2167 : :
2168 [ + + ]: 64957 : if (ret == 0) {
2169 : 64949 : break;
2170 : : }
2171 : :
2172 [ - + ]: 8 : if (err != EINTR) {
2173 : 0 : errno = err;
2174 : 0 : PyErr_SetFromErrno(PyExc_OSError);
2175 : 0 : return -1;
2176 : : }
2177 : :
2178 : : /* sleep was interrupted by SIGINT */
2179 [ - + ]: 8 : if (PyErr_CheckSignals()) {
2180 : 0 : return -1;
2181 : : }
2182 : :
2183 : : #ifndef HAVE_CLOCK_NANOSLEEP
2184 : : if (get_monotonic(&monotonic) < 0) {
2185 : : return -1;
2186 : : }
2187 : : timeout = deadline - monotonic;
2188 : : if (timeout < 0) {
2189 : : break;
2190 : : }
2191 : : /* retry with the recomputed delay */
2192 : : #endif
2193 : : } while (1);
2194 : :
2195 : 64949 : return 0;
2196 : : #else // MS_WINDOWS
2197 : : _PyTime_t timeout_100ns = _PyTime_As100Nanoseconds(timeout,
2198 : : _PyTime_ROUND_CEILING);
2199 : :
2200 : : // Maintain Windows Sleep() semantics for time.sleep(0)
2201 : : if (timeout_100ns == 0) {
2202 : : Py_BEGIN_ALLOW_THREADS
2203 : : // A value of zero causes the thread to relinquish the remainder of its
2204 : : // time slice to any other thread that is ready to run. If there are no
2205 : : // other threads ready to run, the function returns immediately, and
2206 : : // the thread continues execution.
2207 : : Sleep(0);
2208 : : Py_END_ALLOW_THREADS
2209 : : return 0;
2210 : : }
2211 : :
2212 : : LARGE_INTEGER relative_timeout;
2213 : : // No need to check for integer overflow, both types are signed
2214 : : assert(sizeof(relative_timeout) == sizeof(timeout_100ns));
2215 : : // SetWaitableTimer(): a negative due time indicates relative time
2216 : : relative_timeout.QuadPart = -timeout_100ns;
2217 : :
2218 : : HANDLE timer = CreateWaitableTimerExW(NULL, NULL, timer_flags,
2219 : : TIMER_ALL_ACCESS);
2220 : : if (timer == NULL) {
2221 : : PyErr_SetFromWindowsErr(0);
2222 : : return -1;
2223 : : }
2224 : :
2225 : : if (!SetWaitableTimerEx(timer, &relative_timeout,
2226 : : 0, // no period; the timer is signaled once
2227 : : NULL, NULL, // no completion routine
2228 : : NULL, // no wake context; do not resume from suspend
2229 : : 0)) // no tolerable delay for timer coalescing
2230 : : {
2231 : : PyErr_SetFromWindowsErr(0);
2232 : : goto error;
2233 : : }
2234 : :
2235 : : // Only the main thread can be interrupted by SIGINT.
2236 : : // Signal handlers are only executed in the main thread.
2237 : : if (_PyOS_IsMainThread()) {
2238 : : HANDLE sigint_event = _PyOS_SigintEvent();
2239 : :
2240 : : while (1) {
2241 : : // Check for pending SIGINT signal before resetting the event
2242 : : if (PyErr_CheckSignals()) {
2243 : : goto error;
2244 : : }
2245 : : ResetEvent(sigint_event);
2246 : :
2247 : : HANDLE events[] = {timer, sigint_event};
2248 : : DWORD rc;
2249 : :
2250 : : Py_BEGIN_ALLOW_THREADS
2251 : : rc = WaitForMultipleObjects(Py_ARRAY_LENGTH(events), events,
2252 : : // bWaitAll
2253 : : FALSE,
2254 : : // No wait timeout
2255 : : INFINITE);
2256 : : Py_END_ALLOW_THREADS
2257 : :
2258 : : if (rc == WAIT_FAILED) {
2259 : : PyErr_SetFromWindowsErr(0);
2260 : : goto error;
2261 : : }
2262 : :
2263 : : if (rc == WAIT_OBJECT_0) {
2264 : : // Timer signaled: we are done
2265 : : break;
2266 : : }
2267 : :
2268 : : assert(rc == (WAIT_OBJECT_0 + 1));
2269 : : // The sleep was interrupted by SIGINT: restart sleeping
2270 : : }
2271 : : }
2272 : : else {
2273 : : DWORD rc;
2274 : :
2275 : : Py_BEGIN_ALLOW_THREADS
2276 : : rc = WaitForSingleObject(timer, INFINITE);
2277 : : Py_END_ALLOW_THREADS
2278 : :
2279 : : if (rc == WAIT_FAILED) {
2280 : : PyErr_SetFromWindowsErr(0);
2281 : : goto error;
2282 : : }
2283 : :
2284 : : assert(rc == WAIT_OBJECT_0);
2285 : : // Timer signaled: we are done
2286 : : }
2287 : :
2288 : : CloseHandle(timer);
2289 : : return 0;
2290 : :
2291 : : error:
2292 : : CloseHandle(timer);
2293 : : return -1;
2294 : : #endif
2295 : : }
|