Пример #1
0
static int
_PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round,
                   long unit_to_ns)
{
    if (PyFloat_Check(obj)) {
        double d;
        d = PyFloat_AsDouble(obj);
        return _PyTime_FromFloatObject(t, d, round, unit_to_ns);
    }
    else {
        long long sec;
        Py_BUILD_ASSERT(sizeof(long long) <= sizeof(_PyTime_t));

        sec = PyLong_AsLongLong(obj);
        if (sec == -1 && PyErr_Occurred()) {
            if (PyErr_ExceptionMatches(PyExc_OverflowError))
                _PyTime_overflow();
            return -1;
        }

        if (_PyTime_check_mul_overflow(sec, unit_to_ns)) {
            _PyTime_overflow();
            return -1;
        }
        *t = sec * unit_to_ns;
        return 0;
    }
}
Пример #2
0
static int
_PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round,
                   long to_nanoseconds)
{
    if (PyFloat_Check(obj)) {
        double d;
        d = PyFloat_AsDouble(obj);
        return _PyTime_FromFloatObject(t, d, round, to_nanoseconds);
    }
    else {
#ifdef HAVE_LONG_LONG
        PY_LONG_LONG sec;
        sec = PyLong_AsLongLong(obj);
        assert(sizeof(PY_LONG_LONG) <= sizeof(_PyTime_t));
#else
        long sec;
        sec = PyLong_AsLong(obj);
        assert(sizeof(PY_LONG_LONG) <= sizeof(_PyTime_t));
#endif
        if (sec == -1 && PyErr_Occurred()) {
            if (PyErr_ExceptionMatches(PyExc_OverflowError))
                _PyTime_overflow();
            return -1;
        }
        *t = sec * to_nanoseconds;
        if (*t / to_nanoseconds != sec) {
            _PyTime_overflow();
            return -1;
        }
        return 0;
    }
}
Пример #3
0
static int
_PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round,
                   long to_nanoseconds)
{
    if (PyFloat_Check(obj)) {
        /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
        volatile double d, err;

        /* convert to a number of nanoseconds */
        d = PyFloat_AsDouble(obj);
        d *= to_nanoseconds;

        if (round == _PyTime_ROUND_CEILING)
            d = ceil(d);
        else
            d = floor(d);

        *t = (_PyTime_t)d;
        err = d - (double)*t;
        if (fabs(err) >= 1.0) {
            _PyTime_overflow();
            return -1;
        }
        return 0;
    }
    else {
#ifdef HAVE_LONG_LONG
        PY_LONG_LONG sec;
        sec = PyLong_AsLongLong(obj);
        assert(sizeof(PY_LONG_LONG) <= sizeof(_PyTime_t));
#else
        long sec;
        sec = PyLong_AsLong(obj);
        assert(sizeof(PY_LONG_LONG) <= sizeof(_PyTime_t));
#endif
        if (sec == -1 && PyErr_Occurred()) {
            if (PyErr_ExceptionMatches(PyExc_OverflowError))
                _PyTime_overflow();
            return -1;
        }
        *t = sec * to_nanoseconds;
        if (*t / to_nanoseconds != sec) {
            _PyTime_overflow();
            return -1;
        }
        return 0;
    }
}
Пример #4
0
static int
_PyTime_FromFloatObject(_PyTime_t *t, double value, _PyTime_round_t round,
                        long to_nanoseconds)
{
    double err;
    /* volatile avoids optimization changing how numbers are rounded */
    volatile double d;

    /* convert to a number of nanoseconds */
    d = value;
    d *= to_nanoseconds;

    if (round == _PyTime_ROUND_HALF_UP)
        d = _PyTime_RoundHalfUp(d);
    else if (round == _PyTime_ROUND_CEILING)
        d = ceil(d);
    else
        d = floor(d);

    *t = (_PyTime_t)d;
    err = d - (double)*t;
    if (fabs(err) >= 1.0) {
        _PyTime_overflow();
        return -1;
    }
    return 0;
}
Пример #5
0
static int
_PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise)
{
    _PyTime_t t;
    int res = 0;

    t = (_PyTime_t)tv->tv_sec * SEC_TO_NS;
    if (t / SEC_TO_NS != tv->tv_sec) {
        if (raise)
            _PyTime_overflow();
        res = -1;
    }

    t += (_PyTime_t)tv->tv_usec * US_TO_NS;

    *tp = t;
    return res;
}
Пример #6
0
static int
_PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts, int raise)
{
    _PyTime_t t;
    int res = 0;

    t = (_PyTime_t)ts->tv_sec * SEC_TO_NS;
    if (t / SEC_TO_NS != ts->tv_sec) {
        if (raise)
            _PyTime_overflow();
        res = -1;
    }

    t += ts->tv_nsec;

    *tp = t;
    return res;
}
Пример #7
0
static int
_PyTime_FromFloatObject(_PyTime_t *t, double value, _PyTime_round_t round,
                        long unit_to_ns)
{
    double err;
    /* volatile avoids optimization changing how numbers are rounded */
    volatile double d;

    /* convert to a number of nanoseconds */
    d = value;
    d *= (double)unit_to_ns;
    d = _PyTime_Round(d, round);

    *t = (_PyTime_t)d;
    err = d - (double)*t;
    if (fabs(err) >= 1.0) {
        _PyTime_overflow();
        return -1;
    }
    return 0;
}
Пример #8
0
static int
_PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise)
{
    _PyTime_t t;
    int res = 0;

    Py_BUILD_ASSERT(sizeof(tv->tv_sec) <= sizeof(_PyTime_t));
    t = (_PyTime_t)tv->tv_sec;

    if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
        if (raise)
            _PyTime_overflow();
        res = -1;
    }
    t = t * SEC_TO_NS;

    t += (_PyTime_t)tv->tv_usec * US_TO_NS;

    *tp = t;
    return res;
}
Пример #9
0
int
_PyTime_AsTimespec(_PyTime_t t, struct timespec *ts)
{
    _PyTime_t secs, nsec;

    secs = t / SEC_TO_NS;
    nsec = t % SEC_TO_NS;
    if (nsec < 0) {
        nsec += SEC_TO_NS;
        secs -= 1;
    }
    ts->tv_sec = (time_t)secs;
    assert(0 <= nsec && nsec < SEC_TO_NS);
    ts->tv_nsec = nsec;

    if ((_PyTime_t)ts->tv_sec != secs) {
        _PyTime_overflow();
        return -1;
    }
    return 0;
}
Пример #10
0
static int
pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
{
#if defined(MS_WINDOWS)
    ULONGLONG ticks;
    _PyTime_t t;

    assert(info == NULL || raise);

    ticks = GetTickCount64();
    Py_BUILD_ASSERT(sizeof(ticks) <= sizeof(_PyTime_t));
    t = (_PyTime_t)ticks;

    if (_PyTime_check_mul_overflow(t, MS_TO_NS)) {
        if (raise) {
            _PyTime_overflow();
            return -1;
        }
        /* Hello, time traveler! */
        assert(0);
    }
    *tp = t * MS_TO_NS;

    if (info) {
        DWORD timeAdjustment, timeIncrement;
        BOOL isTimeAdjustmentDisabled, ok;
        info->implementation = "GetTickCount64()";
        info->monotonic = 1;
        ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
                                     &isTimeAdjustmentDisabled);
        if (!ok) {
            PyErr_SetFromWindowsErr(0);
            return -1;
        }
        info->resolution = timeIncrement * 1e-7;
        info->adjustable = 0;
    }

