cpython/Python/pytime.c

#include "Python.h"
#include "pycore_time.h"          // PyTime_t

#include <time.h>                 // gmtime_r()
#ifdef HAVE_SYS_TIME_H
#  include <sys/time.h>           // gettimeofday()
#endif
#ifdef MS_WINDOWS
#  include <winsock2.h>           // struct timeval
#endif

#if defined(__APPLE__)
#  include <mach/mach_time.h>     // mach_absolute_time(), mach_timebase_info()

#if defined(__APPLE__) && defined(__has_builtin)
#  if __has_builtin(__builtin_available)
#define HAVE_CLOCK_GETTIME_RUNTIME
#  endif
#endif
#endif

/* To millisecond (10^-3) */
#define SEC_TO_MS

/* To microseconds (10^-6) */
#define MS_TO_US
#define SEC_TO_US

/* To nanoseconds (10^-9) */
#define US_TO_NS
#define MS_TO_NS
#define SEC_TO_NS

/* Conversion from nanoseconds */
#define NS_TO_MS
#define NS_TO_US
#define NS_TO_100NS

#if SIZEOF_TIME_T == SIZEOF_LONG_LONG
#define PY_TIME_T_MAX
#define PY_TIME_T_MIN
#elif SIZEOF_TIME_T == SIZEOF_LONG
#define PY_TIME_T_MAX
#define PY_TIME_T_MIN
#else
#  error "unsupported time_t size"
#endif

#if PY_TIME_T_MAX + PY_TIME_T_MIN != -1
#  error "time_t is not a two's complement integer type"
#endif

#if PyTime_MIN + PyTime_MAX != -1
#  error "PyTime_t is not a two's complement integer type"
#endif


#ifdef MS_WINDOWS
static _PyTimeFraction py_qpc_base = {0, 0};

// Forward declaration
static int py_win_perf_counter_frequency(_PyTimeFraction *base, int raise_exc);
#endif


static PyTime_t
_PyTime_GCD(PyTime_t x, PyTime_t y)
{}


int
_PyTimeFraction_Set(_PyTimeFraction *frac, PyTime_t numer, PyTime_t denom)
{}


double
_PyTimeFraction_Resolution(const _PyTimeFraction *frac)
{}


static void
pytime_time_t_overflow(void)
{}


static void
pytime_overflow(void)
{}


// Compute t1 + t2. Clamp to [PyTime_MIN; PyTime_MAX] on overflow.
static inline int
pytime_add(PyTime_t *t1, PyTime_t t2)
{}


PyTime_t
_PyTime_Add(PyTime_t t1, PyTime_t t2)
{}


static inline int
pytime_mul_check_overflow(PyTime_t a, PyTime_t b)
{}


// Compute t * k. Clamp to [PyTime_MIN; PyTime_MAX] on overflow.
static inline int
pytime_mul(PyTime_t *t, PyTime_t k)
{}


// Compute t * k. Clamp to [PyTime_MIN; PyTime_MAX] on overflow.
static inline PyTime_t
_PyTime_Mul(PyTime_t t, PyTime_t k)
{}


PyTime_t
_PyTimeFraction_Mul(PyTime_t ticks, const _PyTimeFraction *frac)
{}


time_t
_PyLong_AsTime_t(PyObject *obj)
{}


PyObject *
_PyLong_FromTime_t(time_t t)
{}


// Convert PyTime_t to time_t.
// Return 0 on success. Return -1 and clamp the value on overflow.
static int
_PyTime_AsTime_t(PyTime_t t, time_t *t2)
{}


#ifdef MS_WINDOWS
// Convert PyTime_t to long.
// Return 0 on success. Return -1 and clamp the value on overflow.
static int
_PyTime_AsCLong(PyTime_t t, long *t2)
{
#if SIZEOF_LONG < _SIZEOF_PYTIME_T
    if ((PyTime_t)LONG_MAX < t) {
        *t2 = LONG_MAX;
        return -1;
    }
    if (t < (PyTime_t)LONG_MIN) {
        *t2 = LONG_MIN;
        return -1;
    }
#endif
    *t2 = (long)t;
    return 0;
}
#endif


/* Round to nearest with ties going to nearest even integer
   (_PyTime_ROUND_HALF_EVEN) */
static double
pytime_round_half_even(double x)
{}


static double
pytime_round(double x, _PyTime_round_t round)
{}


