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