summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Python/thread_nt.h
diff options
context:
space:
mode:
authorshadchin <[email protected]>2026-02-03 21:59:07 +0300
committershadchin <[email protected]>2026-02-03 22:28:51 +0300
commitbce46f28de392862d5c6c3b185d844ee7c623be3 (patch)
tree424878b5b90144f98970ce4a2745990c77330ad2 /contrib/tools/python3/Python/thread_nt.h
parent0e0ee9fa48ce9411b4038aa769493d22ff6c10a2 (diff)
Import Python 3.13.11
commit_hash:bbb53cefb159aa3e7afaa475fd19d5a03b66945f
Diffstat (limited to 'contrib/tools/python3/Python/thread_nt.h')
-rw-r--r--contrib/tools/python3/Python/thread_nt.h105
1 files changed, 67 insertions, 38 deletions
diff --git a/contrib/tools/python3/Python/thread_nt.h b/contrib/tools/python3/Python/thread_nt.h
index 26f441bd6d3..3a01a7fe327 100644
--- a/contrib/tools/python3/Python/thread_nt.h
+++ b/contrib/tools/python3/Python/thread_nt.h
@@ -1,4 +1,5 @@
-#include "pycore_interp.h" // _PyInterpreterState.threads.stacksize
+#include "pycore_interp.h" // _PyInterpreterState.threads.stacksize
+#include "pycore_time.h" // _PyTime_AsMicroseconds()
/* This code implemented by [email protected] */
/* Fast NonRecursiveMutex support by Yakov Markovitch, [email protected] */
@@ -76,17 +77,18 @@ EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds)
}
} else if (milliseconds != 0) {
/* wait at least until the deadline */
- _PyTime_t nanoseconds = _PyTime_FromNanoseconds((_PyTime_t)milliseconds * 1000000);
- _PyTime_t deadline = _PyTime_Add(_PyTime_GetPerfCounter(), nanoseconds);
+ PyTime_t timeout = (PyTime_t)milliseconds * (1000 * 1000);
+ PyTime_t deadline = _PyDeadline_Init(timeout);
while (mutex->locked) {
- _PyTime_t microseconds = _PyTime_AsMicroseconds(nanoseconds,
- _PyTime_ROUND_TIMEOUT);
+ PyTime_t microseconds = _PyTime_AsMicroseconds(timeout,
+ _PyTime_ROUND_TIMEOUT);
if (PyCOND_TIMEDWAIT(&mutex->cv, &mutex->cs, microseconds) < 0) {
result = WAIT_FAILED;
break;
}
- nanoseconds = deadline - _PyTime_GetPerfCounter();
- if (nanoseconds <= 0) {
+
+ timeout = _PyDeadline_Get(deadline);
+ if (timeout <= 0) {
break;
}
}
@@ -182,9 +184,9 @@ bootstrap(void *call)
return 0;
}
-unsigned long
-PyThread_start_new_thread(void (*func)(void *), void *arg)
-{
+int
+PyThread_start_joinable_thread(void (*func)(void *), void *arg,
+ PyThread_ident_t* ident, PyThread_handle_t* handle) {
HANDLE hThread;
unsigned threadID;
callobj *obj;
@@ -194,7 +196,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
obj = (callobj*)HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
if (!obj)
- return PYTHREAD_INVALID_THREAD_ID;
+ return -1;
obj->func = func;
obj->arg = arg;
PyThreadState *tstate = _PyThreadState_GET();
@@ -207,22 +209,47 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
/* I've seen errno == EAGAIN here, which means "there are
* too many threads".
*/
- int e = errno;
- threadID = (unsigned)-1;
HeapFree(GetProcessHeap(), 0, obj);
+ return -1;
}
- else {
- CloseHandle(hThread);
+ *ident = threadID;
+ // The cast is safe since HANDLE is pointer-sized
+ *handle = (PyThread_handle_t) hThread;
+ return 0;
+}
+
+unsigned long
+PyThread_start_new_thread(void (*func)(void *), void *arg) {
+ PyThread_handle_t handle;
+ PyThread_ident_t ident;
+ if (PyThread_start_joinable_thread(func, arg, &ident, &handle)) {
+ return PYTHREAD_INVALID_THREAD_ID;
}
- return threadID;
+ CloseHandle((HANDLE) handle);
+ // The cast is safe since the ident is really an unsigned int
+ return (unsigned long) ident;
+}
+
+int
+PyThread_join_thread(PyThread_handle_t handle) {
+ HANDLE hThread = (HANDLE) handle;
+ int errored = (WaitForSingleObject(hThread, INFINITE) != WAIT_OBJECT_0);
+ CloseHandle(hThread);
+ return errored;
+}
+
+int
+PyThread_detach_thread(PyThread_handle_t handle) {
+ HANDLE hThread = (HANDLE) handle;
+ return (CloseHandle(hThread) == 0);
}
/*
* Return the thread Id instead of a handle. The Id is said to uniquely identify the
* thread in the system
*/
-unsigned long
-PyThread_get_thread_ident(void)
+PyThread_ident_t
+PyThread_get_thread_ident_ex(void)
{
if (!initialized)
PyThread_init_thread();
@@ -230,6 +257,13 @@ PyThread_get_thread_ident(void)
return GetCurrentThreadId();
}
+unsigned long
+PyThread_get_thread_ident(void)
+{
+ return (unsigned long) PyThread_get_thread_ident_ex();
+}
+
+
#ifdef PY_HAVE_THREAD_NATIVE_ID
/*
* Return the native Thread ID (TID) of the calling thread.
@@ -257,6 +291,14 @@ PyThread_exit_thread(void)
_endthreadex(0);
}
+void _Py_NO_RETURN
+PyThread_hang_thread(void)
+{
+ while (1) {
+ SleepEx(INFINITE, TRUE);
+ }
+}
+
/*
* Lock support. It has to be implemented as semaphores.
* I [Dag] tried to implement it with mutex but I could find a way to
@@ -408,16 +450,7 @@ PyThread_set_key_value(int key, void *value)
void *
PyThread_get_key_value(int key)
{
- /* because TLS is used in the Py_END_ALLOW_THREAD macro,
- * it is necessary to preserve the windows error state, because
- * it is assumed to be preserved across the call to the macro.
- * Ideally, the macro should be fixed, but it is simpler to
- * do it here.
- */
- DWORD error = GetLastError();
- void *result = TlsGetValue(key);
- SetLastError(error);
- return result;
+ return TlsGetValue(key);
}
void
@@ -489,14 +522,10 @@ void *
PyThread_tss_get(Py_tss_t *key)
{
assert(key != NULL);
- /* because TSS is used in the Py_END_ALLOW_THREAD macro,
- * it is necessary to preserve the windows error state, because
- * it is assumed to be preserved across the call to the macro.
- * Ideally, the macro should be fixed, but it is simpler to
- * do it here.
- */
- DWORD error = GetLastError();
- void *result = TlsGetValue(key->_key);
- SetLastError(error);
- return result;
+ int err = GetLastError();
+ void *r = TlsGetValue(key->_key);
+ if (r || !GetLastError()) {
+ SetLastError(err);
+ }
+ return r;
}