static int
pytime_double_to_denominator(double d, time_t *sec, long *numerator,
                             long idenominator, _PyTime_round_t round)
{}


static int
pytime_object_to_denominator(PyObject *obj, time_t *sec, long *numerator,
                             long denominator, _PyTime_round_t round)
{}


int
_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
{}


int
_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
                         _PyTime_round_t round)
{}


int
_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
                        _PyTime_round_t round)
{}


PyTime_t
_PyTime_FromSeconds(int seconds)
{}


PyTime_t
_PyTime_FromMicrosecondsClamp(PyTime_t us)
{}


int
_PyTime_FromLong(PyTime_t *tp, PyObject *obj)
{}


#ifdef HAVE_CLOCK_GETTIME
static int
pytime_fromtimespec(PyTime_t *tp, const struct timespec *ts, int raise_exc)
{}

int
_PyTime_FromTimespec(PyTime_t *tp, const struct timespec *ts)
{}
#endif


#ifndef MS_WINDOWS
static int
pytime_fromtimeval(PyTime_t *tp, struct timeval *tv, int raise_exc)
{}


int
_PyTime_FromTimeval(PyTime_t *tp, struct timeval *tv)
{}
#endif


static int
pytime_from_double(PyTime_t *tp, double value, _PyTime_round_t round,
                   long unit_to_ns)
{}


static int
pytime_from_object(PyTime_t *tp, PyObject *obj, _PyTime_round_t round,
                   long unit_to_ns)
{}


int
_PyTime_FromSecondsObject(PyTime_t *tp, PyObject *obj, _PyTime_round_t round)
{}


int
_PyTime_FromMillisecondsObject(PyTime_t *tp, PyObject *obj, _PyTime_round_t round)
{}


double
PyTime_AsSecondsDouble(PyTime_t ns)
{}


PyObject *
_PyTime_AsLong(PyTime_t ns)
{}

int
_PyTime_FromSecondsDouble(double seconds, _PyTime_round_t round, PyTime_t *result)
{}


static PyTime_t
pytime_divide_round_up(const PyTime_t t, const PyTime_t k)
{}


static PyTime_t
pytime_divide(const PyTime_t t, const PyTime_t k,
              const _PyTime_round_t round)
{}


// Compute (t / k, t % k) in (pq, pr).
// Make sure that 0 <= pr < k.
// Return 0 on success.
// Return -1 on underflow and store (PyTime_MIN, 0) in (pq, pr).
static int
pytime_divmod(const PyTime_t t, const PyTime_t k,
              PyTime_t *pq, PyTime_t *pr)
{}


#ifdef MS_WINDOWS
PyTime_t
_PyTime_As100Nanoseconds(PyTime_t ns, _PyTime_round_t round)
{
    return pytime_divide(ns, NS_TO_100NS, round);
}
#endif


PyTime_t
_PyTime_AsMicroseconds(PyTime_t ns, _PyTime_round_t round)
{}


PyTime_t
_PyTime_AsMilliseconds(PyTime_t ns, _PyTime_round_t round)
{}


static int
pytime_as_timeval(PyTime_t ns, PyTime_t *ptv_sec, int *ptv_usec,
                  _PyTime_round_t round)
{}


static int
pytime_as_timeval_struct(PyTime_t t, struct timeval *tv,
                         _PyTime_round_t round, int raise_exc)
{}


int
_PyTime_AsTimeval(PyTime_t t, struct timeval *tv, _PyTime_round_t round)
{}


void
_PyTime_AsTimeval_clamp(PyTime_t t, struct timeval *tv, _PyTime_round_t round)
{}


int
_PyTime_AsTimevalTime_t(PyTime_t t, time_t *p_secs, int *us,
                        _PyTime_round_t round)
{}


#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE)
static int
pytime_as_timespec(PyTime_t ns, struct timespec *ts, int raise_exc)
{}

void
_PyTime_AsTimespec_clamp(PyTime_t t, struct timespec *ts)
{}

int
_PyTime_AsTimespec(PyTime_t t, struct timespec *ts)
{}
#endif


// N.B. If raise_exc=0, this may be called without the GIL.
static int
py_get_system_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
{}


int
PyTime_Time(PyTime_t *result)
{}


int
PyTime_TimeRaw(PyTime_t *result)
{}


int
_PyTime_TimeWithInfo(PyTime_t *t, _Py_clock_info_t *info)
{}