#elif defined(__APPLE__)
    static mach_timebase_info_data_t timebase;
    uint64_t time;

    if (timebase.denom == 0) {
        /* 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);
    }

    time = mach_absolute_time();

    /* apply timebase factor */
    time *= timebase.numer;
    time /= timebase.denom;

    *tp = time;

    if (info) {
        info->implementation = "mach_absolute_time()";
        info->resolution = (double)timebase.numer / timebase.denom * 1e-9;
        info->monotonic = 1;
        info->adjustable = 0;
    }

#else
    struct timespec ts;
#ifdef CLOCK_HIGHRES
    const clockid_t clk_id = CLOCK_HIGHRES;
    const char *implementation = "clock_gettime(CLOCK_HIGHRES)";
#else
    const clockid_t clk_id = CLOCK_MONOTONIC;
    const char *implementation = "clock_gettime(CLOCK_MONOTONIC)";
#endif

    assert(info == NULL || raise);

    if (clock_gettime(clk_id, &ts) != 0) {
        if (raise) {
            PyErr_SetFromErrno(PyExc_OSError);
            return -1;
        }
        return -1;
    }

    if (info) {
        struct timespec res;
        info->monotonic = 1;
        info->implementation = implementation;
        info->adjustable = 0;
        if (clock_getres(clk_id, &res) != 0) {
            PyErr_SetFromErrno(PyExc_OSError);
            return -1;
        }
        info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
    }
    if (_PyTime_FromTimespec(tp, &ts, raise) < 0)
        return -1;
#endif
    return 0;
}
Пример #11
0
static int
_PyTime_AsTimeval_impl(_PyTime_t t, struct timeval *tv, _PyTime_round_t round,
                       int raise)
{
    const long k = US_TO_NS;
    _PyTime_t secs, ns;
    int res = 0;
    int usec;

    secs = t / SEC_TO_NS;
    ns = t % SEC_TO_NS;
    if (ns < 0) {
        ns += SEC_TO_NS;
        secs -= 1;
    }

#ifdef MS_WINDOWS
    /* On Windows, timeval.tv_sec is a long (32 bit),
       whereas time_t can be 64-bit. */
    assert(sizeof(tv->tv_sec) == sizeof(long));
#if SIZEOF_TIME_T > SIZEOF_LONG
    if (secs > LONG_MAX) {
        secs = LONG_MAX;
        res = -1;
    }
    else if (secs < LONG_MIN) {
        secs = LONG_MIN;
        res = -1;
    }
#endif
    tv->tv_sec = (long)secs;
#else
    /* On OpenBSD 5.4, timeval.tv_sec is a long.
       Example: long is 64-bit, whereas time_t is 32-bit. */
    tv->tv_sec = secs;
    if ((_PyTime_t)tv->tv_sec != secs)
        res = -1;
#endif

    if (round == _PyTime_ROUND_HALF_UP) {
        _PyTime_t r;
        usec = (int)(ns / k);
        r = ns % k;
        if (Py_ABS(r) >= k / 2) {
            if (ns >= 0)
                usec++;
            else
                usec--;
        }
    }
    else if (round == _PyTime_ROUND_CEILING)
        usec = (int)((ns + k - 1) / k);
    else
        usec = (int)(ns / k);

    if (usec >= SEC_TO_US) {
        usec -= SEC_TO_US;
        tv->tv_sec += 1;
    }

    assert(0 <= usec && usec < SEC_TO_US);
    tv->tv_usec = usec;

    if (res && raise)
        _PyTime_overflow();
    return res;
}