1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377 |
- /* Time module */
- #include "Python.h"
- #include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
- #include "pycore_moduleobject.h" // _PyModule_GetState()
- #include "pycore_namespace.h" // _PyNamespace_New()
- #include "pycore_runtime.h" // _Py_ID()
- #include <ctype.h>
- #ifdef HAVE_SYS_TIMES_H
- # include <sys/times.h>
- #endif
- #ifdef HAVE_SYS_TYPES_H
- # include <sys/types.h>
- #endif
- #if defined(HAVE_SYS_RESOURCE_H)
- # include <sys/resource.h>
- #endif
- #ifdef QUICKWIN
- # include <io.h>
- #endif
- #if defined(HAVE_PTHREAD_H)
- # include <pthread.h>
- #endif
- #if defined(_AIX)
- # include <sys/thread.h>
- #endif
- #if defined(__WATCOMC__) && !defined(__QNX__)
- # include <i86.h>
- #else
- # ifdef MS_WINDOWS
- # ifndef WIN32_LEAN_AND_MEAN
- # define WIN32_LEAN_AND_MEAN
- # endif
- # include <windows.h>
- # endif /* MS_WINDOWS */
- #endif /* !__WATCOMC__ || __QNX__ */
- #ifdef _Py_MEMORY_SANITIZER
- # include <sanitizer/msan_interface.h>
- #endif
- #ifdef _MSC_VER
- # define _Py_timezone _timezone
- # define _Py_daylight _daylight
- # define _Py_tzname _tzname
- #else
- # define _Py_timezone timezone
- # define _Py_daylight daylight
- # define _Py_tzname tzname
- #endif
- #if defined(__APPLE__ ) && defined(__has_builtin)
- # if __has_builtin(__builtin_available)
- # define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
- # endif
- #endif
- #ifndef HAVE_CLOCK_GETTIME_RUNTIME
- # define HAVE_CLOCK_GETTIME_RUNTIME 1
- #endif
- #define SEC_TO_NS (1000 * 1000 * 1000)
- #if defined(HAVE_TIMES) || defined(HAVE_CLOCK)
- static int
- check_ticks_per_second(long tps, const char *context)
- {
- /* Effectively, check that _PyTime_MulDiv(t, SEC_TO_NS, ticks_per_second)
- cannot overflow. */
- if (tps >= 0 && (_PyTime_t)tps > _PyTime_MAX / SEC_TO_NS) {
- PyErr_Format(PyExc_OverflowError, "%s is too large", context);
- return -1;
- }
- return 0;
- }
- #endif /* HAVE_TIMES || HAVE_CLOCK */
- #ifdef HAVE_TIMES
- # define ticks_per_second _PyRuntime.time.ticks_per_second
- static void
- ensure_ticks_per_second(void)
- {
- if (_PyRuntime.time.ticks_per_second_initialized) {
- return;
- }
- _PyRuntime.time.ticks_per_second_initialized = 1;
- # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
- ticks_per_second = sysconf(_SC_CLK_TCK);
- if (ticks_per_second < 1) {
- ticks_per_second = -1;
- }
- # elif defined(HZ)
- ticks_per_second = HZ;
- # else
- ticks_per_second = 60; /* magic fallback value; may be bogus */
- # endif
- }
- #endif /* HAVE_TIMES */
- PyStatus
- _PyTime_Init(void)
- {
- #ifdef HAVE_TIMES
- ensure_ticks_per_second();
- #endif
- return PyStatus_Ok();
- }
- /* Forward declarations */
- static int pysleep(_PyTime_t timeout);
- typedef struct {
- PyTypeObject *struct_time_type;
- } time_module_state;
- static inline time_module_state*
- get_time_state(PyObject *module)
- {
- void *state = _PyModule_GetState(module);
- assert(state != NULL);
- return (time_module_state *)state;
- }
- static PyObject*
- _PyFloat_FromPyTime(_PyTime_t t)
- {
- double d = _PyTime_AsSecondsDouble(t);
- return PyFloat_FromDouble(d);
- }
- static int
- get_system_time(_PyTime_t *t)
- {
- // Avoid _PyTime_GetSystemClock() which silently ignores errors.
- return _PyTime_GetSystemClockWithInfo(t, NULL);
- }
- static PyObject *
- time_time(PyObject *self, PyObject *unused)
- {
- _PyTime_t t;
- if (get_system_time(&t) < 0) {
- return NULL;
- }
- return _PyFloat_FromPyTime(t);
- }
- PyDoc_STRVAR(time_doc,
- "time() -> floating-point number\n\
- \n\
- Return the current time in seconds since the Epoch.\n\
- Fractions of a second may be present if the system clock provides them.");
- static PyObject *
- time_time_ns(PyObject *self, PyObject *unused)
- {
- _PyTime_t t;
- if (get_system_time(&t) < 0) {
- return NULL;
- }
- return _PyTime_AsNanosecondsObject(t);
- }
- PyDoc_STRVAR(time_ns_doc,
- "time_ns() -> int\n\
- \n\
- Return the current time in nanoseconds since the Epoch.");
- #if defined(HAVE_CLOCK)
- #ifndef CLOCKS_PER_SEC
- # ifdef CLK_TCK
- # define CLOCKS_PER_SEC CLK_TCK
- # else
- # define CLOCKS_PER_SEC 1000000
- # endif
- #endif
- static int
- _PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
- {
- if (check_ticks_per_second(CLOCKS_PER_SEC, "CLOCKS_PER_SEC") < 0) {
- return -1;
- }
- if (info) {
- info->implementation = "clock()";
- info->resolution = 1.0 / (double)CLOCKS_PER_SEC;
- info->monotonic = 1;
- info->adjustable = 0;
- }
- clock_t ticks = clock();
- if (ticks == (clock_t)-1) {
- PyErr_SetString(PyExc_RuntimeError,
- "the processor time used is not available "
- "or its value cannot be represented");
- return -1;
- }
- _PyTime_t ns = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)CLOCKS_PER_SEC);
- *tp = _PyTime_FromNanoseconds(ns);
- return 0;
- }
- #endif /* HAVE_CLOCK */
- #ifdef HAVE_CLOCK_GETTIME
- #ifdef __APPLE__
- /*
- * The clock_* functions will be removed from the module
- * dict entirely when the C API is not available.
- */
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wunguarded-availability"
- #endif
- static PyObject *
- time_clock_gettime(PyObject *self, PyObject *args)
- {
- int ret;
- struct timespec tp;
- #if defined(_AIX) && (SIZEOF_LONG == 8)
- long clk_id;
- if (!PyArg_ParseTuple(args, "l:clock_gettime", &clk_id)) {
- #else
- int clk_id;
- if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) {
- #endif
- return NULL;
- }
- ret = clock_gettime((clockid_t)clk_id, &tp);
- if (ret != 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
- }
- return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
- }
- PyDoc_STRVAR(clock_gettime_doc,
- "clock_gettime(clk_id) -> float\n\
- \n\
- Return the time of the specified clock clk_id.");
- static PyObject *
- time_clock_gettime_ns(PyObject *self, PyObject *args)
- {
- int ret;
- int clk_id;
- struct timespec ts;
- _PyTime_t t;
- if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) {
- return NULL;
- }
- ret = clock_gettime((clockid_t)clk_id, &ts);
- if (ret != 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
- }
- if (_PyTime_FromTimespec(&t, &ts) < 0) {
- return NULL;
- }
- return _PyTime_AsNanosecondsObject(t);
- }
- PyDoc_STRVAR(clock_gettime_ns_doc,
- "clock_gettime_ns(clk_id) -> int\n\
- \n\
- Return the time of the specified clock clk_id as nanoseconds.");
- #endif /* HAVE_CLOCK_GETTIME */
- #ifdef HAVE_CLOCK_SETTIME
- static PyObject *
- time_clock_settime(PyObject *self, PyObject *args)
- {
- int clk_id;
- PyObject *obj;
- _PyTime_t t;
- struct timespec tp;
- int ret;
- if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj))
- return NULL;
- if (_PyTime_FromSecondsObject(&t, obj, _PyTime_ROUND_FLOOR) < 0)
- return NULL;
- if (_PyTime_AsTimespec(t, &tp) == -1)
- return NULL;
- ret = clock_settime((clockid_t)clk_id, &tp);
- if (ret != 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
- }
- Py_RETURN_NONE;
- }
- PyDoc_STRVAR(clock_settime_doc,
- "clock_settime(clk_id, time)\n\
- \n\
- Set the time of the specified clock clk_id.");
- static PyObject *
- time_clock_settime_ns(PyObject *self, PyObject *args)
- {
- int clk_id;
- PyObject *obj;
- _PyTime_t t;
- struct timespec ts;
- int ret;
- if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) {
- return NULL;
- }
- if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
- return NULL;
- }
- if (_PyTime_AsTimespec(t, &ts) == -1) {
- return NULL;
- }
- ret = clock_settime((clockid_t)clk_id, &ts);
- if (ret != 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
- }
- Py_RETURN_NONE;
- }
- PyDoc_STRVAR(clock_settime_ns_doc,
- "clock_settime_ns(clk_id, time)\n\
- \n\
- Set the time of the specified clock clk_id with nanoseconds.");
- #endif /* HAVE_CLOCK_SETTIME */
- #ifdef HAVE_CLOCK_GETRES
- static PyObject *
- time_clock_getres(PyObject *self, PyObject *args)
- {
- int ret;
- int clk_id;
- struct timespec tp;
- if (!PyArg_ParseTuple(args, "i:clock_getres", &clk_id))
- return NULL;
- ret = clock_getres((clockid_t)clk_id, &tp);
- if (ret != 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
- }
- return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
- }
- PyDoc_STRVAR(clock_getres_doc,
- "clock_getres(clk_id) -> floating-point number\n\
- \n\
- Return the resolution (precision) of the specified clock clk_id.");
- #ifdef __APPLE__
- #pragma clang diagnostic pop
- #endif
- #endif /* HAVE_CLOCK_GETRES */
- #ifdef HAVE_PTHREAD_GETCPUCLOCKID
- static PyObject *
- time_pthread_getcpuclockid(PyObject *self, PyObject *args)
- {
- unsigned long thread_id;
- int err;
- clockid_t clk_id;
- if (!PyArg_ParseTuple(args, "k:pthread_getcpuclockid", &thread_id)) {
- return NULL;
- }
- err = pthread_getcpuclockid((pthread_t)thread_id, &clk_id);
- if (err) {
- errno = err;
- PyErr_SetFromErrno(PyExc_OSError);
- return NULL;
- }
- #ifdef _Py_MEMORY_SANITIZER
- __msan_unpoison(&clk_id, sizeof(clk_id));
- #endif
- return PyLong_FromLong(clk_id);
- }
- PyDoc_STRVAR(pthread_getcpuclockid_doc,
- "pthread_getcpuclockid(thread_id) -> int\n\
- \n\
- Return the clk_id of a thread's CPU time clock.");
- #endif /* HAVE_PTHREAD_GETCPUCLOCKID */
- static PyObject *
- time_sleep(PyObject *self, PyObject *timeout_obj)
- {
- _PyTime_t timeout;
- if (_PyTime_FromSecondsObject(&timeout, timeout_obj, _PyTime_ROUND_TIMEOUT))
- return NULL;
- if (timeout < 0) {
- PyErr_SetString(PyExc_ValueError,
- "sleep length must be non-negative");
- return NULL;
- }
- if (pysleep(timeout) != 0) {
- return NULL;
- }
- Py_RETURN_NONE;
- }
- PyDoc_STRVAR(sleep_doc,
- "sleep(seconds)\n\
- \n\
- Delay execution for a given number of seconds. The argument may be\n\
- a floating-point number for subsecond precision.");
- static PyStructSequence_Field struct_time_type_fields[] = {
- {"tm_year", "year, for example, 1993"},
- {"tm_mon", "month of year, range [1, 12]"},
- {"tm_mday", "day of month, range [1, 31]"},
- {"tm_hour", "hours, range [0, 23]"},
- {"tm_min", "minutes, range [0, 59]"},
- {"tm_sec", "seconds, range [0, 61])"},
- {"tm_wday", "day of week, range [0, 6], Monday is 0"},
- {"tm_yday", "day of year, range [1, 366]"},
- {"tm_isdst", "1 if summer time is in effect, 0 if not, and -1 if unknown"},
- {"tm_zone", "abbreviation of timezone name"},
- {"tm_gmtoff", "offset from UTC in seconds"},
- {0}
- };
- static PyStructSequence_Desc struct_time_type_desc = {
- "time.struct_time",
- "The time value as returned by gmtime(), localtime(), and strptime(), and\n"
- " accepted by asctime(), mktime() and strftime(). May be considered as a\n"
- " sequence of 9 integers.\n\n"
- " Note that several fields' values are not the same as those defined by\n"
- " the C language standard for struct tm. For example, the value of the\n"
- " field tm_year is the actual year, not year - 1900. See individual\n"
- " fields' descriptions for details.",
- struct_time_type_fields,
- 9,
- };
- #if defined(MS_WINDOWS)
- #ifndef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
- #define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION 0x00000002
- #endif
- static DWORD timer_flags = (DWORD)-1;
- #endif
- static PyObject *
- tmtotuple(time_module_state *state, struct tm *p
- #ifndef HAVE_STRUCT_TM_TM_ZONE
- , const char *zone, time_t gmtoff
- #endif
- )
- {
- PyObject *v = PyStructSequence_New(state->struct_time_type);
- if (v == NULL)
- return NULL;
- #define SET_ITEM(INDEX, CALL) \
- do { \
- PyObject *obj = (CALL); \
- if (obj == NULL) { \
- Py_DECREF(v); \
- return NULL; \
- } \
- PyStructSequence_SET_ITEM(v, (INDEX), obj); \
- } while (0)
- #define SET(INDEX, VAL) \
- SET_ITEM((INDEX), PyLong_FromLong((long) (VAL)))
- SET(0, p->tm_year + 1900);
- SET(1, p->tm_mon + 1); /* Want January == 1 */
- SET(2, p->tm_mday);
- SET(3, p->tm_hour);
- SET(4, p->tm_min);
- SET(5, p->tm_sec);
- SET(6, (p->tm_wday + 6) % 7); /* Want Monday == 0 */
- SET(7, p->tm_yday + 1); /* Want January, 1 == 1 */
- SET(8, p->tm_isdst);
- #ifdef HAVE_STRUCT_TM_TM_ZONE
- SET_ITEM(9, PyUnicode_DecodeLocale(p->tm_zone, "surrogateescape"));
- SET(10, p->tm_gmtoff);
- #else
- SET_ITEM(9, PyUnicode_DecodeLocale(zone, "surrogateescape"));
- SET_ITEM(10, _PyLong_FromTime_t(gmtoff));
- #endif /* HAVE_STRUCT_TM_TM_ZONE */
- #undef SET
- #undef SET_ITEM
- return v;
- }
- /* Parse arg tuple that can contain an optional float-or-None value;
- format needs to be "|O:name".
- Returns non-zero on success (parallels PyArg_ParseTuple).
- */
- static int
- parse_time_t_args(PyObject *args, const char *format, time_t *pwhen)
- {
- PyObject *ot = NULL;
- time_t whent;
- if (!PyArg_ParseTuple(args, format, &ot))
- return 0;
- if (ot == NULL || ot == Py_None) {
- whent = time(NULL);
- }
- else {
- if (_PyTime_ObjectToTime_t(ot, &whent, _PyTime_ROUND_FLOOR) == -1)
- return 0;
- }
- *pwhen = whent;
- return 1;
- }
- static PyObject *
- time_gmtime(PyObject *module, PyObject *args)
- {
- time_t when;
- struct tm buf;
- if (!parse_time_t_args(args, "|O:gmtime", &when))
- return NULL;
- errno = 0;
- if (_PyTime_gmtime(when, &buf) != 0)
- return NULL;
- time_module_state *state = get_time_state(module);
- #ifdef HAVE_STRUCT_TM_TM_ZONE
- return tmtotuple(state, &buf);
- #else
- return tmtotuple(state, &buf, "UTC", 0);
- #endif
- }
- #ifndef HAVE_TIMEGM
- static time_t
- timegm(struct tm *p)
- {
- /* XXX: the following implementation will not work for tm_year < 1970.
- but it is likely that platforms that don't have timegm do not support
- negative timestamps anyways. */
- return p->tm_sec + p->tm_min*60 + p->tm_hour*3600 + p->tm_yday*86400 +
- (p->tm_year-70)*31536000 + ((p->tm_year-69)/4)*86400 -
- ((p->tm_year-1)/100)*86400 + ((p->tm_year+299)/400)*86400;
- }
- #endif
- PyDoc_STRVAR(gmtime_doc,
- "gmtime([seconds]) -> (tm_year, tm_mon, tm_mday, tm_hour, tm_min,\n\
- tm_sec, tm_wday, tm_yday, tm_isdst)\n\
- \n\
- Convert seconds since the Epoch to a time tuple expressing UTC (a.k.a.\n\
- GMT). When 'seconds' is not passed in, convert the current time instead.\n\
- \n\
- If the platform supports the tm_gmtoff and tm_zone, they are available as\n\
- attributes only.");
- static PyObject *
- time_localtime(PyObject *module, PyObject *args)
- {
- time_t when;
- struct tm buf;
- if (!parse_time_t_args(args, "|O:localtime", &when))
- return NULL;
- if (_PyTime_localtime(when, &buf) != 0)
- return NULL;
- time_module_state *state = get_time_state(module);
- #ifdef HAVE_STRUCT_TM_TM_ZONE
- return tmtotuple(state, &buf);
- #else
- {
- struct tm local = buf;
- char zone[100];
- time_t gmtoff;
- strftime(zone, sizeof(zone), "%Z", &buf);
- gmtoff = timegm(&buf) - when;
- return tmtotuple(state, &local, zone, gmtoff);
- }
- #endif
- }
- #if defined(__linux__) && !defined(__GLIBC__)
- static const char *utc_string = NULL;
- #endif
- PyDoc_STRVAR(localtime_doc,
- "localtime([seconds]) -> (tm_year,tm_mon,tm_mday,tm_hour,tm_min,\n\
- tm_sec,tm_wday,tm_yday,tm_isdst)\n\
- \n\
- Convert seconds since the Epoch to a time tuple expressing local time.\n\
- When 'seconds' is not passed in, convert the current time instead.");
- /* Convert 9-item tuple to tm structure. Return 1 on success, set
- * an exception and return 0 on error.
- */
- static int
- gettmarg(time_module_state *state, PyObject *args,
- struct tm *p, const char *format)
- {
- int y;
- memset((void *) p, '\0', sizeof(struct tm));
- if (!PyTuple_Check(args)) {
- PyErr_SetString(PyExc_TypeError,
- "Tuple or struct_time argument required");
- return 0;
- }
- if (!PyArg_ParseTuple(args, format,
- &y, &p->tm_mon, &p->tm_mday,
- &p->tm_hour, &p->tm_min, &p->tm_sec,
- &p->tm_wday, &p->tm_yday, &p->tm_isdst))
- return 0;
- if (y < INT_MIN + 1900) {
- PyErr_SetString(PyExc_OverflowError, "year out of range");
- return 0;
- }
- p->tm_year = y - 1900;
- p->tm_mon--;
- p->tm_wday = (p->tm_wday + 1) % 7;
- p->tm_yday--;
- #ifdef HAVE_STRUCT_TM_TM_ZONE
- if (Py_IS_TYPE(args, state->struct_time_type)) {
- PyObject *item;
- item = PyStructSequence_GET_ITEM(args, 9);
- if (item != Py_None) {
- p->tm_zone = (char *)PyUnicode_AsUTF8(item);
- if (p->tm_zone == NULL) {
- return 0;
- }
- #if defined(__linux__) && !defined(__GLIBC__)
- // Make an attempt to return the C library's own timezone strings to
- // it. musl refuses to process a tm_zone field unless it produced
- // it. See issue #34672.
- if (utc_string && strcmp(p->tm_zone, utc_string) == 0) {
- p->tm_zone = utc_string;
- }
- else if (tzname[0] && strcmp(p->tm_zone, tzname[0]) == 0) {
- p->tm_zone = tzname[0];
- }
- else if (tzname[1] && strcmp(p->tm_zone, tzname[1]) == 0) {
- p->tm_zone = tzname[1];
- }
- #endif
- }
- item = PyStructSequence_GET_ITEM(args, 10);
- if (item != Py_None) {
- p->tm_gmtoff = PyLong_AsLong(item);
- if (PyErr_Occurred())
- return 0;
- }
- }
- #endif /* HAVE_STRUCT_TM_TM_ZONE */
- return 1;
- }
- /* Check values of the struct tm fields before it is passed to strftime() and
- * asctime(). Return 1 if all values are valid, otherwise set an exception
- * and returns 0.
- */
- static int
- checktm(struct tm* buf)
- {
- /* Checks added to make sure strftime() and asctime() does not crash Python by
- indexing blindly into some array for a textual representation
- by some bad index (fixes bug #897625 and #6608).
- Also support values of zero from Python code for arguments in which
- that is out of range by forcing that value to the lowest value that
- is valid (fixed bug #1520914).
- Valid ranges based on what is allowed in struct tm:
- - tm_year: [0, max(int)] (1)
- - tm_mon: [0, 11] (2)
- - tm_mday: [1, 31]
- - tm_hour: [0, 23]
- - tm_min: [0, 59]
- - tm_sec: [0, 60]
- - tm_wday: [0, 6] (1)
- - tm_yday: [0, 365] (2)
- - tm_isdst: [-max(int), max(int)]
- (1) gettmarg() handles bounds-checking.
- (2) Python's acceptable range is one greater than the range in C,
- thus need to check against automatic decrement by gettmarg().
- */
- if (buf->tm_mon == -1)
- buf->tm_mon = 0;
- else if (buf->tm_mon < 0 || buf->tm_mon > 11) {
- PyErr_SetString(PyExc_ValueError, "month out of range");
- return 0;
- }
- if (buf->tm_mday == 0)
- buf->tm_mday = 1;
- else if (buf->tm_mday < 0 || buf->tm_mday > 31) {
- PyErr_SetString(PyExc_ValueError, "day of month out of range");
- return 0;
- }
- if (buf->tm_hour < 0 || buf->tm_hour > 23) {
- PyErr_SetString(PyExc_ValueError, "hour out of range");
- return 0;
- }
- if (buf->tm_min < 0 || buf->tm_min > 59) {
- PyErr_SetString(PyExc_ValueError, "minute out of range");
- return 0;
- }
- if (buf->tm_sec < 0 || buf->tm_sec > 61) {
- PyErr_SetString(PyExc_ValueError, "seconds out of range");
- return 0;
- }
- /* tm_wday does not need checking of its upper-bound since taking
- ``% 7`` in gettmarg() automatically restricts the range. */
- if (buf->tm_wday < 0) {
- PyErr_SetString(PyExc_ValueError, "day of week out of range");
- return 0;
- }
- if (buf->tm_yday == -1)
- buf->tm_yday = 0;
- else if (buf->tm_yday < 0 || buf->tm_yday > 365) {
- PyErr_SetString(PyExc_ValueError, "day of year out of range");
- return 0;
- }
- return 1;
- }
- #ifdef MS_WINDOWS
- /* wcsftime() doesn't format correctly time zones, see issue #10653 */
- # undef HAVE_WCSFTIME
- #endif
- #define STRFTIME_FORMAT_CODES \
- "Commonly used format codes:\n\
- \n\
- %Y Year with century as a decimal number.\n\
- %m Month as a decimal number [01,12].\n\
- %d Day of the month as a decimal number [01,31].\n\
- %H Hour (24-hour clock) as a decimal number [00,23].\n\
- %M Minute as a decimal number [00,59].\n\
- %S Second as a decimal number [00,61].\n\
- %z Time zone offset from UTC.\n\
- %a Locale's abbreviated weekday name.\n\
- %A Locale's full weekday name.\n\
- %b Locale's abbreviated month name.\n\
- %B Locale's full month name.\n\
- %c Locale's appropriate date and time representation.\n\
- %I Hour (12-hour clock) as a decimal number [01,12].\n\
- %p Locale's equivalent of either AM or PM.\n\
- \n\
- Other codes may be available on your platform. See documentation for\n\
- the C library strftime function.\n"
- #ifdef HAVE_STRFTIME
- #ifdef HAVE_WCSFTIME
- #define time_char wchar_t
- #define format_time wcsftime
- #define time_strlen wcslen
- #else
- #define time_char char
- #define format_time strftime
- #define time_strlen strlen
- #endif
- static PyObject *
- time_strftime1(time_char **outbuf, size_t *bufsize,
- time_char *format, size_t fmtlen,
- struct tm *tm)
- {
- size_t buflen;
- #if defined(MS_WINDOWS) && !defined(HAVE_WCSFTIME)
- /* check that the format string contains only valid directives */
- for (const time_char *f = strchr(format, '%');
- f != NULL;
- f = strchr(f + 2, '%'))
- {
- if (f[1] == '#')
- ++f; /* not documented by python, */
- if (f[1] == '\0')
- break;
- if ((f[1] == 'y') && tm->tm_year < 0) {
- PyErr_SetString(PyExc_ValueError,
- "format %y requires year >= 1900 on Windows");
- return NULL;
- }
- }
- #elif (defined(_AIX) || (defined(__sun) && defined(__SVR4))) && defined(HAVE_WCSFTIME)
- for (const time_char *f = wcschr(format, '%');
- f != NULL;
- f = wcschr(f + 2, '%'))
- {
- if (f[1] == L'\0')
- break;
- /* Issue #19634: On AIX, wcsftime("y", (1899, 1, 1, 0, 0, 0, 0, 0, 0))
- returns "0/" instead of "99" */
- if (f[1] == L'y' && tm->tm_year < 0) {
- PyErr_SetString(PyExc_ValueError,
- "format %y requires year >= 1900 on AIX");
- return NULL;
- }
- }
- #endif
- /* I hate these functions that presume you know how big the output
- * will be ahead of time...
- */
- while (1) {
- if (*bufsize > PY_SSIZE_T_MAX/sizeof(time_char)) {
- PyErr_NoMemory();
- return NULL;
- }
- *outbuf = (time_char *)PyMem_Realloc(*outbuf,
- *bufsize*sizeof(time_char));
- if (*outbuf == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- #if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
- errno = 0;
- #endif
- _Py_BEGIN_SUPPRESS_IPH
- buflen = format_time(*outbuf, *bufsize, format, tm);
- _Py_END_SUPPRESS_IPH
- #if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
- /* VisualStudio .NET 2005 does this properly */
- if (buflen == 0 && errno == EINVAL) {
- PyErr_SetString(PyExc_ValueError, "Invalid format string");
- return NULL;
- }
- #endif
- if (buflen == 0 && *bufsize < 256 * fmtlen) {
- *bufsize += *bufsize;
- continue;
- }
- /* If the buffer is 256 times as long as the format,
- it's probably not failing for lack of room!
- More likely, the format yields an empty result,
- e.g. an empty format, or %Z when the timezone
- is unknown. */
- #ifdef HAVE_WCSFTIME
- return PyUnicode_FromWideChar(*outbuf, buflen);
- #else
- return PyUnicode_DecodeLocaleAndSize(*outbuf, buflen, "surrogateescape");
- #endif
- }
- }
- static PyObject *
- time_strftime(PyObject *module, PyObject *args)
- {
- PyObject *tup = NULL;
- struct tm buf;
- PyObject *format_arg;
- Py_ssize_t format_size;
- time_char *format, *outbuf = NULL;
- size_t fmtlen, bufsize = 1024;
- memset((void *) &buf, '\0', sizeof(buf));
- if (!PyArg_ParseTuple(args, "U|O:strftime", &format_arg, &tup))
- return NULL;
- time_module_state *state = get_time_state(module);
- if (tup == NULL) {
- time_t tt = time(NULL);
- if (_PyTime_localtime(tt, &buf) != 0)
- return NULL;
- }
- else if (!gettmarg(state, tup, &buf,
- "iiiiiiiii;strftime(): illegal time tuple argument") ||
- !checktm(&buf))
- {
- return NULL;
- }
- #if defined(_MSC_VER) || (defined(__sun) && defined(__SVR4)) || defined(_AIX) || defined(__VXWORKS__)
- if (buf.tm_year + 1900 < 1 || 9999 < buf.tm_year + 1900) {
- PyErr_SetString(PyExc_ValueError,
- "strftime() requires year in [1; 9999]");
- return NULL;
- }
- #endif
- /* Normalize tm_isdst just in case someone foolishly implements %Z
- based on the assumption that tm_isdst falls within the range of
- [-1, 1] */
- if (buf.tm_isdst < -1)
- buf.tm_isdst = -1;
- else if (buf.tm_isdst > 1)
- buf.tm_isdst = 1;
- format_size = PyUnicode_GET_LENGTH(format_arg);
- if ((size_t)format_size > PY_SSIZE_T_MAX/sizeof(time_char) - 1) {
- PyErr_NoMemory();
- return NULL;
- }
- format = PyMem_Malloc((format_size + 1)*sizeof(time_char));
- if (format == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- _PyUnicodeWriter writer;
- _PyUnicodeWriter_Init(&writer);
- writer.overallocate = 1;
- Py_ssize_t i = 0;
- while (i < format_size) {
- fmtlen = 0;
- for (; i < format_size; i++) {
- Py_UCS4 c = PyUnicode_READ_CHAR(format_arg, i);
- if (!c || c > 127) {
- break;
- }
- format[fmtlen++] = (char)c;
- }
- if (fmtlen) {
- format[fmtlen] = 0;
- PyObject *unicode = time_strftime1(&outbuf, &bufsize,
- format, fmtlen, &buf);
- if (unicode == NULL) {
- goto error;
- }
- if (_PyUnicodeWriter_WriteStr(&writer, unicode) < 0) {
- Py_DECREF(unicode);
- goto error;
- }
- Py_DECREF(unicode);
- }
- Py_ssize_t start = i;
- for (; i < format_size; i++) {
- Py_UCS4 c = PyUnicode_READ_CHAR(format_arg, i);
- if (c == '%') {
- break;
- }
- }
- if (start < i) {
- if (_PyUnicodeWriter_WriteSubstring(&writer, format_arg, start, i) < 0) {
- goto error;
- }
- }
- }
- PyMem_Free(outbuf);
- PyMem_Free(format);
- return _PyUnicodeWriter_Finish(&writer);
- error:
- PyMem_Free(outbuf);
- PyMem_Free(format);
- _PyUnicodeWriter_Dealloc(&writer);
- return NULL;
- }
- #undef time_char
- #undef format_time
- PyDoc_STRVAR(strftime_doc,
- "strftime(format[, tuple]) -> string\n\
- \n\
- Convert a time tuple to a string according to a format specification.\n\
- See the library reference manual for formatting codes. When the time tuple\n\
- is not present, current time as returned by localtime() is used.\n\
- \n" STRFTIME_FORMAT_CODES);
- #endif /* HAVE_STRFTIME */
- static PyObject *
- time_strptime(PyObject *self, PyObject *args)
- {
- PyObject *func, *result;
- func = _PyImport_GetModuleAttrString("_strptime", "_strptime_time");
- if (!func) {
- return NULL;
- }
- result = PyObject_Call(func, args, NULL);
- Py_DECREF(func);
- return result;
- }
- PyDoc_STRVAR(strptime_doc,
- "strptime(string, format) -> struct_time\n\
- \n\
- Parse a string to a time tuple according to a format specification.\n\
- See the library reference manual for formatting codes (same as\n\
- strftime()).\n\
- \n" STRFTIME_FORMAT_CODES);
- static PyObject *
- _asctime(struct tm *timeptr)
- {
- /* Inspired by Open Group reference implementation available at
- * http://pubs.opengroup.org/onlinepubs/009695399/functions/asctime.html */
- static const char wday_name[7][4] = {
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- };
- static const char mon_name[12][4] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
- return PyUnicode_FromFormat(
- "%s %s%3d %.2d:%.2d:%.2d %d",
- wday_name[timeptr->tm_wday],
- mon_name[timeptr->tm_mon],
- timeptr->tm_mday, timeptr->tm_hour,
- timeptr->tm_min, timeptr->tm_sec,
- 1900 + timeptr->tm_year);
- }
- static PyObject *
- time_asctime(PyObject *module, PyObject *args)
- {
- PyObject *tup = NULL;
- struct tm buf;
- if (!PyArg_UnpackTuple(args, "asctime", 0, 1, &tup))
- return NULL;
- time_module_state *state = get_time_state(module);
- if (tup == NULL) {
- time_t tt = time(NULL);
- if (_PyTime_localtime(tt, &buf) != 0)
- return NULL;
- }
- else if (!gettmarg(state, tup, &buf,
- "iiiiiiiii;asctime(): illegal time tuple argument") ||
- !checktm(&buf))
- {
- return NULL;
- }
- return _asctime(&buf);
- }
- PyDoc_STRVAR(asctime_doc,
- "asctime([tuple]) -> string\n\
- \n\
- Convert a time tuple to a string, e.g. 'Sat Jun 06 16:26:11 1998'.\n\
- When the time tuple is not present, current time as returned by localtime()\n\
- is used.");
- static PyObject *
- time_ctime(PyObject *self, PyObject *args)
- {
- time_t tt;
- struct tm buf;
- if (!parse_time_t_args(args, "|O:ctime", &tt))
- return NULL;
- if (_PyTime_localtime(tt, &buf) != 0)
- return NULL;
- return _asctime(&buf);
- }
- PyDoc_STRVAR(ctime_doc,
- "ctime(seconds) -> string\n\
- \n\
- Convert a time in seconds since the Epoch to a string in local time.\n\
- This is equivalent to asctime(localtime(seconds)). When the time tuple is\n\
- not present, current time as returned by localtime() is used.");
- #ifdef HAVE_MKTIME
- static PyObject *
- time_mktime(PyObject *module, PyObject *tm_tuple)
- {
- struct tm tm;
- time_t tt;
- time_module_state *state = get_time_state(module);
- if (!gettmarg(state, tm_tuple, &tm,
- "iiiiiiiii;mktime(): illegal time tuple argument"))
- {
- return NULL;
- }
- #if defined(_AIX) || (defined(__VXWORKS__) && !defined(_WRS_CONFIG_LP64))
- /* bpo-19748: AIX mktime() valid range is 00:00:00 UTC, January 1, 1970
- to 03:14:07 UTC, January 19, 2038. Thanks to the workaround below,
- it is possible to support years in range [1902; 2037] */
- if (tm.tm_year < 2 || tm.tm_year > 137) {
- /* bpo-19748: On AIX, mktime() does not report overflow error
- for timestamp < -2^31 or timestamp > 2**31-1. VxWorks has the
- same issue when working in 32 bit mode. */
- PyErr_SetString(PyExc_OverflowError,
- "mktime argument out of range");
- return NULL;
- }
- #endif
- #ifdef _AIX
- /* bpo-34373: AIX mktime() has an integer overflow for years in range
- [1902; 1969]. Workaround the issue by using a year greater or equal than
- 1970 (tm_year >= 70): mktime() behaves correctly in that case
- (ex: properly report errors). tm_year and tm_wday are adjusted after
- mktime() call. */
- int orig_tm_year = tm.tm_year;
- int delta_days = 0;
- while (tm.tm_year < 70) {
- /* Use 4 years to account properly leap years */
- tm.tm_year += 4;
- delta_days -= (366 + (365 * 3));
- }
- #endif
- tm.tm_wday = -1; /* sentinel; original value ignored */
- tt = mktime(&tm);
- /* Return value of -1 does not necessarily mean an error, but tm_wday
- * cannot remain set to -1 if mktime succeeded. */
- if (tt == (time_t)(-1)
- /* Return value of -1 does not necessarily mean an error, but
- * tm_wday cannot remain set to -1 if mktime succeeded. */
- && tm.tm_wday == -1)
- {
- PyErr_SetString(PyExc_OverflowError,
- "mktime argument out of range");
- return NULL;
- }
- #ifdef _AIX
- if (delta_days != 0) {
- tm.tm_year = orig_tm_year;
- if (tm.tm_wday != -1) {
- tm.tm_wday = (tm.tm_wday + delta_days) % 7;
- }
- tt += delta_days * (24 * 3600);
- }
- #endif
- return PyFloat_FromDouble((double)tt);
- }
- PyDoc_STRVAR(mktime_doc,
- "mktime(tuple) -> floating-point number\n\
- \n\
- Convert a time tuple in local time to seconds since the Epoch.\n\
- Note that mktime(gmtime(0)) will not generally return zero for most\n\
- time zones; instead the returned value will either be equal to that\n\
- of the timezone or altzone attributes on the time module.");
- #endif /* HAVE_MKTIME */
- #ifdef HAVE_WORKING_TZSET
- static int init_timezone(PyObject *module);
- static PyObject *
- time_tzset(PyObject *self, PyObject *unused)
- {
- PyObject* m;
- m = PyImport_ImportModule("time");
- if (m == NULL) {
- return NULL;
- }
- #if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
- tzset();
- #endif
- /* Reset timezone, altzone, daylight and tzname */
- if (init_timezone(m) < 0) {
- return NULL;
- }
- Py_DECREF(m);
- if (PyErr_Occurred())
- return NULL;
- Py_RETURN_NONE;
- }
- PyDoc_STRVAR(tzset_doc,
- "tzset()\n\
- \n\
- Initialize, or reinitialize, the local timezone to the value stored in\n\
- os.environ['TZ']. The TZ environment variable should be specified in\n\
- standard Unix timezone format as documented in the tzset man page\n\
- (eg. 'US/Eastern', 'Europe/Amsterdam'). Unknown timezones will silently\n\
- fall back to UTC. If the TZ environment variable is not set, the local\n\
- timezone is set to the systems best guess of wallclock time.\n\
- Changing the TZ environment variable without calling tzset *may* change\n\
- the local timezone used by methods such as localtime, but this behaviour\n\
- should not be relied on.");
- #endif /* HAVE_WORKING_TZSET */
- static int
- get_monotonic(_PyTime_t *t)
- {
- // Avoid _PyTime_GetMonotonicClock() which silently ignores errors.
- return _PyTime_GetMonotonicClockWithInfo(t, NULL);
- }
- static PyObject *
- time_monotonic(PyObject *self, PyObject *unused)
- {
- _PyTime_t t;
- if (get_monotonic(&t) < 0) {
- return NULL;
- }
- return _PyFloat_FromPyTime(t);
- }
- PyDoc_STRVAR(monotonic_doc,
- "monotonic() -> float\n\
- \n\
- Monotonic clock, cannot go backward.");
- static PyObject *
- time_monotonic_ns(PyObject *self, PyObject *unused)
- {
- _PyTime_t t;
- if (get_monotonic(&t) < 0) {
- return NULL;
- }
- return _PyTime_AsNanosecondsObject(t);
- }
- PyDoc_STRVAR(monotonic_ns_doc,
- "monotonic_ns() -> int\n\
- \n\
- Monotonic clock, cannot go backward, as nanoseconds.");
- static int
- get_perf_counter(_PyTime_t *t)
- {
- // Avoid _PyTime_GetPerfCounter() which silently ignores errors.
- return _PyTime_GetPerfCounterWithInfo(t, NULL);
- }
- static PyObject *
- time_perf_counter(PyObject *self, PyObject *unused)
- {
- _PyTime_t t;
- if (get_perf_counter(&t) < 0) {
- return NULL;
- }
- return _PyFloat_FromPyTime(t);
- }
- PyDoc_STRVAR(perf_counter_doc,
- "perf_counter() -> float\n\
- \n\
- Performance counter for benchmarking.");
- static PyObject *
- time_perf_counter_ns(PyObject *self, PyObject *unused)
- {
- _PyTime_t t;
- if (get_perf_counter(&t) < 0) {
- return NULL;
- }
- return _PyTime_AsNanosecondsObject(t);
- }
- PyDoc_STRVAR(perf_counter_ns_doc,
- "perf_counter_ns() -> int\n\
- \n\
- Performance counter for benchmarking as nanoseconds.");
- static int
- _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
- {
- #if defined(MS_WINDOWS)
- HANDLE process;
- FILETIME creation_time, exit_time, kernel_time, user_time;
- ULARGE_INTEGER large;
- _PyTime_t ktime, utime, t;
- BOOL ok;
- process = GetCurrentProcess();
- ok = GetProcessTimes(process, &creation_time, &exit_time,
- &kernel_time, &user_time);
- if (!ok) {
- PyErr_SetFromWindowsErr(0);
- return -1;
- }
- if (info) {
- info->implementation = "GetProcessTimes()";
- info->resolution = 1e-7;
- info->monotonic = 1;
- info->adjustable = 0;
- }
- large.u.LowPart = kernel_time.dwLowDateTime;
- large.u.HighPart = kernel_time.dwHighDateTime;
- ktime = large.QuadPart;
- large.u.LowPart = user_time.dwLowDateTime;
- large.u.HighPart = user_time.dwHighDateTime;
- utime = large.QuadPart;
- /* ktime and utime have a resolution of 100 nanoseconds */
- t = _PyTime_FromNanoseconds((ktime + utime) * 100);
- *tp = t;
- return 0;
- #else
- /* clock_gettime */
- // gh-115714: Don't use CLOCK_PROCESS_CPUTIME_ID on WASI.
- /* CLOCK_PROF is defined on NetBSD, but not supported.
- * CLOCK_PROCESS_CPUTIME_ID is broken on NetBSD for the same reason as
- * CLOCK_THREAD_CPUTIME_ID (see comment below).
- */
- #if defined(HAVE_CLOCK_GETTIME) \
- && (defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_PROF)) \
- && !defined(__NetBSD__)
- struct timespec ts;
- if (HAVE_CLOCK_GETTIME_RUNTIME) {
- #ifdef CLOCK_PROF
- const clockid_t clk_id = CLOCK_PROF;
- const char *function = "clock_gettime(CLOCK_PROF)";
- #else
- const clockid_t clk_id = CLOCK_PROCESS_CPUTIME_ID;
- const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)";
- #endif
- if (clock_gettime(clk_id, &ts) == 0) {
- if (info) {
- struct timespec res;
- info->implementation = function;
- info->monotonic = 1;
- info->adjustable = 0;
- if (clock_getres(clk_id, &res)) {
- PyErr_SetFromErrno(PyExc_OSError);
- return -1;
- }
- info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
- }
- if (_PyTime_FromTimespec(tp, &ts) < 0) {
- return -1;
- }
- return 0;
- }
- }
- #endif
- /* getrusage(RUSAGE_SELF) */
- #if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRUSAGE)
- struct rusage ru;
- if (getrusage(RUSAGE_SELF, &ru) == 0) {
- _PyTime_t utime, stime;
- if (info) {
- info->implementation = "getrusage(RUSAGE_SELF)";
- info->monotonic = 1;
- info->adjustable = 0;
- info->resolution = 1e-6;
- }
- if (_PyTime_FromTimeval(&utime, &ru.ru_utime) < 0) {
- return -1;
- }
- if (_PyTime_FromTimeval(&stime, &ru.ru_stime) < 0) {
- return -1;
- }
- _PyTime_t total = utime + stime;
- *tp = total;
- return 0;
- }
- #endif
- /* times() */
- #ifdef HAVE_TIMES
- struct tms t;
- if (times(&t) != (clock_t)-1) {
- assert(_PyRuntime.time.ticks_per_second_initialized);
- if (check_ticks_per_second(ticks_per_second, "_SC_CLK_TCK") < 0) {
- return -1;
- }
- if (ticks_per_second != -1) {
- if (info) {
- info->implementation = "times()";
- info->monotonic = 1;
- info->adjustable = 0;
- info->resolution = 1.0 / (double)ticks_per_second;
- }
- _PyTime_t ns;
- ns = _PyTime_MulDiv(t.tms_utime, SEC_TO_NS, ticks_per_second);
- ns += _PyTime_MulDiv(t.tms_stime, SEC_TO_NS, ticks_per_second);
- *tp = _PyTime_FromNanoseconds(ns);
- return 0;
- }
- }
- #endif
- /* clock */
- /* Currently, Python 3 requires clock() to build: see issue #22624 */
- return _PyTime_GetClockWithInfo(tp, info);
- #endif
- }
- static PyObject *
- time_process_time(PyObject *self, PyObject *unused)
- {
- _PyTime_t t;
- if (_PyTime_GetProcessTimeWithInfo(&t, NULL) < 0) {
- return NULL;
- }
- return _PyFloat_FromPyTime(t);
- }
- PyDoc_STRVAR(process_time_doc,
- "process_time() -> float\n\
- \n\
- Process time for profiling: sum of the kernel and user-space CPU time.");
- static PyObject *
- time_process_time_ns(PyObject *self, PyObject *unused)
- {
- _PyTime_t t;
- if (_PyTime_GetProcessTimeWithInfo(&t, NULL) < 0) {
- return NULL;
- }
- return _PyTime_AsNanosecondsObject(t);
- }
- PyDoc_STRVAR(process_time_ns_doc,
- "process_time() -> int\n\
- \n\
- Process time for profiling as nanoseconds:\n\
- sum of the kernel and user-space CPU time.");
- #if defined(MS_WINDOWS)
- #define HAVE_THREAD_TIME
- static int
- _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
- {
- HANDLE thread;
- FILETIME creation_time, exit_time, kernel_time, user_time;
- ULARGE_INTEGER large;
- _PyTime_t ktime, utime, t;
- BOOL ok;
- thread = GetCurrentThread();
- ok = GetThreadTimes(thread, &creation_time, &exit_time,
- &kernel_time, &user_time);
- if (!ok) {
- PyErr_SetFromWindowsErr(0);
- return -1;
- }
- if (info) {
- info->implementation = "GetThreadTimes()";
- info->resolution = 1e-7;
- info->monotonic = 1;
- info->adjustable = 0;
- }
- large.u.LowPart = kernel_time.dwLowDateTime;
- large.u.HighPart = kernel_time.dwHighDateTime;
- ktime = large.QuadPart;
- large.u.LowPart = user_time.dwLowDateTime;
- large.u.HighPart = user_time.dwHighDateTime;
- utime = large.QuadPart;
- /* ktime and utime have a resolution of 100 nanoseconds */
- t = _PyTime_FromNanoseconds((ktime + utime) * 100);
- *tp = t;
- return 0;
- }
- #elif defined(_AIX)
- #define HAVE_THREAD_TIME
- static int
- _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
- {
- /* bpo-40192: On AIX, thread_cputime() is preferred: it has nanosecond
- resolution, whereas clock_gettime(CLOCK_THREAD_CPUTIME_ID)
- has a resolution of 10 ms. */
- thread_cputime_t tc;
- if (thread_cputime(-1, &tc) != 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- return -1;
- }
- if (info) {
- info->implementation = "thread_cputime()";
- info->monotonic = 1;
- info->adjustable = 0;
- info->resolution = 1e-9;
- }
- *tp = _PyTime_FromNanoseconds(tc.stime + tc.utime);
- return 0;
- }
- #elif defined(__sun) && defined(__SVR4)
- #define HAVE_THREAD_TIME
- static int
- _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
- {
- /* bpo-35455: On Solaris, CLOCK_THREAD_CPUTIME_ID clock is not always
- available; use gethrvtime() to substitute this functionality. */
- if (info) {
- info->implementation = "gethrvtime()";
- info->resolution = 1e-9;
- info->monotonic = 1;
- info->adjustable = 0;
- }
- *tp = _PyTime_FromNanoseconds(gethrvtime());
- return 0;
- }
- /* CLOCK_THREAD_CPUTIME_ID is broken on NetBSD: the result of clock_gettime()
- * includes the sleeping time, that defeats the purpose of the clock.
- * Also, clock_getres() does not support it.
- * https://github.com/python/cpython/issues/123978
- * https://gnats.netbsd.org/57512
- */
- #elif defined(HAVE_CLOCK_GETTIME) && \
- defined(CLOCK_THREAD_CPUTIME_ID) && \
- !defined(__EMSCRIPTEN__) && !defined(__wasi__) && \
- !defined(__NetBSD__)
- #define HAVE_THREAD_TIME
- #if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability)
- static int
- _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
- __attribute__((availability(macos, introduced=10.12)))
- __attribute__((availability(ios, introduced=10.0)))
- __attribute__((availability(tvos, introduced=10.0)))
- __attribute__((availability(watchos, introduced=3.0)));
- #endif
- static int
- _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
- {
- struct timespec ts;
- const clockid_t clk_id = CLOCK_THREAD_CPUTIME_ID;
- const char *function = "clock_gettime(CLOCK_THREAD_CPUTIME_ID)";
- if (clock_gettime(clk_id, &ts)) {
- PyErr_SetFromErrno(PyExc_OSError);
- return -1;
- }
- if (info) {
- struct timespec res;
- info->implementation = function;
- info->monotonic = 1;
- info->adjustable = 0;
- if (clock_getres(clk_id, &res)) {
- PyErr_SetFromErrno(PyExc_OSError);
- return -1;
- }
- info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
- }
- if (_PyTime_FromTimespec(tp, &ts) < 0) {
- return -1;
- }
- return 0;
- }
- #endif
- #ifdef HAVE_THREAD_TIME
- #ifdef __APPLE__
- /*
- * The clock_* functions will be removed from the module
- * dict entirely when the C API is not available.
- */
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wunguarded-availability"
- #endif
- static PyObject *
- time_thread_time(PyObject *self, PyObject *unused)
- {
- _PyTime_t t;
- if (_PyTime_GetThreadTimeWithInfo(&t, NULL) < 0) {
- return NULL;
- }
- return _PyFloat_FromPyTime(t);
- }
- PyDoc_STRVAR(thread_time_doc,
- "thread_time() -> float\n\
- \n\
- Thread time for profiling: sum of the kernel and user-space CPU time.");
- static PyObject *
- time_thread_time_ns(PyObject *self, PyObject *unused)
- {
- _PyTime_t t;
- if (_PyTime_GetThreadTimeWithInfo(&t, NULL) < 0) {
- return NULL;
- }
- return _PyTime_AsNanosecondsObject(t);
- }
- PyDoc_STRVAR(thread_time_ns_doc,
- "thread_time() -> int\n\
- \n\
- Thread time for profiling as nanoseconds:\n\
- sum of the kernel and user-space CPU time.");
- #ifdef __APPLE__
- #pragma clang diagnostic pop
- #endif
- #endif
- static PyObject *
- time_get_clock_info(PyObject *self, PyObject *args)
- {
- char *name;
- _Py_clock_info_t info;
- PyObject *obj = NULL, *dict, *ns;
- _PyTime_t t;
- if (!PyArg_ParseTuple(args, "s:get_clock_info", &name)) {
- return NULL;
- }
- #ifdef Py_DEBUG
- info.implementation = NULL;
- info.monotonic = -1;
- info.adjustable = -1;
- info.resolution = -1.0;
- #else
- info.implementation = "";
- info.monotonic = 0;
- info.adjustable = 0;
- info.resolution = 1.0;
- #endif
- if (strcmp(name, "time") == 0) {
- if (_PyTime_GetSystemClockWithInfo(&t, &info) < 0) {
- return NULL;
- }
- }
- else if (strcmp(name, "monotonic") == 0) {
- if (_PyTime_GetMonotonicClockWithInfo(&t, &info) < 0) {
- return NULL;
- }
- }
- else if (strcmp(name, "perf_counter") == 0) {
- if (_PyTime_GetPerfCounterWithInfo(&t, &info) < 0) {
- return NULL;
- }
- }
- else if (strcmp(name, "process_time") == 0) {
- if (_PyTime_GetProcessTimeWithInfo(&t, &info) < 0) {
- return NULL;
- }
- }
- #ifdef HAVE_THREAD_TIME
- else if (strcmp(name, "thread_time") == 0) {
- #ifdef __APPLE__
- if (HAVE_CLOCK_GETTIME_RUNTIME) {
- #endif
- if (_PyTime_GetThreadTimeWithInfo(&t, &info) < 0) {
- return NULL;
- }
- #ifdef __APPLE__
- } else {
- PyErr_SetString(PyExc_ValueError, "unknown clock");
- return NULL;
- }
- #endif
- }
- #endif
- else {
- PyErr_SetString(PyExc_ValueError, "unknown clock");
- return NULL;
- }
- dict = PyDict_New();
- if (dict == NULL) {
- return NULL;
- }
- assert(info.implementation != NULL);
- obj = PyUnicode_FromString(info.implementation);
- if (obj == NULL) {
- goto error;
- }
- if (PyDict_SetItemString(dict, "implementation", obj) == -1) {
- goto error;
- }
- Py_CLEAR(obj);
- assert(info.monotonic != -1);
- obj = PyBool_FromLong(info.monotonic);
- if (obj == NULL) {
- goto error;
- }
- if (PyDict_SetItemString(dict, "monotonic", obj) == -1) {
- goto error;
- }
- Py_CLEAR(obj);
- assert(info.adjustable != -1);
- obj = PyBool_FromLong(info.adjustable);
- if (obj == NULL) {
- goto error;
- }
- if (PyDict_SetItemString(dict, "adjustable", obj) == -1) {
- goto error;
- }
- Py_CLEAR(obj);
- assert(info.resolution > 0.0);
- assert(info.resolution <= 1.0);
- obj = PyFloat_FromDouble(info.resolution);
- if (obj == NULL) {
- goto error;
- }
- if (PyDict_SetItemString(dict, "resolution", obj) == -1) {
- goto error;
- }
- Py_CLEAR(obj);
- ns = _PyNamespace_New(dict);
- Py_DECREF(dict);
- return ns;
- error:
- Py_DECREF(dict);
- Py_XDECREF(obj);
- return NULL;
- }
- PyDoc_STRVAR(get_clock_info_doc,
- "get_clock_info(name: str) -> dict\n\
- \n\
- Get information of the specified clock.");
- #ifndef HAVE_DECL_TZNAME
- static void
- get_zone(char *zone, int n, struct tm *p)
- {
- #ifdef HAVE_STRUCT_TM_TM_ZONE
- strncpy(zone, p->tm_zone ? p->tm_zone : " ", n);
- #else
- tzset();
- strftime(zone, n, "%Z", p);
- #endif
- }
- static time_t
- get_gmtoff(time_t t, struct tm *p)
- {
- #ifdef HAVE_STRUCT_TM_TM_ZONE
- return p->tm_gmtoff;
- #else
- return timegm(p) - t;
- #endif
- }
- #endif // !HAVE_DECL_TZNAME
- static int
- init_timezone(PyObject *m)
- {
- #define ADD_INT(NAME, VALUE) do { \
- if (PyModule_AddIntConstant(m, NAME, VALUE) < 0) { \
- return -1; \
- } \
- } while (0)
- assert(!PyErr_Occurred());
- /* This code moved from PyInit_time wholesale to allow calling it from
- time_tzset. In the future, some parts of it can be moved back
- (for platforms that don't HAVE_WORKING_TZSET, when we know what they
- are), and the extraneous calls to tzset(3) should be removed.
- I haven't done this yet, as I don't want to change this code as
- little as possible when introducing the time.tzset and time.tzsetwall
- methods. This should simply be a method of doing the following once,
- at the top of this function and removing the call to tzset() from
- time_tzset():
- #ifdef HAVE_TZSET
- tzset()
- #endif
- And I'm lazy and hate C so nyer.
- */
- #ifdef HAVE_DECL_TZNAME
- PyObject *otz0, *otz1;
- #if !defined(MS_WINDOWS) || defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
- tzset();
- #endif
- ADD_INT("timezone", _Py_timezone);
- #ifdef HAVE_ALTZONE
- ADD_INT("altzone", altzone);
- #else
- ADD_INT("altzone", _Py_timezone-3600);
- #endif
- ADD_INT("daylight", _Py_daylight);
- #ifdef MS_WINDOWS
- TIME_ZONE_INFORMATION tzinfo = {0};
- GetTimeZoneInformation(&tzinfo);
- otz0 = PyUnicode_FromWideChar(tzinfo.StandardName, -1);
- if (otz0 == NULL) {
- return -1;
- }
- otz1 = PyUnicode_FromWideChar(tzinfo.DaylightName, -1);
- if (otz1 == NULL) {
- Py_DECREF(otz0);
- return -1;
- }
- #else
- otz0 = PyUnicode_DecodeLocale(_Py_tzname[0], "surrogateescape");
- if (otz0 == NULL) {
- return -1;
- }
- otz1 = PyUnicode_DecodeLocale(_Py_tzname[1], "surrogateescape");
- if (otz1 == NULL) {
- Py_DECREF(otz0);
- return -1;
- }
- #endif // MS_WINDOWS
- if (_PyModule_Add(m, "tzname", Py_BuildValue("(NN)", otz0, otz1)) < 0) {
- return -1;
- }
- #else // !HAVE_DECL_TZNAME
- static const time_t YEAR = (365 * 24 + 6) * 3600;
- time_t t;
- struct tm p;
- time_t janzone_t, julyzone_t;
- char janname[10], julyname[10];
- t = (time((time_t *)0) / YEAR) * YEAR;
- _PyTime_localtime(t, &p);
- get_zone(janname, 9, &p);
- janzone_t = -get_gmtoff(t, &p);
- janname[9] = '\0';
- t += YEAR/2;
- _PyTime_localtime(t, &p);
- get_zone(julyname, 9, &p);
- julyzone_t = -get_gmtoff(t, &p);
- julyname[9] = '\0';
- /* Sanity check, don't check for the validity of timezones.
- In practice, it should be more in range -12 hours .. +14 hours. */
- #define MAX_TIMEZONE (48 * 3600)
- if (janzone_t < -MAX_TIMEZONE || janzone_t > MAX_TIMEZONE
- || julyzone_t < -MAX_TIMEZONE || julyzone_t > MAX_TIMEZONE)
- {
- PyErr_SetString(PyExc_RuntimeError, "invalid GMT offset");
- return -1;
- }
- int janzone = (int)janzone_t;
- int julyzone = (int)julyzone_t;
- PyObject *tzname_obj;
- if (janzone < julyzone) {
- /* DST is reversed in the southern hemisphere */
- ADD_INT("timezone", julyzone);
- ADD_INT("altzone", janzone);
- ADD_INT("daylight", janzone != julyzone);
- tzname_obj = Py_BuildValue("(zz)", julyname, janname);
- } else {
- ADD_INT("timezone", janzone);
- ADD_INT("altzone", julyzone);
- ADD_INT("daylight", janzone != julyzone);
- tzname_obj = Py_BuildValue("(zz)", janname, julyname);
- }
- if (_PyModule_Add(m, "tzname", tzname_obj) < 0) {
- return -1;
- }
- #endif // !HAVE_DECL_TZNAME
- #undef ADD_INT
- if (PyErr_Occurred()) {
- return -1;
- }
- return 0;
- }
- static PyMethodDef time_methods[] = {
- {"time", time_time, METH_NOARGS, time_doc},
- {"time_ns", time_time_ns, METH_NOARGS, time_ns_doc},
- #ifdef HAVE_CLOCK_GETTIME
- {"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc},
- {"clock_gettime_ns",time_clock_gettime_ns, METH_VARARGS, clock_gettime_ns_doc},
- #endif
- #ifdef HAVE_CLOCK_SETTIME
- {"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc},
- {"clock_settime_ns",time_clock_settime_ns, METH_VARARGS, clock_settime_ns_doc},
- #endif
- #ifdef HAVE_CLOCK_GETRES
- {"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc},
- #endif
- #ifdef HAVE_PTHREAD_GETCPUCLOCKID
- {"pthread_getcpuclockid", time_pthread_getcpuclockid, METH_VARARGS, pthread_getcpuclockid_doc},
- #endif
- {"sleep", time_sleep, METH_O, sleep_doc},
- {"gmtime", time_gmtime, METH_VARARGS, gmtime_doc},
- {"localtime", time_localtime, METH_VARARGS, localtime_doc},
- {"asctime", time_asctime, METH_VARARGS, asctime_doc},
- {"ctime", time_ctime, METH_VARARGS, ctime_doc},
- #ifdef HAVE_MKTIME
- {"mktime", time_mktime, METH_O, mktime_doc},
- #endif
- #ifdef HAVE_STRFTIME
- {"strftime", time_strftime, METH_VARARGS, strftime_doc},
- #endif
- {"strptime", time_strptime, METH_VARARGS, strptime_doc},
- #ifdef HAVE_WORKING_TZSET
- {"tzset", time_tzset, METH_NOARGS, tzset_doc},
- #endif
- {"monotonic", time_monotonic, METH_NOARGS, monotonic_doc},
- {"monotonic_ns", time_monotonic_ns, METH_NOARGS, monotonic_ns_doc},
- {"process_time", time_process_time, METH_NOARGS, process_time_doc},
- {"process_time_ns", time_process_time_ns, METH_NOARGS, process_time_ns_doc},
- #ifdef HAVE_THREAD_TIME
- {"thread_time", time_thread_time, METH_NOARGS, thread_time_doc},
- {"thread_time_ns", time_thread_time_ns, METH_NOARGS, thread_time_ns_doc},
- #endif
- {"perf_counter", time_perf_counter, METH_NOARGS, perf_counter_doc},
- {"perf_counter_ns", time_perf_counter_ns, METH_NOARGS, perf_counter_ns_doc},
- {"get_clock_info", time_get_clock_info, METH_VARARGS, get_clock_info_doc},
- {NULL, NULL} /* sentinel */
- };
- PyDoc_STRVAR(module_doc,
- "This module provides various functions to manipulate time values.\n\
- \n\
- There are two standard representations of time. One is the number\n\
- of seconds since the Epoch, in UTC (a.k.a. GMT). It may be an integer\n\
- or a floating-point number (to represent fractions of seconds).\n\
- The epoch is the point where the time starts, the return value of time.gmtime(0).\n\
- It is January 1, 1970, 00:00:00 (UTC) on all platforms.\n\
- \n\
- The other representation is a tuple of 9 integers giving local time.\n\
- The tuple items are:\n\
- year (including century, e.g. 1998)\n\
- month (1-12)\n\
- day (1-31)\n\
- hours (0-23)\n\
- minutes (0-59)\n\
- seconds (0-59)\n\
- weekday (0-6, Monday is 0)\n\
- Julian day (day in the year, 1-366)\n\
- DST (Daylight Savings Time) flag (-1, 0 or 1)\n\
- If the DST flag is 0, the time is given in the regular time zone;\n\
- if it is 1, the time is given in the DST time zone;\n\
- if it is -1, mktime() should guess based on the date and time.\n");
- static int
- time_exec(PyObject *module)
- {
- time_module_state *state = get_time_state(module);
- #if defined(__APPLE__) && defined(HAVE_CLOCK_GETTIME)
- if (HAVE_CLOCK_GETTIME_RUNTIME) {
- /* pass: ^^^ cannot use '!' here */
- } else {
- PyObject* dct = PyModule_GetDict(module);
- if (dct == NULL) {
- return -1;
- }
- if (PyDict_DelItemString(dct, "clock_gettime") == -1) {
- PyErr_Clear();
- }
- if (PyDict_DelItemString(dct, "clock_gettime_ns") == -1) {
- PyErr_Clear();
- }
- if (PyDict_DelItemString(dct, "clock_settime") == -1) {
- PyErr_Clear();
- }
- if (PyDict_DelItemString(dct, "clock_settime_ns") == -1) {
- PyErr_Clear();
- }
- if (PyDict_DelItemString(dct, "clock_getres") == -1) {
- PyErr_Clear();
- }
- }
- #endif
- #if defined(__APPLE__) && defined(HAVE_THREAD_TIME)
- if (HAVE_CLOCK_GETTIME_RUNTIME) {
- /* pass: ^^^ cannot use '!' here */
- } else {
- PyObject* dct = PyModule_GetDict(module);
- if (PyDict_DelItemString(dct, "thread_time") == -1) {
- PyErr_Clear();
- }
- if (PyDict_DelItemString(dct, "thread_time_ns") == -1) {
- PyErr_Clear();
- }
- }
- #endif
- /* Set, or reset, module variables like time.timezone */
- if (init_timezone(module) < 0) {
- return -1;
- }
- #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES)
- if (HAVE_CLOCK_GETTIME_RUNTIME) {
- #ifdef CLOCK_REALTIME
- if (PyModule_AddIntMacro(module, CLOCK_REALTIME) < 0) {
- return -1;
- }
- #endif
- #ifdef CLOCK_MONOTONIC
- if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC) < 0) {
- return -1;
- }
- #endif
- #ifdef CLOCK_MONOTONIC_RAW
- if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC_RAW) < 0) {
- return -1;
- }
- #endif
- #ifdef CLOCK_HIGHRES
- if (PyModule_AddIntMacro(module, CLOCK_HIGHRES) < 0) {
- return -1;
- }
- #endif
- #ifdef CLOCK_PROCESS_CPUTIME_ID
- if (PyModule_AddIntMacro(module, CLOCK_PROCESS_CPUTIME_ID) < 0) {
- return -1;
- }
- #endif
- #ifdef CLOCK_THREAD_CPUTIME_ID
- if (PyModule_AddIntMacro(module, CLOCK_THREAD_CPUTIME_ID) < 0) {
- return -1;
- }
- #endif
- #ifdef CLOCK_PROF
- if (PyModule_AddIntMacro(module, CLOCK_PROF) < 0) {
- return -1;
- }
- #endif
- #ifdef CLOCK_BOOTTIME
- if (PyModule_AddIntMacro(module, CLOCK_BOOTTIME) < 0) {
- return -1;
- }
- #endif
- #ifdef CLOCK_TAI
- if (PyModule_AddIntMacro(module, CLOCK_TAI) < 0) {
- return -1;
- }
- #endif
- #ifdef CLOCK_UPTIME
- if (PyModule_AddIntMacro(module, CLOCK_UPTIME) < 0) {
- return -1;
- }
- #endif
- #ifdef CLOCK_UPTIME_RAW
- if (PyModule_AddIntMacro(module, CLOCK_UPTIME_RAW) < 0) {
- return -1;
- }
- #endif
- }
- #endif /* defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES) */
- if (PyModule_AddIntConstant(module, "_STRUCT_TM_ITEMS", 11)) {
- return -1;
- }
- // struct_time type
- state->struct_time_type = PyStructSequence_NewType(&struct_time_type_desc);
- if (state->struct_time_type == NULL) {
- return -1;
- }
- if (PyModule_AddType(module, state->struct_time_type)) {
- return -1;
- }
- #if defined(__linux__) && !defined(__GLIBC__)
- struct tm tm;
- const time_t zero = 0;
- if (gmtime_r(&zero, &tm) != NULL)
- utc_string = tm.tm_zone;
- #endif
- #if defined(MS_WINDOWS)
- if (timer_flags == (DWORD)-1) {
- DWORD test_flags = CREATE_WAITABLE_TIMER_HIGH_RESOLUTION;
- HANDLE timer = CreateWaitableTimerExW(NULL, NULL, test_flags,
- TIMER_ALL_ACCESS);
- if (timer == NULL) {
- // CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is not supported.
- timer_flags = 0;
- }
- else {
- // CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is supported.
- timer_flags = CREATE_WAITABLE_TIMER_HIGH_RESOLUTION;
- CloseHandle(timer);
- }
- }
- #endif
- return 0;
- }
- static int
- time_module_traverse(PyObject *module, visitproc visit, void *arg)
- {
- time_module_state *state = get_time_state(module);
- Py_VISIT(state->struct_time_type);
- return 0;
- }
- static int
- time_module_clear(PyObject *module)
- {
- time_module_state *state = get_time_state(module);
- Py_CLEAR(state->struct_time_type);
- return 0;
- }
- static void
- time_module_free(void *module)
- {
- time_module_clear((PyObject *)module);
- }
- static struct PyModuleDef_Slot time_slots[] = {
- {Py_mod_exec, time_exec},
- {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
- {0, NULL}
- };
- static struct PyModuleDef timemodule = {
- PyModuleDef_HEAD_INIT,
- .m_name = "time",
- .m_doc = module_doc,
- .m_size = sizeof(time_module_state),
- .m_methods = time_methods,
- .m_slots = time_slots,
- .m_traverse = time_module_traverse,
- .m_clear = time_module_clear,
- .m_free = time_module_free,
- };
- PyMODINIT_FUNC
- PyInit_time(void)
- {
- return PyModuleDef_Init(&timemodule);
- }
- // time.sleep() implementation.
- // On error, raise an exception and return -1.
- // On success, return 0.
- static int
- pysleep(_PyTime_t timeout)
- {
- assert(timeout >= 0);
- #ifndef MS_WINDOWS
- #ifdef HAVE_CLOCK_NANOSLEEP
- struct timespec timeout_abs;
- #elif defined(HAVE_NANOSLEEP)
- struct timespec timeout_ts;
- #else
- struct timeval timeout_tv;
- #endif
- _PyTime_t deadline, monotonic;
- int err = 0;
- if (get_monotonic(&monotonic) < 0) {
- return -1;
- }
- deadline = monotonic + timeout;
- #ifdef HAVE_CLOCK_NANOSLEEP
- if (_PyTime_AsTimespec(deadline, &timeout_abs) < 0) {
- return -1;
- }
- #endif
- do {
- #ifdef HAVE_CLOCK_NANOSLEEP
- // use timeout_abs
- #elif defined(HAVE_NANOSLEEP)
- if (_PyTime_AsTimespec(timeout, &timeout_ts) < 0) {
- return -1;
- }
- #else
- if (_PyTime_AsTimeval(timeout, &timeout_tv, _PyTime_ROUND_CEILING) < 0) {
- return -1;
- }
- #endif
- int ret;
- Py_BEGIN_ALLOW_THREADS
- #ifdef HAVE_CLOCK_NANOSLEEP
- ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL);
- err = ret;
- #elif defined(HAVE_NANOSLEEP)
- ret = nanosleep(&timeout_ts, NULL);
- err = errno;
- #else
- ret = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout_tv);
- err = errno;
- #endif
- Py_END_ALLOW_THREADS
- if (ret == 0) {
- break;
- }
- if (err != EINTR) {
- errno = err;
- PyErr_SetFromErrno(PyExc_OSError);
- return -1;
- }
- /* sleep was interrupted by SIGINT */
- if (PyErr_CheckSignals()) {
- return -1;
- }
- #ifndef HAVE_CLOCK_NANOSLEEP
- if (get_monotonic(&monotonic) < 0) {
- return -1;
- }
- timeout = deadline - monotonic;
- if (timeout < 0) {
- break;
- }
- /* retry with the recomputed delay */
- #endif
- } while (1);
- return 0;
- #else // MS_WINDOWS
- _PyTime_t timeout_100ns = _PyTime_As100Nanoseconds(timeout,
- _PyTime_ROUND_CEILING);
- // Maintain Windows Sleep() semantics for time.sleep(0)
- if (timeout_100ns == 0) {
- Py_BEGIN_ALLOW_THREADS
- // A value of zero causes the thread to relinquish the remainder of its
- // time slice to any other thread that is ready to run. If there are no
- // other threads ready to run, the function returns immediately, and
- // the thread continues execution.
- Sleep(0);
- Py_END_ALLOW_THREADS
- return 0;
- }
- LARGE_INTEGER relative_timeout;
- // No need to check for integer overflow, both types are signed
- assert(sizeof(relative_timeout) == sizeof(timeout_100ns));
- // SetWaitableTimer(): a negative due time indicates relative time
- relative_timeout.QuadPart = -timeout_100ns;
- HANDLE timer = CreateWaitableTimerExW(NULL, NULL, timer_flags,
- TIMER_ALL_ACCESS);
- if (timer == NULL) {
- PyErr_SetFromWindowsErr(0);
- return -1;
- }
- if (!SetWaitableTimerEx(timer, &relative_timeout,
- 0, // no period; the timer is signaled once
- NULL, NULL, // no completion routine
- NULL, // no wake context; do not resume from suspend
- 0)) // no tolerable delay for timer coalescing
- {
- PyErr_SetFromWindowsErr(0);
- goto error;
- }
- // Only the main thread can be interrupted by SIGINT.
- // Signal handlers are only executed in the main thread.
- if (_PyOS_IsMainThread()) {
- HANDLE sigint_event = _PyOS_SigintEvent();
- while (1) {
- // Check for pending SIGINT signal before resetting the event
- if (PyErr_CheckSignals()) {
- goto error;
- }
- ResetEvent(sigint_event);
- HANDLE events[] = {timer, sigint_event};
- DWORD rc;
- Py_BEGIN_ALLOW_THREADS
- rc = WaitForMultipleObjects(Py_ARRAY_LENGTH(events), events,
- // bWaitAll
- FALSE,
- // No wait timeout
- INFINITE);
- Py_END_ALLOW_THREADS
- if (rc == WAIT_FAILED) {
- PyErr_SetFromWindowsErr(0);
- goto error;
- }
- if (rc == WAIT_OBJECT_0) {
- // Timer signaled: we are done
- break;
- }
- assert(rc == (WAIT_OBJECT_0 + 1));
- // The sleep was interrupted by SIGINT: restart sleeping
- }
- }
- else {
- DWORD rc;
- Py_BEGIN_ALLOW_THREADS
- rc = WaitForSingleObject(timer, INFINITE);
- Py_END_ALLOW_THREADS
- if (rc == WAIT_FAILED) {
- PyErr_SetFromWindowsErr(0);
- goto error;
- }
- assert(rc == WAIT_OBJECT_0);
- // Timer signaled: we are done
- }
- CloseHandle(timer);
- return 0;
- error:
- CloseHandle(timer);
- return -1;
- #endif
- }
|