#ifdef MS_WINDOWS
static int
py_win_perf_counter_frequency(_PyTimeFraction *base, int raise_exc)
{
    LARGE_INTEGER freq;
    // Since Windows XP, the function cannot fail.
    (void)QueryPerformanceFrequency(&freq);
    LONGLONG frequency = freq.QuadPart;

    // Since Windows XP, frequency cannot be zero.
    assert(frequency >= 1);

    Py_BUILD_ASSERT(sizeof(PyTime_t) == sizeof(frequency));
    PyTime_t denom = (PyTime_t)frequency;

    // Known QueryPerformanceFrequency() values:
    //
    // * 10,000,000 (10 MHz): 100 ns resolution
    // * 3,579,545 Hz (3.6 MHz): 279 ns resolution
    if (_PyTimeFraction_Set(base, SEC_TO_NS, denom) < 0) {
        if (raise_exc) {
            PyErr_SetString(PyExc_RuntimeError,
                            "invalid QueryPerformanceFrequency");
        }
        return -1;
    }
    return 0;
}


// N.B. If raise_exc=0, this may be called without the GIL.
static int
py_get_win_perf_counter(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
{
    assert(info == NULL || raise_exc);

    if (py_qpc_base.denom == 0) {
        if (py_win_perf_counter_frequency(&py_qpc_base, raise_exc) < 0) {
            return -1;
        }
    }

    if (info) {
        info->implementation = "QueryPerformanceCounter()";
        info->resolution = _PyTimeFraction_Resolution(&py_qpc_base);
        info->monotonic = 1;
        info->adjustable = 0;
    }

    LARGE_INTEGER now;
    QueryPerformanceCounter(&now);
    LONGLONG ticksll = now.QuadPart;

    /* Make sure that casting LONGLONG to PyTime_t cannot overflow,
       both types are signed */
    PyTime_t ticks;
    static_assert(sizeof(ticksll) <= sizeof(ticks),
                  "LONGLONG is larger than PyTime_t");
    ticks = (PyTime_t)ticksll;

    *tp = _PyTimeFraction_Mul(ticks, &py_qpc_base);
    return 0;
}
#endif  // MS_WINDOWS


#ifdef __APPLE__
static int
py_mach_timebase_info(_PyTimeFraction *base, int raise_exc)
{
    mach_timebase_info_data_t timebase;
    // According to the Technical Q&A QA1398, mach_timebase_info() cannot
    // fail: https://developer.apple.com/library/mac/#qa/qa1398/
    (void)mach_timebase_info(&timebase);

    // Check that timebase.numer and timebase.denom can be casted to
    // PyTime_t. In practice, timebase uses uint32_t, so casting cannot
    // overflow. At the end, only make sure that the type is uint32_t
    // (PyTime_t is 64-bit long).
    Py_BUILD_ASSERT(sizeof(timebase.numer) <= sizeof(PyTime_t));
    Py_BUILD_ASSERT(sizeof(timebase.denom) <= sizeof(PyTime_t));
    PyTime_t numer = (PyTime_t)timebase.numer;
    PyTime_t denom = (PyTime_t)timebase.denom;

    // Known time bases:
    //
    // * (1, 1) on Intel: 1 ns
    // * (1000000000, 33333335) on PowerPC: ~30 ns
    // * (1000000000, 25000000) on PowerPC: 40 ns
    if (_PyTimeFraction_Set(base, numer, denom) < 0) {
        if (raise_exc) {
            PyErr_SetString(PyExc_RuntimeError,
                            "invalid mach_timebase_info");
        }
        return -1;
    }
    return 0;
}
#endif


// N.B. If raise_exc=0, this may be called without the GIL.
static int
py_get_monotonic_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
{}


int
PyTime_Monotonic(PyTime_t *result)
{}


int
PyTime_MonotonicRaw(PyTime_t *result)
{}


int
_PyTime_MonotonicWithInfo(PyTime_t *tp, _Py_clock_info_t *info)
{}


int
_PyTime_PerfCounterWithInfo(PyTime_t *t, _Py_clock_info_t *info)
{}


int
PyTime_PerfCounter(PyTime_t *result)
{}


int
PyTime_PerfCounterRaw(PyTime_t *result)
{}


int
_PyTime_localtime(time_t t, struct tm *tm)
{}


int
_PyTime_gmtime(time_t t, struct tm *tm)
{}


PyTime_t
_PyDeadline_Init(PyTime_t timeout)
{}


PyTime_t
_PyDeadline_Get(PyTime_t deadline)
{}