mirror of
https://github.com/python/cpython.git
synced 2025-07-23 19:25:40 +00:00
bpo-21302: Add _PyTime_AsNanoseconds() (GH-28350)
Refactor pytime.c: * Add pytime_from_nanoseconds() and pytime_as_nanoseconds(), and use explicitly these functions * Add two empty lines between functions * PEP 7: add braces { ... } * C99: declare variables where they are set * Rename private functions to lowercase * Rename error_time_t_overflow() to pytime_time_t_overflow() * Rename win_perf_counter_frequency() to py_win_perf_counter_frequency() * py_get_monotonic_clock(): add an assertion to detect overflow when mach_absolute_time() unsigned uint64_t is casted to _PyTime_t (signed int64_t). _testcapi: use _PyTime_FromNanoseconds().
This commit is contained in:
parent
40d2ac92f9
commit
b49263b698
4 changed files with 233 additions and 171 deletions
|
@ -111,6 +111,9 @@ PyAPI_FUNC(_PyTime_t) _PyTime_AsMilliseconds(_PyTime_t t,
|
||||||
PyAPI_FUNC(_PyTime_t) _PyTime_AsMicroseconds(_PyTime_t t,
|
PyAPI_FUNC(_PyTime_t) _PyTime_AsMicroseconds(_PyTime_t t,
|
||||||
_PyTime_round_t round);
|
_PyTime_round_t round);
|
||||||
|
|
||||||
|
/* Convert timestamp to a number of nanoseconds (10^-9 seconds). */
|
||||||
|
PyAPI_FUNC(_PyTime_t) _PyTime_AsNanoseconds(_PyTime_t t);
|
||||||
|
|
||||||
/* Convert timestamp to a number of nanoseconds (10^-9 seconds) as a Python int
|
/* Convert timestamp to a number of nanoseconds (10^-9 seconds) as a Python int
|
||||||
object. */
|
object. */
|
||||||
PyAPI_FUNC(PyObject *) _PyTime_AsNanosecondsObject(_PyTime_t t);
|
PyAPI_FUNC(PyObject *) _PyTime_AsNanosecondsObject(_PyTime_t t);
|
||||||
|
|
|
@ -4623,11 +4623,10 @@ static PyObject *
|
||||||
test_pytime_fromseconds(PyObject *self, PyObject *args)
|
test_pytime_fromseconds(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
int seconds;
|
int seconds;
|
||||||
_PyTime_t ts;
|
if (!PyArg_ParseTuple(args, "i", &seconds)) {
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "i", &seconds))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
ts = _PyTime_FromSeconds(seconds);
|
}
|
||||||
|
_PyTime_t ts = _PyTime_FromSeconds(seconds);
|
||||||
return _PyTime_AsNanosecondsObject(ts);
|
return _PyTime_AsNanosecondsObject(ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4636,14 +4635,16 @@ test_pytime_fromsecondsobject(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *obj;
|
PyObject *obj;
|
||||||
int round;
|
int round;
|
||||||
|
if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (check_time_rounding(round) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
_PyTime_t ts;
|
_PyTime_t ts;
|
||||||
|
if (_PyTime_FromSecondsObject(&ts, obj, round) == -1) {
|
||||||
if (!PyArg_ParseTuple(args, "Oi", &obj, &round))
|
|
||||||
return NULL;
|
|
||||||
if (check_time_rounding(round) < 0)
|
|
||||||
return NULL;
|
|
||||||
if (_PyTime_FromSecondsObject(&ts, obj, round) == -1)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
return _PyTime_AsNanosecondsObject(ts);
|
return _PyTime_AsNanosecondsObject(ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4651,16 +4652,14 @@ static PyObject *
|
||||||
test_pytime_assecondsdouble(PyObject *self, PyObject *args)
|
test_pytime_assecondsdouble(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *obj;
|
PyObject *obj;
|
||||||
_PyTime_t ts;
|
|
||||||
double d;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O", &obj)) {
|
if (!PyArg_ParseTuple(args, "O", &obj)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
_PyTime_t ts;
|
||||||
if (_PyTime_FromNanosecondsObject(&ts, obj) < 0) {
|
if (_PyTime_FromNanosecondsObject(&ts, obj) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
d = _PyTime_AsSecondsDouble(ts);
|
double d = _PyTime_AsSecondsDouble(ts);
|
||||||
return PyFloat_FromDouble(d);
|
return PyFloat_FromDouble(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4669,23 +4668,22 @@ test_PyTime_AsTimeval(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *obj;
|
PyObject *obj;
|
||||||
int round;
|
int round;
|
||||||
_PyTime_t t;
|
if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
|
||||||
struct timeval tv;
|
|
||||||
PyObject *seconds;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "Oi", &obj, &round))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
if (check_time_rounding(round) < 0) {
|
if (check_time_rounding(round) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
_PyTime_t t;
|
||||||
if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
|
if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
struct timeval tv;
|
||||||
if (_PyTime_AsTimeval(t, &tv, round) < 0) {
|
if (_PyTime_AsTimeval(t, &tv, round) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
seconds = PyLong_FromLongLong(tv.tv_sec);
|
PyObject *seconds = PyLong_FromLongLong(tv.tv_sec);
|
||||||
if (seconds == NULL) {
|
if (seconds == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -4697,15 +4695,14 @@ static PyObject *
|
||||||
test_PyTime_AsTimespec(PyObject *self, PyObject *args)
|
test_PyTime_AsTimespec(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *obj;
|
PyObject *obj;
|
||||||
_PyTime_t t;
|
|
||||||
struct timespec ts;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O", &obj)) {
|
if (!PyArg_ParseTuple(args, "O", &obj)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
_PyTime_t t;
|
||||||
if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
|
if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
struct timespec ts;
|
||||||
if (_PyTime_AsTimespec(t, &ts) == -1) {
|
if (_PyTime_AsTimespec(t, &ts) == -1) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -4718,21 +4715,19 @@ test_PyTime_AsMilliseconds(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *obj;
|
PyObject *obj;
|
||||||
int round;
|
int round;
|
||||||
_PyTime_t t, ms;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
|
if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
_PyTime_t t;
|
||||||
if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
|
if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (check_time_rounding(round) < 0) {
|
if (check_time_rounding(round) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ms = _PyTime_AsMilliseconds(t, round);
|
_PyTime_t ms = _PyTime_AsMilliseconds(t, round);
|
||||||
/* This conversion rely on the fact that _PyTime_t is a number of
|
_PyTime_t ns = _PyTime_FromNanoseconds(ms);
|
||||||
nanoseconds */
|
return _PyTime_AsNanosecondsObject(ns);
|
||||||
return _PyTime_AsNanosecondsObject(ms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -4740,20 +4735,19 @@ test_PyTime_AsMicroseconds(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *obj;
|
PyObject *obj;
|
||||||
int round;
|
int round;
|
||||||
_PyTime_t t, ms;
|
if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "Oi", &obj, &round))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
_PyTime_t t;
|
||||||
if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
|
if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (check_time_rounding(round) < 0) {
|
if (check_time_rounding(round) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ms = _PyTime_AsMicroseconds(t, round);
|
_PyTime_t us = _PyTime_AsMicroseconds(t, round);
|
||||||
/* This conversion rely on the fact that _PyTime_t is a number of
|
_PyTime_t ns = _PyTime_FromNanoseconds(us);
|
||||||
nanoseconds */
|
return _PyTime_AsNanosecondsObject(ns);
|
||||||
return _PyTime_AsNanosecondsObject(ms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
|
|
|
@ -128,12 +128,11 @@ static int
|
||||||
_PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
_PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
||||||
{
|
{
|
||||||
static int initialized = 0;
|
static int initialized = 0;
|
||||||
clock_t ticks;
|
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
|
|
||||||
/* must sure that _PyTime_MulDiv(ticks, SEC_TO_NS, CLOCKS_PER_SEC)
|
/* Make sure that _PyTime_MulDiv(ticks, SEC_TO_NS, CLOCKS_PER_SEC)
|
||||||
above cannot overflow */
|
above cannot overflow */
|
||||||
if ((_PyTime_t)CLOCKS_PER_SEC > _PyTime_MAX / SEC_TO_NS) {
|
if ((_PyTime_t)CLOCKS_PER_SEC > _PyTime_MAX / SEC_TO_NS) {
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
@ -149,14 +148,15 @@ _PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
||||||
info->adjustable = 0;
|
info->adjustable = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ticks = clock();
|
clock_t ticks = clock();
|
||||||
if (ticks == (clock_t)-1) {
|
if (ticks == (clock_t)-1) {
|
||||||
PyErr_SetString(PyExc_RuntimeError,
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
"the processor time used is not available "
|
"the processor time used is not available "
|
||||||
"or its value cannot be represented");
|
"or its value cannot be represented");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*tp = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)CLOCKS_PER_SEC);
|
_PyTime_t ns = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)CLOCKS_PER_SEC);
|
||||||
|
*tp = _PyTime_FromNanoseconds(ns);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_CLOCK */
|
#endif /* HAVE_CLOCK */
|
||||||
|
@ -1325,10 +1325,10 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
||||||
info->resolution = 1.0 / (double)ticks_per_second;
|
info->resolution = 1.0 / (double)ticks_per_second;
|
||||||
}
|
}
|
||||||
|
|
||||||
_PyTime_t total;
|
_PyTime_t ns;
|
||||||
total = _PyTime_MulDiv(t.tms_utime, SEC_TO_NS, ticks_per_second);
|
ns = _PyTime_MulDiv(t.tms_utime, SEC_TO_NS, ticks_per_second);
|
||||||
total += _PyTime_MulDiv(t.tms_stime, SEC_TO_NS, ticks_per_second);
|
ns += _PyTime_MulDiv(t.tms_stime, SEC_TO_NS, ticks_per_second);
|
||||||
*tp = total;
|
*tp = _PyTime_FromNanoseconds(ns);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
319
Python/pytime.c
319
Python/pytime.c
|
@ -34,21 +34,39 @@
|
||||||
#define NS_TO_MS (1000 * 1000)
|
#define NS_TO_MS (1000 * 1000)
|
||||||
#define NS_TO_US (1000)
|
#define NS_TO_US (1000)
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
error_time_t_overflow(void)
|
pytime_time_t_overflow(void)
|
||||||
{
|
{
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"timestamp out of range for platform time_t");
|
"timestamp out of range for platform time_t");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_PyTime_overflow(void)
|
pytime_overflow(void)
|
||||||
{
|
{
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"timestamp too large to convert to C _PyTime_t");
|
"timestamp too large to convert to C _PyTime_t");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline _PyTime_t
|
||||||
|
pytime_from_nanoseconds(_PyTime_t t)
|
||||||
|
{
|
||||||
|
// _PyTime_t is a number of nanoseconds
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline _PyTime_t
|
||||||
|
pytime_as_nanoseconds(_PyTime_t t)
|
||||||
|
{
|
||||||
|
// _PyTime_t is a number of nanoseconds
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
_PyTime_t
|
_PyTime_t
|
||||||
_PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, _PyTime_t div)
|
_PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, _PyTime_t div)
|
||||||
{
|
{
|
||||||
|
@ -80,13 +98,14 @@ _PyLong_AsTime_t(PyObject *obj)
|
||||||
#endif
|
#endif
|
||||||
if (val == -1 && PyErr_Occurred()) {
|
if (val == -1 && PyErr_Occurred()) {
|
||||||
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
||||||
error_time_t_overflow();
|
pytime_time_t_overflow();
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return (time_t)val;
|
return (time_t)val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyLong_FromTime_t(time_t t)
|
_PyLong_FromTime_t(time_t t)
|
||||||
{
|
{
|
||||||
|
@ -98,28 +117,30 @@ _PyLong_FromTime_t(time_t t)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Round to nearest with ties going to nearest even integer
|
/* Round to nearest with ties going to nearest even integer
|
||||||
(_PyTime_ROUND_HALF_EVEN) */
|
(_PyTime_ROUND_HALF_EVEN) */
|
||||||
static double
|
static double
|
||||||
_PyTime_RoundHalfEven(double x)
|
pytime_round_half_even(double x)
|
||||||
{
|
{
|
||||||
double rounded = round(x);
|
double rounded = round(x);
|
||||||
if (fabs(x-rounded) == 0.5) {
|
if (fabs(x-rounded) == 0.5) {
|
||||||
/* halfway case: round to even */
|
/* halfway case: round to even */
|
||||||
rounded = 2.0*round(x/2.0);
|
rounded = 2.0 * round(x / 2.0);
|
||||||
}
|
}
|
||||||
return rounded;
|
return rounded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static double
|
static double
|
||||||
_PyTime_Round(double x, _PyTime_round_t round)
|
pytime_round(double x, _PyTime_round_t round)
|
||||||
{
|
{
|
||||||
/* volatile avoids optimization changing how numbers are rounded */
|
/* volatile avoids optimization changing how numbers are rounded */
|
||||||
volatile double d;
|
volatile double d;
|
||||||
|
|
||||||
d = x;
|
d = x;
|
||||||
if (round == _PyTime_ROUND_HALF_EVEN) {
|
if (round == _PyTime_ROUND_HALF_EVEN) {
|
||||||
d = _PyTime_RoundHalfEven(d);
|
d = pytime_round_half_even(d);
|
||||||
}
|
}
|
||||||
else if (round == _PyTime_ROUND_CEILING) {
|
else if (round == _PyTime_ROUND_CEILING) {
|
||||||
d = ceil(d);
|
d = ceil(d);
|
||||||
|
@ -134,9 +155,10 @@ _PyTime_Round(double x, _PyTime_round_t round)
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator,
|
pytime_double_to_denominator(double d, time_t *sec, long *numerator,
|
||||||
long idenominator, _PyTime_round_t round)
|
long idenominator, _PyTime_round_t round)
|
||||||
{
|
{
|
||||||
double denominator = (double)idenominator;
|
double denominator = (double)idenominator;
|
||||||
double intpart;
|
double intpart;
|
||||||
|
@ -146,7 +168,7 @@ _PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator,
|
||||||
floatpart = modf(d, &intpart);
|
floatpart = modf(d, &intpart);
|
||||||
|
|
||||||
floatpart *= denominator;
|
floatpart *= denominator;
|
||||||
floatpart = _PyTime_Round(floatpart, round);
|
floatpart = pytime_round(floatpart, round);
|
||||||
if (floatpart >= denominator) {
|
if (floatpart >= denominator) {
|
||||||
floatpart -= denominator;
|
floatpart -= denominator;
|
||||||
intpart += 1.0;
|
intpart += 1.0;
|
||||||
|
@ -158,7 +180,7 @@ _PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator,
|
||||||
assert(0.0 <= floatpart && floatpart < denominator);
|
assert(0.0 <= floatpart && floatpart < denominator);
|
||||||
|
|
||||||
if (!_Py_InIntegralTypeRange(time_t, intpart)) {
|
if (!_Py_InIntegralTypeRange(time_t, intpart)) {
|
||||||
error_time_t_overflow();
|
pytime_time_t_overflow();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*sec = (time_t)intpart;
|
*sec = (time_t)intpart;
|
||||||
|
@ -167,9 +189,10 @@ _PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
|
pytime_object_to_denominator(PyObject *obj, time_t *sec, long *numerator,
|
||||||
long denominator, _PyTime_round_t round)
|
long denominator, _PyTime_round_t round)
|
||||||
{
|
{
|
||||||
assert(denominator >= 1);
|
assert(denominator >= 1);
|
||||||
|
|
||||||
|
@ -180,8 +203,8 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
|
||||||
PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
|
PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return _PyTime_DoubleToDenominator(d, sec, numerator,
|
return pytime_double_to_denominator(d, sec, numerator,
|
||||||
denominator, round);
|
denominator, round);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*sec = _PyLong_AsTime_t(obj);
|
*sec = _PyLong_AsTime_t(obj);
|
||||||
|
@ -193,6 +216,7 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
|
_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
|
||||||
{
|
{
|
||||||
|
@ -207,11 +231,11 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
d = _PyTime_Round(d, round);
|
d = pytime_round(d, round);
|
||||||
(void)modf(d, &intpart);
|
(void)modf(d, &intpart);
|
||||||
|
|
||||||
if (!_Py_InIntegralTypeRange(time_t, intpart)) {
|
if (!_Py_InIntegralTypeRange(time_t, intpart)) {
|
||||||
error_time_t_overflow();
|
pytime_time_t_overflow();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*sec = (time_t)intpart;
|
*sec = (time_t)intpart;
|
||||||
|
@ -226,49 +250,50 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
|
_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
|
||||||
_PyTime_round_t round)
|
_PyTime_round_t round)
|
||||||
{
|
{
|
||||||
return _PyTime_ObjectToDenominator(obj, sec, nsec, SEC_TO_NS, round);
|
return pytime_object_to_denominator(obj, sec, nsec, SEC_TO_NS, round);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
|
_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
|
||||||
_PyTime_round_t round)
|
_PyTime_round_t round)
|
||||||
{
|
{
|
||||||
return _PyTime_ObjectToDenominator(obj, sec, usec, SEC_TO_US, round);
|
return pytime_object_to_denominator(obj, sec, usec, SEC_TO_US, round);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_PyTime_t
|
_PyTime_t
|
||||||
_PyTime_FromSeconds(int seconds)
|
_PyTime_FromSeconds(int seconds)
|
||||||
{
|
{
|
||||||
_PyTime_t t;
|
|
||||||
/* ensure that integer overflow cannot happen, int type should have 32
|
/* ensure that integer overflow cannot happen, int type should have 32
|
||||||
bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_MS takes 30
|
bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_MS takes 30
|
||||||
bits). */
|
bits). */
|
||||||
Py_BUILD_ASSERT(INT_MAX <= _PyTime_MAX / SEC_TO_NS);
|
Py_BUILD_ASSERT(INT_MAX <= _PyTime_MAX / SEC_TO_NS);
|
||||||
Py_BUILD_ASSERT(INT_MIN >= _PyTime_MIN / SEC_TO_NS);
|
Py_BUILD_ASSERT(INT_MIN >= _PyTime_MIN / SEC_TO_NS);
|
||||||
|
|
||||||
t = (_PyTime_t)seconds;
|
_PyTime_t t = (_PyTime_t)seconds;
|
||||||
assert((t >= 0 && t <= _PyTime_MAX / SEC_TO_NS)
|
assert((t >= 0 && t <= _PyTime_MAX / SEC_TO_NS)
|
||||||
|| (t < 0 && t >= _PyTime_MIN / SEC_TO_NS));
|
|| (t < 0 && t >= _PyTime_MIN / SEC_TO_NS));
|
||||||
t *= SEC_TO_NS;
|
t *= SEC_TO_NS;
|
||||||
return t;
|
return pytime_from_nanoseconds(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_PyTime_t
|
_PyTime_t
|
||||||
_PyTime_FromNanoseconds(_PyTime_t ns)
|
_PyTime_FromNanoseconds(_PyTime_t ns)
|
||||||
{
|
{
|
||||||
/* _PyTime_t already uses nanosecond resolution, no conversion needed */
|
return pytime_from_nanoseconds(ns);
|
||||||
return ns;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj)
|
_PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj)
|
||||||
{
|
{
|
||||||
long long nsec;
|
|
||||||
_PyTime_t t;
|
|
||||||
|
|
||||||
if (!PyLong_Check(obj)) {
|
if (!PyLong_Check(obj)) {
|
||||||
PyErr_Format(PyExc_TypeError, "expect int, got %s",
|
PyErr_Format(PyExc_TypeError, "expect int, got %s",
|
||||||
|
@ -277,25 +302,25 @@ _PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_BUILD_ASSERT(sizeof(long long) == sizeof(_PyTime_t));
|
Py_BUILD_ASSERT(sizeof(long long) == sizeof(_PyTime_t));
|
||||||
nsec = PyLong_AsLongLong(obj);
|
long long nsec = PyLong_AsLongLong(obj);
|
||||||
if (nsec == -1 && PyErr_Occurred()) {
|
if (nsec == -1 && PyErr_Occurred()) {
|
||||||
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
||||||
_PyTime_overflow();
|
pytime_overflow();
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _PyTime_t already uses nanosecond resolution, no conversion needed */
|
_PyTime_t t = (_PyTime_t)nsec;
|
||||||
t = (_PyTime_t)nsec;
|
*tp = pytime_from_nanoseconds(t);
|
||||||
*tp = t;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_CLOCK_GETTIME
|
#ifdef HAVE_CLOCK_GETTIME
|
||||||
static int
|
static int
|
||||||
pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise)
|
pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise)
|
||||||
{
|
{
|
||||||
_PyTime_t t, nsec;
|
_PyTime_t t, tv_nsec;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
Py_BUILD_ASSERT(sizeof(ts->tv_sec) <= sizeof(_PyTime_t));
|
Py_BUILD_ASSERT(sizeof(ts->tv_sec) <= sizeof(_PyTime_t));
|
||||||
|
@ -303,7 +328,7 @@ pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise)
|
||||||
|
|
||||||
if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
|
if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
|
||||||
if (raise) {
|
if (raise) {
|
||||||
_PyTime_overflow();
|
pytime_overflow();
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
t = (t > 0) ? _PyTime_MAX : _PyTime_MIN;
|
t = (t > 0) ? _PyTime_MAX : _PyTime_MIN;
|
||||||
|
@ -312,21 +337,21 @@ pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise)
|
||||||
t = t * SEC_TO_NS;
|
t = t * SEC_TO_NS;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsec = ts->tv_nsec;
|
tv_nsec = ts->tv_nsec;
|
||||||
/* The following test is written for positive only nsec */
|
/* The following test is written for positive only tv_nsec */
|
||||||
assert(nsec >= 0);
|
assert(tv_nsec >= 0);
|
||||||
if (t > _PyTime_MAX - nsec) {
|
if (t > _PyTime_MAX - tv_nsec) {
|
||||||
if (raise) {
|
if (raise) {
|
||||||
_PyTime_overflow();
|
pytime_overflow();
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
t = _PyTime_MAX;
|
t = _PyTime_MAX;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
t += nsec;
|
t += tv_nsec;
|
||||||
}
|
}
|
||||||
|
|
||||||
*tp = t;
|
*tp = pytime_from_nanoseconds(t);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,6 +362,7 @@ _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if !defined(MS_WINDOWS)
|
#if !defined(MS_WINDOWS)
|
||||||
static int
|
static int
|
||||||
pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise)
|
pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise)
|
||||||
|
@ -349,7 +375,7 @@ pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise)
|
||||||
|
|
||||||
if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
|
if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
|
||||||
if (raise) {
|
if (raise) {
|
||||||
_PyTime_overflow();
|
pytime_overflow();
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
t = (t > 0) ? _PyTime_MAX : _PyTime_MIN;
|
t = (t > 0) ? _PyTime_MAX : _PyTime_MIN;
|
||||||
|
@ -363,7 +389,7 @@ pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise)
|
||||||
assert(usec >= 0);
|
assert(usec >= 0);
|
||||||
if (t > _PyTime_MAX - usec) {
|
if (t > _PyTime_MAX - usec) {
|
||||||
if (raise) {
|
if (raise) {
|
||||||
_PyTime_overflow();
|
pytime_overflow();
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
t = _PyTime_MAX;
|
t = _PyTime_MAX;
|
||||||
|
@ -372,10 +398,11 @@ pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise)
|
||||||
t += usec;
|
t += usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
*tp = t;
|
*tp = pytime_from_nanoseconds(t);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv)
|
_PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv)
|
||||||
{
|
{
|
||||||
|
@ -383,8 +410,9 @@ _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_PyTime_FromDouble(_PyTime_t *t, double value, _PyTime_round_t round,
|
pytime_from_double(_PyTime_t *tp, double value, _PyTime_round_t round,
|
||||||
long unit_to_ns)
|
long unit_to_ns)
|
||||||
{
|
{
|
||||||
/* volatile avoids optimization changing how numbers are rounded */
|
/* volatile avoids optimization changing how numbers are rounded */
|
||||||
|
@ -393,18 +421,21 @@ _PyTime_FromDouble(_PyTime_t *t, double value, _PyTime_round_t round,
|
||||||
/* convert to a number of nanoseconds */
|
/* convert to a number of nanoseconds */
|
||||||
d = value;
|
d = value;
|
||||||
d *= (double)unit_to_ns;
|
d *= (double)unit_to_ns;
|
||||||
d = _PyTime_Round(d, round);
|
d = pytime_round(d, round);
|
||||||
|
|
||||||
if (!_Py_InIntegralTypeRange(_PyTime_t, d)) {
|
if (!_Py_InIntegralTypeRange(_PyTime_t, d)) {
|
||||||
_PyTime_overflow();
|
pytime_overflow();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*t = (_PyTime_t)d;
|
_PyTime_t ns = (_PyTime_t)d;
|
||||||
|
|
||||||
|
*tp = pytime_from_nanoseconds(ns);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round,
|
pytime_from_object(_PyTime_t *tp, PyObject *obj, _PyTime_round_t round,
|
||||||
long unit_to_ns)
|
long unit_to_ns)
|
||||||
{
|
{
|
||||||
if (PyFloat_Check(obj)) {
|
if (PyFloat_Check(obj)) {
|
||||||
|
@ -414,71 +445,77 @@ _PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round,
|
||||||
PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
|
PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return _PyTime_FromDouble(t, d, round, unit_to_ns);
|
return pytime_from_double(tp, d, round, unit_to_ns);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
long long sec;
|
|
||||||
Py_BUILD_ASSERT(sizeof(long long) <= sizeof(_PyTime_t));
|
Py_BUILD_ASSERT(sizeof(long long) <= sizeof(_PyTime_t));
|
||||||
|
long long sec = PyLong_AsLongLong(obj);
|
||||||
sec = PyLong_AsLongLong(obj);
|
|
||||||
if (sec == -1 && PyErr_Occurred()) {
|
if (sec == -1 && PyErr_Occurred()) {
|
||||||
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
||||||
_PyTime_overflow();
|
pytime_overflow();
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_PyTime_check_mul_overflow(sec, unit_to_ns)) {
|
if (_PyTime_check_mul_overflow(sec, unit_to_ns)) {
|
||||||
_PyTime_overflow();
|
pytime_overflow();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*t = sec * unit_to_ns;
|
_PyTime_t ns = sec * unit_to_ns;
|
||||||
|
|
||||||
|
*tp = pytime_from_nanoseconds(ns);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
_PyTime_FromSecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round)
|
|
||||||
{
|
|
||||||
return _PyTime_FromObject(t, obj, round, SEC_TO_NS);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_FromMillisecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round)
|
_PyTime_FromSecondsObject(_PyTime_t *tp, PyObject *obj, _PyTime_round_t round)
|
||||||
{
|
{
|
||||||
return _PyTime_FromObject(t, obj, round, MS_TO_NS);
|
return pytime_from_object(tp, obj, round, SEC_TO_NS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyTime_FromMillisecondsObject(_PyTime_t *tp, PyObject *obj, _PyTime_round_t round)
|
||||||
|
{
|
||||||
|
return pytime_from_object(tp, obj, round, MS_TO_NS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
double
|
double
|
||||||
_PyTime_AsSecondsDouble(_PyTime_t t)
|
_PyTime_AsSecondsDouble(_PyTime_t t)
|
||||||
{
|
{
|
||||||
/* volatile avoids optimization changing how numbers are rounded */
|
/* volatile avoids optimization changing how numbers are rounded */
|
||||||
volatile double d;
|
volatile double d;
|
||||||
|
|
||||||
if (t % SEC_TO_NS == 0) {
|
_PyTime_t ns = pytime_as_nanoseconds(t);
|
||||||
_PyTime_t secs;
|
if (ns % SEC_TO_NS == 0) {
|
||||||
/* Divide using integers to avoid rounding issues on the integer part.
|
/* Divide using integers to avoid rounding issues on the integer part.
|
||||||
1e-9 cannot be stored exactly in IEEE 64-bit. */
|
1e-9 cannot be stored exactly in IEEE 64-bit. */
|
||||||
secs = t / SEC_TO_NS;
|
_PyTime_t secs = ns / SEC_TO_NS;
|
||||||
d = (double)secs;
|
d = (double)secs;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
d = (double)t;
|
d = (double)ns;
|
||||||
d /= 1e9;
|
d /= 1e9;
|
||||||
}
|
}
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyTime_AsNanosecondsObject(_PyTime_t t)
|
_PyTime_AsNanosecondsObject(_PyTime_t t)
|
||||||
{
|
{
|
||||||
|
_PyTime_t ns = pytime_as_nanoseconds(t);
|
||||||
Py_BUILD_ASSERT(sizeof(long long) >= sizeof(_PyTime_t));
|
Py_BUILD_ASSERT(sizeof(long long) >= sizeof(_PyTime_t));
|
||||||
return PyLong_FromLongLong((long long)t);
|
return PyLong_FromLongLong((long long)ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static _PyTime_t
|
static _PyTime_t
|
||||||
_PyTime_Divide(const _PyTime_t t, const _PyTime_t k,
|
pytime_divide(const _PyTime_t t, const _PyTime_t k,
|
||||||
const _PyTime_round_t round)
|
const _PyTime_round_t round)
|
||||||
{
|
{
|
||||||
assert(k > 1);
|
assert(k > 1);
|
||||||
if (round == _PyTime_ROUND_HALF_EVEN) {
|
if (round == _PyTime_ROUND_HALF_EVEN) {
|
||||||
|
@ -523,66 +560,77 @@ _PyTime_Divide(const _PyTime_t t, const _PyTime_t k,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_PyTime_t
|
_PyTime_t
|
||||||
_PyTime_AsMilliseconds(_PyTime_t t, _PyTime_round_t round)
|
_PyTime_AsNanoseconds(_PyTime_t t)
|
||||||
{
|
{
|
||||||
return _PyTime_Divide(t, NS_TO_MS, round);
|
return pytime_as_nanoseconds(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_PyTime_t
|
_PyTime_t
|
||||||
_PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round)
|
_PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round)
|
||||||
{
|
{
|
||||||
return _PyTime_Divide(t, NS_TO_US, round);
|
_PyTime_t ns = pytime_as_nanoseconds(t);
|
||||||
|
return pytime_divide(ns, NS_TO_US, round);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
_PyTime_AsTimeval_impl(_PyTime_t t, _PyTime_t *p_secs, int *p_us,
|
_PyTime_t
|
||||||
_PyTime_round_t round)
|
_PyTime_AsMilliseconds(_PyTime_t t, _PyTime_round_t round)
|
||||||
{
|
{
|
||||||
_PyTime_t secs, ns;
|
_PyTime_t ns = pytime_as_nanoseconds(t);
|
||||||
int usec;
|
return pytime_divide(ns, NS_TO_MS, round);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
pytime_as_timeval(_PyTime_t t, _PyTime_t *p_secs, int *p_us,
|
||||||
|
_PyTime_round_t round)
|
||||||
|
{
|
||||||
|
_PyTime_t ns, tv_sec;
|
||||||
|
ns = pytime_as_nanoseconds(t);
|
||||||
|
tv_sec = ns / SEC_TO_NS;
|
||||||
|
ns = ns % SEC_TO_NS;
|
||||||
|
|
||||||
|
int tv_usec = (int)pytime_divide(ns, US_TO_NS, round);
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
if (tv_usec < 0) {
|
||||||
secs = t / SEC_TO_NS;
|
tv_usec += SEC_TO_US;
|
||||||
ns = t % SEC_TO_NS;
|
if (tv_sec != _PyTime_MIN) {
|
||||||
|
tv_sec -= 1;
|
||||||
usec = (int)_PyTime_Divide(ns, US_TO_NS, round);
|
|
||||||
if (usec < 0) {
|
|
||||||
usec += SEC_TO_US;
|
|
||||||
if (secs != _PyTime_MIN) {
|
|
||||||
secs -= 1;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (usec >= SEC_TO_US) {
|
else if (tv_usec >= SEC_TO_US) {
|
||||||
usec -= SEC_TO_US;
|
tv_usec -= SEC_TO_US;
|
||||||
if (secs != _PyTime_MAX) {
|
if (tv_sec != _PyTime_MAX) {
|
||||||
secs += 1;
|
tv_sec += 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(0 <= usec && usec < SEC_TO_US);
|
assert(0 <= tv_usec && tv_usec < SEC_TO_US);
|
||||||
|
|
||||||
*p_secs = secs;
|
*p_secs = tv_sec;
|
||||||
*p_us = usec;
|
*p_us = tv_usec;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_PyTime_AsTimevalStruct_impl(_PyTime_t t, struct timeval *tv,
|
pytime_as_timeval_struct(_PyTime_t t, struct timeval *tv,
|
||||||
_PyTime_round_t round, int raise)
|
_PyTime_round_t round, int raise)
|
||||||
{
|
{
|
||||||
_PyTime_t secs, secs2;
|
_PyTime_t secs, secs2;
|
||||||
int us;
|
int us;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
res = _PyTime_AsTimeval_impl(t, &secs, &us, round);
|
res = pytime_as_timeval(t, &secs, &us, round);
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
tv->tv_sec = (long)secs;
|
tv->tv_sec = (long)secs;
|
||||||
#else
|
#else
|
||||||
|
@ -593,38 +641,39 @@ _PyTime_AsTimevalStruct_impl(_PyTime_t t, struct timeval *tv,
|
||||||
secs2 = (_PyTime_t)tv->tv_sec;
|
secs2 = (_PyTime_t)tv->tv_sec;
|
||||||
if (res < 0 || secs2 != secs) {
|
if (res < 0 || secs2 != secs) {
|
||||||
if (raise) {
|
if (raise) {
|
||||||
error_time_t_overflow();
|
pytime_time_t_overflow();
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
|
_PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
|
||||||
{
|
{
|
||||||
return _PyTime_AsTimevalStruct_impl(t, tv, round, 1);
|
return pytime_as_timeval_struct(t, tv, round, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_AsTimeval_noraise(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
|
_PyTime_AsTimeval_noraise(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
|
||||||
{
|
{
|
||||||
return _PyTime_AsTimevalStruct_impl(t, tv, round, 0);
|
return pytime_as_timeval_struct(t, tv, round, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_AsTimevalTime_t(_PyTime_t t, time_t *p_secs, int *us,
|
_PyTime_AsTimevalTime_t(_PyTime_t t, time_t *p_secs, int *us,
|
||||||
_PyTime_round_t round)
|
_PyTime_round_t round)
|
||||||
{
|
{
|
||||||
_PyTime_t secs;
|
_PyTime_t secs;
|
||||||
int res;
|
int res = pytime_as_timeval(t, &secs, us, round);
|
||||||
|
|
||||||
res = _PyTime_AsTimeval_impl(t, &secs, us, round);
|
*p_secs = (time_t)secs;
|
||||||
|
|
||||||
*p_secs = secs;
|
|
||||||
|
|
||||||
if (res < 0 || (_PyTime_t)*p_secs != secs) {
|
if (res < 0 || (_PyTime_t)*p_secs != secs) {
|
||||||
error_time_t_overflow();
|
pytime_time_t_overflow();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -635,26 +684,28 @@ _PyTime_AsTimevalTime_t(_PyTime_t t, time_t *p_secs, int *us,
|
||||||
int
|
int
|
||||||
_PyTime_AsTimespec(_PyTime_t t, struct timespec *ts)
|
_PyTime_AsTimespec(_PyTime_t t, struct timespec *ts)
|
||||||
{
|
{
|
||||||
_PyTime_t secs, nsec;
|
_PyTime_t tv_sec, tv_nsec;
|
||||||
|
|
||||||
secs = t / SEC_TO_NS;
|
_PyTime_t ns = pytime_as_nanoseconds(t);
|
||||||
nsec = t % SEC_TO_NS;
|
tv_sec = ns / SEC_TO_NS;
|
||||||
if (nsec < 0) {
|
tv_nsec = ns % SEC_TO_NS;
|
||||||
nsec += SEC_TO_NS;
|
if (tv_nsec < 0) {
|
||||||
secs -= 1;
|
tv_nsec += SEC_TO_NS;
|
||||||
|
tv_sec -= 1;
|
||||||
}
|
}
|
||||||
ts->tv_sec = (time_t)secs;
|
ts->tv_sec = (time_t)tv_sec;
|
||||||
assert(0 <= nsec && nsec < SEC_TO_NS);
|
assert(0 <= tv_nsec && tv_nsec < SEC_TO_NS);
|
||||||
ts->tv_nsec = nsec;
|
ts->tv_nsec = tv_nsec;
|
||||||
|
|
||||||
if ((_PyTime_t)ts->tv_sec != secs) {
|
if ((_PyTime_t)ts->tv_sec != tv_sec) {
|
||||||
error_time_t_overflow();
|
pytime_time_t_overflow();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
py_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
py_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
{
|
{
|
||||||
|
@ -670,7 +721,8 @@ py_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
/* 11,644,473,600,000,000,000: number of nanoseconds between
|
/* 11,644,473,600,000,000,000: number of nanoseconds between
|
||||||
the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
|
the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
|
||||||
days). */
|
days). */
|
||||||
*tp = large.QuadPart * 100 - 11644473600000000000;
|
_PyTime_t ns = large.QuadPart * 100 - 11644473600000000000;
|
||||||
|
*tp = pytime_from_nanoseconds(ns);
|
||||||
if (info) {
|
if (info) {
|
||||||
DWORD timeAdjustment, timeIncrement;
|
DWORD timeAdjustment, timeIncrement;
|
||||||
BOOL isTimeAdjustmentDisabled, ok;
|
BOOL isTimeAdjustmentDisabled, ok;
|
||||||
|
@ -730,7 +782,8 @@ py_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_CLOCK_GETTIME_RUNTIME
|
#ifdef HAVE_CLOCK_GETTIME_RUNTIME
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -765,6 +818,7 @@ py_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_PyTime_t
|
_PyTime_t
|
||||||
_PyTime_GetSystemClock(void)
|
_PyTime_GetSystemClock(void)
|
||||||
{
|
{
|
||||||
|
@ -777,12 +831,14 @@ _PyTime_GetSystemClock(void)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
|
_PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
|
||||||
{
|
{
|
||||||
return py_get_system_clock(t, info, 1);
|
return py_get_system_clock(t, info, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
static int
|
static int
|
||||||
py_mach_timebase_info(_PyTime_t *pnumer, _PyTime_t *pdenom, int raise)
|
py_mach_timebase_info(_PyTime_t *pnumer, _PyTime_t *pdenom, int raise)
|
||||||
|
@ -848,7 +904,7 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
|
|
||||||
if (_PyTime_check_mul_overflow(t, MS_TO_NS)) {
|
if (_PyTime_check_mul_overflow(t, MS_TO_NS)) {
|
||||||
if (raise) {
|
if (raise) {
|
||||||
_PyTime_overflow();
|
pytime_overflow();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// Truncate to _PyTime_MAX silently.
|
// Truncate to _PyTime_MAX silently.
|
||||||
|
@ -889,8 +945,13 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
info->adjustable = 0;
|
info->adjustable = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t ticks = mach_absolute_time();
|
uint64_t uticks = mach_absolute_time();
|
||||||
*tp = _PyTime_MulDiv((_PyTime_t)ticks, timebase_numer, timebase_denom);
|
// unsigned => signed
|
||||||
|
assert(uticks <= (uint64_t)_PyTime_MAX);
|
||||||
|
_PyTime_t ticks = (_PyTime_t)uticks;
|
||||||
|
|
||||||
|
_PyTime_t ns = _PyTime_MulDiv(ticks, timebase_numer, timebase_denom);
|
||||||
|
*tp = pytime_from_nanoseconds(ns);
|
||||||
|
|
||||||
#elif defined(__hpux)
|
#elif defined(__hpux)
|
||||||
hrtime_t time;
|
hrtime_t time;
|
||||||
|
@ -903,7 +964,7 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*tp = time;
|
*tp = pytime_from_nanoseconds(time);
|
||||||
|
|
||||||
if (info) {
|
if (info) {
|
||||||
info->implementation = "gethrtime()";
|
info->implementation = "gethrtime()";
|
||||||
|
@ -950,6 +1011,7 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_PyTime_t
|
_PyTime_t
|
||||||
_PyTime_GetMonotonicClock(void)
|
_PyTime_GetMonotonicClock(void)
|
||||||
{
|
{
|
||||||
|
@ -962,6 +1024,7 @@ _PyTime_GetMonotonicClock(void)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
_PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
||||||
{
|
{
|
||||||
|
@ -971,7 +1034,7 @@ _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
static int
|
static int
|
||||||
win_perf_counter_frequency(LONGLONG *pfrequency, int raise)
|
py_win_perf_counter_frequency(LONGLONG *pfrequency, int raise)
|
||||||
{
|
{
|
||||||
LONGLONG frequency;
|
LONGLONG frequency;
|
||||||
|
|
||||||
|
@ -1025,7 +1088,7 @@ py_get_win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
{
|
{
|
||||||
static LONGLONG frequency = 0;
|
static LONGLONG frequency = 0;
|
||||||
if (frequency == 0) {
|
if (frequency == 0) {
|
||||||
if (win_perf_counter_frequency(&frequency, raise) < 0) {
|
if (py_win_perf_counter_frequency(&frequency, raise) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1047,7 +1110,8 @@ py_get_win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
|
||||||
Py_BUILD_ASSERT(sizeof(ticksll) <= sizeof(ticks));
|
Py_BUILD_ASSERT(sizeof(ticksll) <= sizeof(ticks));
|
||||||
ticks = (_PyTime_t)ticksll;
|
ticks = (_PyTime_t)ticksll;
|
||||||
|
|
||||||
*tp = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)frequency);
|
_PyTime_t ns = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)frequency);
|
||||||
|
*tp = pytime_from_nanoseconds(ns);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1075,8 +1139,8 @@ _PyTime_GetPerfCounter(void)
|
||||||
res = py_get_monotonic_clock(&t, NULL, 0);
|
res = py_get_monotonic_clock(&t, NULL, 0);
|
||||||
#endif
|
#endif
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
// If win_perf_counter_frequency() or py_get_monotonic_clock() fails:
|
// If py_win_perf_counter_frequency() or py_get_monotonic_clock()
|
||||||
// silently ignore the failure and return 0.
|
// fails: silently ignore the failure and return 0.
|
||||||
t = 0;
|
t = 0;
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
|
@ -1121,6 +1185,7 @@ _PyTime_localtime(time_t t, struct tm *tm)
|
||||||
#endif /* MS_WINDOWS */
|
#endif /* MS_WINDOWS */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_gmtime(time_t t, struct tm *tm)
|
_PyTime_gmtime(time_t t, struct tm *tm)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue