LCOV - code coverage report
Current view: | top level - Modules - timemodule.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 112 | 556 | 20.1 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 19 | 51 | 37.3 %
|  |  | Branches: | 36 | 326 | 11.0 %

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

Generated by: LCOV version 1.14