LCOV - code coverage report
Current view: top level - Modules - timemodule.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 394 556 70.9 %
Date: 2022-07-07 18:19:46 Functions: 46 48 95.8 %

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

Generated by: LCOV version 1.14