diff options
| author | shadchin <[email protected]> | 2026-02-03 21:59:07 +0300 |
|---|---|---|
| committer | shadchin <[email protected]> | 2026-02-03 22:28:51 +0300 |
| commit | bce46f28de392862d5c6c3b185d844ee7c623be3 (patch) | |
| tree | 424878b5b90144f98970ce4a2745990c77330ad2 /contrib/tools/python3/Python/thread.c | |
| parent | 0e0ee9fa48ce9411b4038aa769493d22ff6c10a2 (diff) | |
Import Python 3.13.11
commit_hash:bbb53cefb159aa3e7afaa475fd19d5a03b66945f
Diffstat (limited to 'contrib/tools/python3/Python/thread.c')
| -rw-r--r-- | contrib/tools/python3/Python/thread.c | 108 |
1 files changed, 106 insertions, 2 deletions
diff --git a/contrib/tools/python3/Python/thread.c b/contrib/tools/python3/Python/thread.c index 7fc53f9b613..b31d1dc5e77 100644 --- a/contrib/tools/python3/Python/thread.c +++ b/contrib/tools/python3/Python/thread.c @@ -6,17 +6,38 @@ Stuff shared by all thread_*.h files is collected here. */ #include "Python.h" +#include "pycore_ceval.h" // _PyEval_MakePendingCalls() #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin() -#include "pycore_pythread.h" +#include "pycore_pythread.h" // _POSIX_THREADS #ifndef DONT_HAVE_STDIO_H -#include <stdio.h> +# include <stdio.h> #endif #include <stdlib.h> +// Define PY_TIMEOUT_MAX constant. +#ifdef _POSIX_THREADS + // PyThread_acquire_lock_timed() uses (us * 1000) to convert microseconds + // to nanoseconds. +# define PY_TIMEOUT_MAX_VALUE (LLONG_MAX / 1000) +#elif defined (NT_THREADS) + // WaitForSingleObject() accepts timeout in milliseconds in the range + // [0; 0xFFFFFFFE] (DWORD type). INFINITE value (0xFFFFFFFF) means no + // timeout. 0xFFFFFFFE milliseconds is around 49.7 days. +# if 0xFFFFFFFELL < LLONG_MAX / 1000 +# define PY_TIMEOUT_MAX_VALUE (0xFFFFFFFELL * 1000) +# else +# define PY_TIMEOUT_MAX_VALUE LLONG_MAX +# endif +#else +# define PY_TIMEOUT_MAX_VALUE LLONG_MAX +#endif +const long long PY_TIMEOUT_MAX = PY_TIMEOUT_MAX_VALUE; + + static void PyThread__init_thread(void); /* Forward */ #define initialized _PyRuntime.threads.initialized @@ -72,6 +93,89 @@ PyThread_set_stacksize(size_t size) } +int +PyThread_ParseTimeoutArg(PyObject *arg, int blocking, PY_TIMEOUT_T *timeout_p) +{ + assert(_PyTime_FromSeconds(-1) == PyThread_UNSET_TIMEOUT); + if (arg == NULL || arg == Py_None) { + *timeout_p = blocking ? PyThread_UNSET_TIMEOUT : 0; + return 0; + } + if (!blocking) { + PyErr_SetString(PyExc_ValueError, + "can't specify a timeout for a non-blocking call"); + return -1; + } + + PyTime_t timeout; + if (_PyTime_FromSecondsObject(&timeout, arg, _PyTime_ROUND_TIMEOUT) < 0) { + return -1; + } + if (timeout < 0) { + PyErr_SetString(PyExc_ValueError, + "timeout value must be a non-negative number"); + return -1; + } + + if (_PyTime_AsMicroseconds(timeout, + _PyTime_ROUND_TIMEOUT) > PY_TIMEOUT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "timeout value is too large"); + return -1; + } + *timeout_p = timeout; + return 0; +} + +PyLockStatus +PyThread_acquire_lock_timed_with_retries(PyThread_type_lock lock, + PY_TIMEOUT_T timeout) +{ + PyThreadState *tstate = _PyThreadState_GET(); + PyTime_t endtime = 0; + if (timeout > 0) { + endtime = _PyDeadline_Init(timeout); + } + + PyLockStatus r; + do { + PyTime_t microseconds; + microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING); + + /* first a simple non-blocking try without releasing the GIL */ + r = PyThread_acquire_lock_timed(lock, 0, 0); + if (r == PY_LOCK_FAILURE && microseconds != 0) { + Py_BEGIN_ALLOW_THREADS + r = PyThread_acquire_lock_timed(lock, microseconds, 1); + Py_END_ALLOW_THREADS + } + + if (r == PY_LOCK_INTR) { + /* Run signal handlers if we were interrupted. Propagate + * exceptions from signal handlers, such as KeyboardInterrupt, by + * passing up PY_LOCK_INTR. */ + if (_PyEval_MakePendingCalls(tstate) < 0) { + return PY_LOCK_INTR; + } + + /* If we're using a timeout, recompute the timeout after processing + * signals, since those can take time. */ + if (timeout > 0) { + timeout = _PyDeadline_Get(endtime); + + /* Check for negative values, since those mean block forever. + */ + if (timeout < 0) { + r = PY_LOCK_FAILURE; + } + } + } + } while (r == PY_LOCK_INTR); /* Retry if we were interrupted. */ + + return r; +} + + /* Thread Specific Storage (TSS) API Cross-platform components of TSS API implementation. |
