diff options
| author | Victor Stinner <vstinner@python.org> | 2021-10-01 11:29:25 (GMT) |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-01 11:29:25 (GMT) |
| commit | 833fdf126c8fe77fd17e8a8ffbc5c571b3bf64bd (patch) | |
| tree | 7e4ed574b7cfb30c0ebb7585061134fee1b1f8ae /Modules | |
| parent | 54957f16a63ecb6b15f77b01fa7c55ada892604a (diff) | |
| download | cpython-833fdf126c8fe77fd17e8a8ffbc5c571b3bf64bd.zip cpython-833fdf126c8fe77fd17e8a8ffbc5c571b3bf64bd.tar.gz cpython-833fdf126c8fe77fd17e8a8ffbc5c571b3bf64bd.tar.bz2 | |
bpo-41710: Add private _PyDeadline_Get() function (GH-28674)
Add a private C API for deadlines: add _PyDeadline_Init() and
_PyDeadline_Get() functions.
* Add _PyTime_Add() and _PyTime_Mul() functions which compute t1+t2
and t1*t2 and clamp the result on overflow.
* _PyTime_MulDiv() now uses _PyTime_Add() and _PyTime_Mul().
Diffstat (limited to 'Modules')
| -rw-r--r-- | Modules/_queuemodule.c | 31 | ||||
| -rw-r--r-- | Modules/_ssl.c | 34 | ||||
| -rw-r--r-- | Modules/_threadmodule.c | 7 | ||||
| -rw-r--r-- | Modules/clinic/_queuemodule.c.h | 10 | ||||
| -rw-r--r-- | Modules/selectmodule.c | 29 | ||||
| -rw-r--r-- | Modules/signalmodule.c | 20 | ||||
| -rw-r--r-- | Modules/socketmodule.c | 20 |
7 files changed, 83 insertions, 68 deletions
diff --git a/Modules/_queuemodule.c b/Modules/_queuemodule.c index b6769e6..eb61349 100644 --- a/Modules/_queuemodule.c +++ b/Modules/_queuemodule.c @@ -182,7 +182,7 @@ _queue.SimpleQueue.get cls: defining_class / block: bool = True - timeout: object = None + timeout as timeout_obj: object = None Remove and return an item from the queue. @@ -198,11 +198,11 @@ in that case). static PyObject * _queue_SimpleQueue_get_impl(simplequeueobject *self, PyTypeObject *cls, - int block, PyObject *timeout) -/*[clinic end generated code: output=1969aefa7db63666 input=5fc4d56b9a54757e]*/ + int block, PyObject *timeout_obj) +/*[clinic end generated code: output=5c2cca914cd1e55b input=5b4047bfbc645ec1]*/ { _PyTime_t endtime = 0; - _PyTime_t timeout_val; + _PyTime_t timeout; PyObject *item; PyLockStatus r; PY_TIMEOUT_T microseconds; @@ -211,24 +211,25 @@ _queue_SimpleQueue_get_impl(simplequeueobject *self, PyTypeObject *cls, /* Non-blocking */ microseconds = 0; } - else if (timeout != Py_None) { + else if (timeout_obj != Py_None) { /* With timeout */ - if (_PyTime_FromSecondsObject(&timeout_val, - timeout, _PyTime_ROUND_CEILING) < 0) + if (_PyTime_FromSecondsObject(&timeout, + timeout_obj, _PyTime_ROUND_CEILING) < 0) { return NULL; - if (timeout_val < 0) { + } + if (timeout < 0) { PyErr_SetString(PyExc_ValueError, "'timeout' must be a non-negative number"); return NULL; } - microseconds = _PyTime_AsMicroseconds(timeout_val, + microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING); if (microseconds > PY_TIMEOUT_MAX) { PyErr_SetString(PyExc_OverflowError, "timeout value is too large"); return NULL; } - endtime = _PyTime_GetMonotonicClock() + timeout_val; + endtime = _PyDeadline_Init(timeout); } else { /* Infinitely blocking */ @@ -247,6 +248,7 @@ _queue_SimpleQueue_get_impl(simplequeueobject *self, PyTypeObject *cls, r = PyThread_acquire_lock_timed(self->lock, microseconds, 1); Py_END_ALLOW_THREADS } + if (r == PY_LOCK_INTR && Py_MakePendingCalls() < 0) { return NULL; } @@ -258,12 +260,15 @@ _queue_SimpleQueue_get_impl(simplequeueobject *self, PyTypeObject *cls, return NULL; } self->locked = 1; + /* Adjust timeout for next iteration (if any) */ - if (endtime > 0) { - timeout_val = endtime - _PyTime_GetMonotonicClock(); - microseconds = _PyTime_AsMicroseconds(timeout_val, _PyTime_ROUND_CEILING); + if (microseconds > 0) { + timeout = _PyDeadline_Get(endtime); + microseconds = _PyTime_AsMicroseconds(timeout, + _PyTime_ROUND_CEILING); } } + /* BEGIN GIL-protected critical section */ assert(self->lst_pos < PyList_GET_SIZE(self->lst)); item = simplequeue_pop_item(self); diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 411314f..fedb35b 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -949,8 +949,9 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self) timeout = GET_SOCKET_TIMEOUT(sock); has_timeout = (timeout > 0); - if (has_timeout) - deadline = _PyTime_GetMonotonicClock() + timeout; + if (has_timeout) { + deadline = _PyDeadline_Init(timeout); + } /* Actually negotiate SSL connection */ /* XXX If SSL_do_handshake() returns 0, it's also a failure. */ @@ -965,7 +966,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self) goto error; if (has_timeout) - timeout = deadline - _PyTime_GetMonotonicClock(); + timeout = _PyDeadline_Get(deadline); if (err.ssl == SSL_ERROR_WANT_READ) { sockstate = PySSL_select(sock, 0, timeout); @@ -2326,8 +2327,9 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b) timeout = GET_SOCKET_TIMEOUT(sock); has_timeout = (timeout > 0); - if (has_timeout) - deadline = _PyTime_GetMonotonicClock() + timeout; + if (has_timeout) { + deadline = _PyDeadline_Init(timeout); + } sockstate = PySSL_select(sock, 1, timeout); if (sockstate == SOCKET_HAS_TIMED_OUT) { @@ -2354,8 +2356,9 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b) if (PyErr_CheckSignals()) goto error; - if (has_timeout) - timeout = deadline - _PyTime_GetMonotonicClock(); + if (has_timeout) { + timeout = _PyDeadline_Get(deadline); + } if (err.ssl == SSL_ERROR_WANT_READ) { sockstate = PySSL_select(sock, 0, timeout); @@ -2494,7 +2497,7 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, Py_ssize_t len, timeout = GET_SOCKET_TIMEOUT(sock); has_timeout = (timeout > 0); if (has_timeout) - deadline = _PyTime_GetMonotonicClock() + timeout; + deadline = _PyDeadline_Init(timeout); do { PySSL_BEGIN_ALLOW_THREADS @@ -2506,8 +2509,9 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, Py_ssize_t len, if (PyErr_CheckSignals()) goto error; - if (has_timeout) - timeout = deadline - _PyTime_GetMonotonicClock(); + if (has_timeout) { + timeout = _PyDeadline_Get(deadline); + } if (err.ssl == SSL_ERROR_WANT_READ) { sockstate = PySSL_select(sock, 0, timeout); @@ -2592,8 +2596,9 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self) timeout = GET_SOCKET_TIMEOUT(sock); has_timeout = (timeout > 0); - if (has_timeout) - deadline = _PyTime_GetMonotonicClock() + timeout; + if (has_timeout) { + deadline = _PyDeadline_Init(timeout); + } while (1) { PySSL_BEGIN_ALLOW_THREADS @@ -2626,8 +2631,9 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self) continue; } - if (has_timeout) - timeout = deadline - _PyTime_GetMonotonicClock(); + if (has_timeout) { + timeout = _PyDeadline_Get(deadline); + } /* Possibly retry shutdown until timeout or failure */ if (err.ssl == SSL_ERROR_WANT_READ) diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index fa7e6d0..543d82d 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -84,13 +84,12 @@ lock_dealloc(lockobject *self) static PyLockStatus acquire_timed(PyThread_type_lock lock, _PyTime_t timeout) { - PyLockStatus r; _PyTime_t endtime = 0; - if (timeout > 0) { - endtime = _PyTime_GetMonotonicClock() + timeout; + endtime = _PyDeadline_Init(timeout); } + PyLockStatus r; do { _PyTime_t microseconds; microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING); @@ -114,7 +113,7 @@ acquire_timed(PyThread_type_lock lock, _PyTime_t timeout) /* If we're using a timeout, recompute the timeout after processing * signals, since those can take time. */ if (timeout > 0) { - timeout = endtime - _PyTime_GetMonotonicClock(); + timeout = _PyDeadline_Get(endtime); /* Check for negative values, since those mean block forever. */ diff --git a/Modules/clinic/_queuemodule.c.h b/Modules/clinic/_queuemodule.c.h index d952256..22d2e99 100644 --- a/Modules/clinic/_queuemodule.c.h +++ b/Modules/clinic/_queuemodule.c.h @@ -139,7 +139,7 @@ PyDoc_STRVAR(_queue_SimpleQueue_get__doc__, static PyObject * _queue_SimpleQueue_get_impl(simplequeueobject *self, PyTypeObject *cls, - int block, PyObject *timeout); + int block, PyObject *timeout_obj); static PyObject * _queue_SimpleQueue_get(simplequeueobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -148,13 +148,13 @@ _queue_SimpleQueue_get(simplequeueobject *self, PyTypeObject *cls, PyObject *con static const char * const _keywords[] = {"block", "timeout", NULL}; static _PyArg_Parser _parser = {"|pO:get", _keywords, 0}; int block = 1; - PyObject *timeout = Py_None; + PyObject *timeout_obj = Py_None; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &block, &timeout)) { + &block, &timeout_obj)) { goto exit; } - return_value = _queue_SimpleQueue_get_impl(self, cls, block, timeout); + return_value = _queue_SimpleQueue_get_impl(self, cls, block, timeout_obj); exit: return return_value; @@ -248,4 +248,4 @@ _queue_SimpleQueue_qsize(simplequeueobject *self, PyObject *Py_UNUSED(ignored)) exit: return return_value; } -/*[clinic end generated code: output=96cc57168d72aab1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=acfaf0191d8935db input=a9049054013a1b77]*/ diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index b71b2c4..ff1c028 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -318,8 +318,9 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, if (omax > max) max = omax; if (emax > max) max = emax; - if (tvp) - deadline = _PyTime_GetMonotonicClock() + timeout; + if (tvp) { + deadline = _PyDeadline_Init(timeout); + } do { Py_BEGIN_ALLOW_THREADS @@ -335,7 +336,7 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, goto finally; if (tvp) { - timeout = deadline - _PyTime_GetMonotonicClock(); + timeout = _PyDeadline_Get(deadline); if (timeout < 0) { /* bpo-35310: lists were unmodified -- clear them explicitly */ FD_ZERO(&ifdset); @@ -599,7 +600,7 @@ select_poll_poll_impl(pollObject *self, PyObject *timeout_obj) } if (timeout >= 0) { - deadline = _PyTime_GetMonotonicClock() + timeout; + deadline = _PyDeadline_Init(timeout); } } @@ -646,7 +647,7 @@ select_poll_poll_impl(pollObject *self, PyObject *timeout_obj) } if (timeout >= 0) { - timeout = deadline - _PyTime_GetMonotonicClock(); + timeout = _PyDeadline_Get(deadline); if (timeout < 0) { poll_result = 0; break; @@ -938,8 +939,9 @@ select_devpoll_poll_impl(devpollObject *self, PyObject *timeout_obj) dvp.dp_nfds = self->max_n_fds; dvp.dp_timeout = (int)ms; - if (timeout >= 0) - deadline = _PyTime_GetMonotonicClock() + timeout; + if (timeout >= 0) { + deadline = _PyDeadline_Init(timeout); + } do { /* call devpoll() */ @@ -956,7 +958,7 @@ select_devpoll_poll_impl(devpollObject *self, PyObject *timeout_obj) return NULL; if (timeout >= 0) { - timeout = deadline - _PyTime_GetMonotonicClock(); + timeout = _PyDeadline_Get(deadline); if (timeout < 0) { poll_result = 0; break; @@ -1550,7 +1552,7 @@ select_epoll_poll_impl(pyEpoll_Object *self, PyObject *timeout_obj, } if (timeout >= 0) { - deadline = _PyTime_GetMonotonicClock() + timeout; + deadline = _PyDeadline_Init(timeout); } } @@ -1584,7 +1586,7 @@ select_epoll_poll_impl(pyEpoll_Object *self, PyObject *timeout_obj, goto error; if (timeout >= 0) { - timeout = deadline - _PyTime_GetMonotonicClock(); + timeout = _PyDeadline_Get(deadline); if (timeout < 0) { nfds = 0; break; @@ -2172,8 +2174,9 @@ select_kqueue_control_impl(kqueue_queue_Object *self, PyObject *changelist, } } - if (ptimeoutspec) - deadline = _PyTime_GetMonotonicClock() + timeout; + if (ptimeoutspec) { + deadline = _PyDeadline_Init(timeout); + } do { Py_BEGIN_ALLOW_THREADS @@ -2190,7 +2193,7 @@ select_kqueue_control_impl(kqueue_queue_Object *self, PyObject *changelist, goto error; if (ptimeoutspec) { - timeout = deadline - _PyTime_GetMonotonicClock(); + timeout = _PyDeadline_Get(deadline); if (timeout < 0) { gotevents = 0; break; diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index fc58cfd..8b7ef2c 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -1221,11 +1221,7 @@ signal_sigtimedwait_impl(PyObject *module, sigset_t sigset, PyObject *timeout_obj) /*[clinic end generated code: output=59c8971e8ae18a64 input=87fd39237cf0b7ba]*/ { - struct timespec ts; - siginfo_t si; - int res; - _PyTime_t timeout, deadline, monotonic; - + _PyTime_t timeout; if (_PyTime_FromSecondsObject(&timeout, timeout_obj, _PyTime_ROUND_CEILING) < 0) return NULL; @@ -1235,12 +1231,16 @@ signal_sigtimedwait_impl(PyObject *module, sigset_t sigset, return NULL; } - deadline = _PyTime_GetMonotonicClock() + timeout; + _PyTime_t deadline = _PyDeadline_Init(timeout); + siginfo_t si; do { - if (_PyTime_AsTimespec(timeout, &ts) < 0) + struct timespec ts; + if (_PyTime_AsTimespec(timeout, &ts) < 0) { return NULL; + } + int res; Py_BEGIN_ALLOW_THREADS res = sigtimedwait(&sigset, &si, &ts); Py_END_ALLOW_THREADS @@ -1259,10 +1259,10 @@ signal_sigtimedwait_impl(PyObject *module, sigset_t sigset, if (PyErr_CheckSignals()) return NULL; - monotonic = _PyTime_GetMonotonicClock(); - timeout = deadline - monotonic; - if (timeout < 0) + timeout = _PyDeadline_Get(deadline); + if (timeout < 0) { break; + } } while (1); return fill_siginfo(&si); diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index f474869..9821227 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -840,18 +840,20 @@ sock_call_ex(PySocketSockObject *s, if (deadline_initialized) { /* recompute the timeout */ - interval = deadline - _PyTime_GetMonotonicClock(); + interval = _PyDeadline_Get(deadline); } else { deadline_initialized = 1; - deadline = _PyTime_GetMonotonicClock() + timeout; + deadline = _PyDeadline_Init(timeout); interval = timeout; } - if (interval >= 0) + if (interval >= 0) { res = internal_select(s, writing, interval, connect); - else + } + else { res = 1; + } } else { res = internal_select(s, writing, timeout, connect); @@ -4176,7 +4178,7 @@ sock_sendall(PySocketSockObject *s, PyObject *args) Py_buffer pbuf; struct sock_send ctx; int has_timeout = (s->sock_timeout > 0); - _PyTime_t interval = s->sock_timeout; + _PyTime_t timeout = s->sock_timeout; _PyTime_t deadline = 0; int deadline_initialized = 0; PyObject *res = NULL; @@ -4195,14 +4197,14 @@ sock_sendall(PySocketSockObject *s, PyObject *args) if (has_timeout) { if (deadline_initialized) { /* recompute the timeout */ - interval = deadline - _PyTime_GetMonotonicClock(); + timeout = _PyDeadline_Get(deadline); } else { deadline_initialized = 1; - deadline = _PyTime_GetMonotonicClock() + s->sock_timeout; + deadline = _PyDeadline_Init(timeout); } - if (interval <= 0) { + if (timeout <= 0) { PyErr_SetString(PyExc_TimeoutError, "timed out"); goto done; } @@ -4211,7 +4213,7 @@ sock_sendall(PySocketSockObject *s, PyObject *args) ctx.buf = buf; ctx.len = len; ctx.flags = flags; - if (sock_call_ex(s, 1, sock_send_impl, &ctx, 0, NULL, interval) < 0) + if (sock_call_ex(s, 1, sock_send_impl, &ctx, 0, NULL, timeout) < 0) goto done; n = ctx.result; assert(n >= 0); |
