12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327 |
- /* 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_strftime(PyObject *module, PyObject *args)
- {
- PyObject *tup = NULL;
- struct tm buf;
- const time_char *fmt;
- #ifdef HAVE_WCSFTIME
- wchar_t *format;
- #else
- PyObject *format;
- #endif
- PyObject *format_arg;
- size_t fmtlen, buflen;
- time_char *outbuf = NULL;
- size_t i;
- PyObject *ret = NULL;
- memset((void *) &buf, '\0', sizeof(buf));
- /* Will always expect a unicode string to be passed as format.
- Given that there's no str type anymore in py3k this seems safe.
- */
- 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;
- #ifdef HAVE_WCSFTIME
- format = PyUnicode_AsWideCharString(format_arg, NULL);
- if (format == NULL)
- return NULL;
- fmt = format;
- #else
- /* Convert the unicode string to an ascii one */
- format = PyUnicode_EncodeLocale(format_arg, "surrogateescape");
- if (format == NULL)
- return NULL;
- fmt = PyBytes_AS_STRING(format);
- #endif
- #if defined(MS_WINDOWS) && !defined(HAVE_WCSFTIME)
- /* check that the format string contains only valid directives */
- for (outbuf = strchr(fmt, '%');
- outbuf != NULL;
- outbuf = strchr(outbuf+2, '%'))
- {
- if (outbuf[1] == '#')
- ++outbuf; /* not documented by python, */
- if (outbuf[1] == '\0')
- break;
- if ((outbuf[1] == 'y') && buf.tm_year < 0) {
- PyErr_SetString(PyExc_ValueError,
- "format %y requires year >= 1900 on Windows");
- Py_DECREF(format);
- return NULL;
- }
- }
- #elif (defined(_AIX) || (defined(__sun) && defined(__SVR4))) && defined(HAVE_WCSFTIME)
- for (outbuf = wcschr(fmt, '%');
- outbuf != NULL;
- outbuf = wcschr(outbuf+2, '%'))
- {
- if (outbuf[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 (outbuf[1] == L'y' && buf.tm_year < 0) {
- PyErr_SetString(PyExc_ValueError,
- "format %y requires year >= 1900 on AIX");
- PyMem_Free(format);
- return NULL;
- }
- }
- #endif
- fmtlen = time_strlen(fmt);
- /* I hate these functions that presume you know how big the output
- * will be ahead of time...
- */
- for (i = 1024; ; i += i) {
- outbuf = (time_char *)PyMem_Malloc(i*sizeof(time_char));
- if (outbuf == NULL) {
- PyErr_NoMemory();
- break;
- }
- #if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
- errno = 0;
- #endif
- _Py_BEGIN_SUPPRESS_IPH
- buflen = format_time(outbuf, i, fmt, &buf);
- _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");
- PyMem_Free(outbuf);
- break;
- }
- #endif
- if (buflen > 0 || i >= 256 * fmtlen) {
- /* 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
- ret = PyUnicode_FromWideChar(outbuf, buflen);
- #else
- ret = PyUnicode_DecodeLocaleAndSize(outbuf, buflen, "surrogateescape");
- #endif
- PyMem_Free(outbuf);
- break;
- }
- PyMem_Free(outbuf);
- }
- #ifdef HAVE_WCSFTIME
- PyMem_Free(format);
- #else
- Py_DECREF(format);
- #endif
- return ret;
- }
- #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 */
- #if defined(HAVE_CLOCK_GETTIME) \
- && (defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_PROF))
- 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;
- }
- #elif defined(HAVE_CLOCK_GETTIME) && \
- defined(CLOCK_PROCESS_CPUTIME_ID) && \
- !defined(__EMSCRIPTEN__) && !defined(__wasi__)
- #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
- }
|