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