diff --git a/Doc/api/init.tex b/Doc/api/init.tex index ba961242d7d..764c93275e2 100644 --- a/Doc/api/init.tex +++ b/Doc/api/init.tex @@ -24,7 +24,7 @@ \end{cfuncdesc} \begin{cfuncdesc}{void}{Py_InitializeEx}{int initsigs} - This function works like \cfunction{Py_Initialize} if + This function works like \cfunction{Py_Initialize()} if \var{initsigs} is 1. If \var{initsigs} is 0, it skips initialization registration of signal handlers, which might be useful when Python is embedded. \versionadded{2.4} @@ -517,14 +517,14 @@ for calling into Python from a C thread is This is a common situation (most Python programs do not use threads), and the lock operations slow the interpreter down a bit. Therefore, the lock is not created initially. This situation is - equivalent to having acquired the lock: when there is only a single + equivalent to having acquired the lock: when there is only a single thread, all object accesses are safe. Therefore, when this function initializes the lock, it also acquires it. Before the Python \module{thread}\refbimodindex{thread} module creates a new thread, knowing that either it has the lock or the lock hasn't been created yet, it calls \cfunction{PyEval_InitThreads()}. When this call - returns, it is guaranteed that the lock has been created and that it - has acquired it. + returns, it is guaranteed that the lock has been created and that the + calling thread has acquired it. It is \strong{not} safe to call this function when it is unknown which thread (if any) currently has the global interpreter lock. @@ -533,6 +533,14 @@ for calling into Python from a C thread is compile time. \end{cfuncdesc} +\begin{cfuncdesc}{int}{PyEval_ThreadsInitialized}{} + Returns a non-zero value if \cfunction{PyEval_InitThreads()} has been + called. This function can be called without holding the lock, and + therefore can be used to avoid calls to the locking API when running + single-threaded. This function is not available when thread support + is disabled at compile time. \versionadded{2.4} +\end{cfuncdesc} + \begin{cfuncdesc}{void}{PyEval_AcquireLock}{} Acquire the global interpreter lock. The lock must have been created earlier. If this thread already has the lock, a deadlock diff --git a/Include/ceval.h b/Include/ceval.h index 3d1f6fd2b09..d9320e02c18 100644 --- a/Include/ceval.h +++ b/Include/ceval.h @@ -120,6 +120,7 @@ PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *); #ifdef WITH_THREAD +PyAPI_FUNC(int) PyEval_ThreadsInitialized(void); PyAPI_FUNC(void) PyEval_InitThreads(void); PyAPI_FUNC(void) PyEval_AcquireLock(void); PyAPI_FUNC(void) PyEval_ReleaseLock(void); diff --git a/Misc/NEWS b/Misc/NEWS index 87c6f37f2c3..d5472044c02 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -136,6 +136,11 @@ Build C API ----- +- SF patch 1044089: New function ``PyEval_ThreadsInitialized()`` returns + non-zero if PyEval_InitThreads() has been called. + +- The undocumented and unused extern int ``_PyThread_Started`` was removed. + - The C API calls ``PyInterpreterState_New()`` and ``PyThreadState_New()`` are two of the very few advertised as being safe to call without holding the GIL. However, this wasn't true in a debug build, as bug 1041645 diff --git a/PC/os2emx/python24.def b/PC/os2emx/python24.def index 4cfd4b86639..4f789145777 100644 --- a/PC/os2emx/python24.def +++ b/PC/os2emx/python24.def @@ -980,7 +980,6 @@ EXPORTS "Py_UseClassExceptionsFlag" "Py_UnicodeFlag" "_Py_QnewFlag" - "_PyThread_Started" ; From python24_s.lib(structmember) "PyMember_Get" diff --git a/PC/os2vacpp/python.def b/PC/os2vacpp/python.def index 8f1207bf398..bc73fac17a0 100644 --- a/PC/os2vacpp/python.def +++ b/PC/os2vacpp/python.def @@ -69,7 +69,6 @@ EXPORTS _PyImport_Inittab _PyParser_Grammar _PyParser_TokenNames - _PyThread_Started _Py_EllipsisObject _Py_NoneStruct _Py_PackageContext diff --git a/Python/ceval.c b/Python/ceval.c index 2223aba7356..4d26a7a7359 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -203,17 +203,20 @@ PyEval_GetCallStats(PyObject *self) #endif #include "pythread.h" -extern int _PyThread_Started; /* Flag for Py_Exit */ - static PyThread_type_lock interpreter_lock = 0; /* This is the GIL */ static long main_thread = 0; +int +PyEval_ThreadsInitialized(void) +{ + return interpreter_lock != 0; +} + void PyEval_InitThreads(void) { if (interpreter_lock) return; - _PyThread_Started = 1; interpreter_lock = PyThread_allocate_lock(); PyThread_acquire_lock(interpreter_lock, 1); main_thread = PyThread_get_thread_ident(); diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 06bec1e0386..92e051b1762 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1517,7 +1517,6 @@ Py_FatalError(const char *msg) #ifdef WITH_THREAD #include "pythread.h" -int _PyThread_Started = 0; /* Set by threadmodule.c and maybe others */ #endif #define NEXITFUNCS 32