mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	gh-59956: Clarify GILState-related Code (gh-101161)
The objective of this change is to help make the GILState-related code easier to understand. This mostly involves moving code around and some semantically equivalent refactors. However, there are a also a small number of slight changes in structure and behavior: * tstate_current is moved out of _PyRuntimeState.gilstate * autoTSSkey is moved out of _PyRuntimeState.gilstate * autoTSSkey is initialized earlier * autoTSSkey is re-initialized (after fork) earlier https://github.com/python/cpython/issues/59956
This commit is contained in:
		
							parent
							
								
									8a2d4f4e8e
								
							
						
					
					
						commit
						6036c3e856
					
				
					 10 changed files with 373 additions and 250 deletions
				
			
		|  | @ -114,11 +114,7 @@ struct _ts { | ||||||
|     PyThreadState *next; |     PyThreadState *next; | ||||||
|     PyInterpreterState *interp; |     PyInterpreterState *interp; | ||||||
| 
 | 
 | ||||||
|     /* Has been initialized to a safe state.
 |     int _status; | ||||||
| 
 |  | ||||||
|        In order to be effective, this must be set to 0 during or right |  | ||||||
|        after allocation. */ |  | ||||||
|     int _initialized; |  | ||||||
| 
 | 
 | ||||||
|     int py_recursion_remaining; |     int py_recursion_remaining; | ||||||
|     int py_recursion_limit; |     int py_recursion_limit; | ||||||
|  |  | ||||||
|  | @ -69,7 +69,7 @@ extern void _PyThread_FiniType(PyInterpreterState *interp); | ||||||
| extern void _Py_Deepfreeze_Fini(void); | extern void _Py_Deepfreeze_Fini(void); | ||||||
| extern void _PyArg_Fini(void); | extern void _PyArg_Fini(void); | ||||||
| 
 | 
 | ||||||
| extern PyStatus _PyGILState_Init(_PyRuntimeState *runtime); | extern PyStatus _PyGILState_Init(PyInterpreterState *interp); | ||||||
| extern PyStatus _PyGILState_SetTstate(PyThreadState *tstate); | extern PyStatus _PyGILState_SetTstate(PyThreadState *tstate); | ||||||
| extern void _PyGILState_Fini(PyInterpreterState *interp); | extern void _PyGILState_Fini(PyInterpreterState *interp); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -67,12 +67,12 @@ _Py_ThreadCanHandlePendingCalls(void) | ||||||
| static inline PyThreadState* | static inline PyThreadState* | ||||||
| _PyRuntimeState_GetThreadState(_PyRuntimeState *runtime) | _PyRuntimeState_GetThreadState(_PyRuntimeState *runtime) | ||||||
| { | { | ||||||
|     return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->gilstate.tstate_current); |     return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->tstate_current); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Get the current Python thread state.
 | /* Get the current Python thread state.
 | ||||||
| 
 | 
 | ||||||
|    Efficient macro reading directly the 'gilstate.tstate_current' atomic |    Efficient macro reading directly the 'tstate_current' atomic | ||||||
|    variable. The macro is unsafe: it does not check for error and it can |    variable. The macro is unsafe: it does not check for error and it can | ||||||
|    return NULL. |    return NULL. | ||||||
| 
 | 
 | ||||||
|  | @ -120,7 +120,7 @@ static inline PyInterpreterState* _PyInterpreterState_GET(void) { | ||||||
| 
 | 
 | ||||||
| // PyThreadState functions
 | // PyThreadState functions
 | ||||||
| 
 | 
 | ||||||
| PyAPI_FUNC(void) _PyThreadState_SetCurrent(PyThreadState *tstate); | PyAPI_FUNC(void) _PyThreadState_Bind(PyThreadState *tstate); | ||||||
| // We keep this around exclusively for stable ABI compatibility.
 | // We keep this around exclusively for stable ABI compatibility.
 | ||||||
| PyAPI_FUNC(void) _PyThreadState_Init( | PyAPI_FUNC(void) _PyThreadState_Init( | ||||||
|     PyThreadState *tstate); |     PyThreadState *tstate); | ||||||
|  | @ -139,17 +139,28 @@ _PyThreadState_UpdateTracingState(PyThreadState *tstate) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | /* PyThreadState status */ | ||||||
|  | 
 | ||||||
|  | #define PyThreadState_UNINITIALIZED 0 | ||||||
|  | /* Has been initialized to a safe state.
 | ||||||
|  | 
 | ||||||
|  |    In order to be effective, this must be set to 0 during or right | ||||||
|  |    after allocation. */ | ||||||
|  | #define PyThreadState_INITIALIZED 1 | ||||||
|  | #define PyThreadState_BOUND 2 | ||||||
|  | #define PyThreadState_UNBOUND 3 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /* Other */ | /* Other */ | ||||||
| 
 | 
 | ||||||
| PyAPI_FUNC(PyThreadState *) _PyThreadState_Swap( | PyAPI_FUNC(PyThreadState *) _PyThreadState_Swap( | ||||||
|     struct _gilstate_runtime_state *gilstate, |     _PyRuntimeState *runtime, | ||||||
|     PyThreadState *newts); |     PyThreadState *newts); | ||||||
| 
 | 
 | ||||||
| PyAPI_FUNC(PyStatus) _PyInterpreterState_Enable(_PyRuntimeState *runtime); | PyAPI_FUNC(PyStatus) _PyInterpreterState_Enable(_PyRuntimeState *runtime); | ||||||
| 
 | 
 | ||||||
| #ifdef HAVE_FORK | #ifdef HAVE_FORK | ||||||
| extern PyStatus _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime); | extern PyStatus _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime); | ||||||
| extern PyStatus _PyGILState_Reinit(_PyRuntimeState *runtime); |  | ||||||
| extern void _PySignal_AfterFork(void); | extern void _PySignal_AfterFork(void); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -41,15 +41,11 @@ struct _gilstate_runtime_state { | ||||||
|     /* bpo-26558: Flag to disable PyGILState_Check().
 |     /* bpo-26558: Flag to disable PyGILState_Check().
 | ||||||
|        If set to non-zero, PyGILState_Check() always return 1. */ |        If set to non-zero, PyGILState_Check() always return 1. */ | ||||||
|     int check_enabled; |     int check_enabled; | ||||||
|     /* Assuming the current thread holds the GIL, this is the
 |  | ||||||
|        PyThreadState for the current thread. */ |  | ||||||
|     _Py_atomic_address tstate_current; |  | ||||||
|     /* The single PyInterpreterState used by this process'
 |     /* The single PyInterpreterState used by this process'
 | ||||||
|        GILState implementation |        GILState implementation | ||||||
|     */ |     */ | ||||||
|     /* TODO: Given interp_main, it may be possible to kill this ref */ |     /* TODO: Given interp_main, it may be possible to kill this ref */ | ||||||
|     PyInterpreterState *autoInterpreterState; |     PyInterpreterState *autoInterpreterState; | ||||||
|     Py_tss_t autoTSSkey; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* Runtime audit hook state */ | /* Runtime audit hook state */ | ||||||
|  | @ -124,6 +120,12 @@ typedef struct pyruntimestate { | ||||||
| 
 | 
 | ||||||
|     unsigned long main_thread; |     unsigned long main_thread; | ||||||
| 
 | 
 | ||||||
|  |     /* Assuming the current thread holds the GIL, this is the
 | ||||||
|  |        PyThreadState for the current thread. */ | ||||||
|  |     _Py_atomic_address tstate_current; | ||||||
|  |     /* Used for the thread state bound to the current thread. */ | ||||||
|  |     Py_tss_t autoTSSkey; | ||||||
|  | 
 | ||||||
|     PyWideStringList orig_argv; |     PyWideStringList orig_argv; | ||||||
| 
 | 
 | ||||||
|     struct _parser_runtime_state parser; |     struct _parser_runtime_state parser; | ||||||
|  |  | ||||||
|  | @ -33,6 +33,9 @@ extern "C" { | ||||||
|               until _PyInterpreterState_Enable() is called. */ \ |               until _PyInterpreterState_Enable() is called. */ \ | ||||||
|             .next_id = -1, \ |             .next_id = -1, \ | ||||||
|         }, \ |         }, \ | ||||||
|  |         /* A TSS key must be initialized with Py_tss_NEEDS_INIT \
 | ||||||
|  |            in accordance with the specification. */ \ | ||||||
|  |         .autoTSSkey = Py_tss_NEEDS_INIT, \ | ||||||
|         .parser = _parser_runtime_state_INIT, \ |         .parser = _parser_runtime_state_INIT, \ | ||||||
|         .imports = { \ |         .imports = { \ | ||||||
|             .lock = { \ |             .lock = { \ | ||||||
|  | @ -49,9 +52,6 @@ extern "C" { | ||||||
|         }, \ |         }, \ | ||||||
|         .gilstate = { \ |         .gilstate = { \ | ||||||
|             .check_enabled = 1, \ |             .check_enabled = 1, \ | ||||||
|             /* A TSS key must be initialized with Py_tss_NEEDS_INIT \
 |  | ||||||
|                in accordance with the specification. */ \ |  | ||||||
|             .autoTSSkey = Py_tss_NEEDS_INIT, \ |  | ||||||
|         }, \ |         }, \ | ||||||
|         .dtoa = _dtoa_runtime_state_INIT(runtime), \ |         .dtoa = _dtoa_runtime_state_INIT(runtime), \ | ||||||
|         .fileutils = { \ |         .fileutils = { \ | ||||||
|  |  | ||||||
|  | @ -1074,13 +1074,7 @@ thread_run(void *boot_raw) | ||||||
|     PyThreadState *tstate; |     PyThreadState *tstate; | ||||||
| 
 | 
 | ||||||
|     tstate = boot->tstate; |     tstate = boot->tstate; | ||||||
|     tstate->thread_id = PyThread_get_thread_ident(); |     _PyThreadState_Bind(tstate); | ||||||
| #ifdef PY_HAVE_THREAD_NATIVE_ID |  | ||||||
|     tstate->native_thread_id = PyThread_get_thread_native_id(); |  | ||||||
| #else |  | ||||||
|     tstate->native_thread_id = 0; |  | ||||||
| #endif |  | ||||||
|     _PyThreadState_SetCurrent(tstate); |  | ||||||
|     PyEval_AcquireThread(tstate); |     PyEval_AcquireThread(tstate); | ||||||
|     tstate->interp->threads.count++; |     tstate->interp->threads.count++; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -587,7 +587,7 @@ PyOS_AfterFork_Child(void) | ||||||
|     PyStatus status; |     PyStatus status; | ||||||
|     _PyRuntimeState *runtime = &_PyRuntime; |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
| 
 | 
 | ||||||
|     status = _PyGILState_Reinit(runtime); |     status = _PyRuntimeState_ReInitThreads(runtime); | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|         goto fatal_error; |         goto fatal_error; | ||||||
|     } |     } | ||||||
|  | @ -611,11 +611,6 @@ PyOS_AfterFork_Child(void) | ||||||
| 
 | 
 | ||||||
|     _PySignal_AfterFork(); |     _PySignal_AfterFork(); | ||||||
| 
 | 
 | ||||||
|     status = _PyRuntimeState_ReInitThreads(runtime); |  | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |  | ||||||
|         goto fatal_error; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     status = _PyInterpreterState_DeleteExceptMain(runtime); |     status = _PyInterpreterState_DeleteExceptMain(runtime); | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|         goto fatal_error; |         goto fatal_error; | ||||||
|  |  | ||||||
|  | @ -581,8 +581,7 @@ PyEval_AcquireThread(PyThreadState *tstate) | ||||||
| 
 | 
 | ||||||
|     take_gil(tstate); |     take_gil(tstate); | ||||||
| 
 | 
 | ||||||
|     struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate; |     if (_PyThreadState_Swap(tstate->interp->runtime, tstate) != NULL) { | ||||||
|     if (_PyThreadState_Swap(gilstate, tstate) != NULL) { |  | ||||||
|         Py_FatalError("non-NULL old thread state"); |         Py_FatalError("non-NULL old thread state"); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -593,7 +592,7 @@ PyEval_ReleaseThread(PyThreadState *tstate) | ||||||
|     assert(is_tstate_valid(tstate)); |     assert(is_tstate_valid(tstate)); | ||||||
| 
 | 
 | ||||||
|     _PyRuntimeState *runtime = tstate->interp->runtime; |     _PyRuntimeState *runtime = tstate->interp->runtime; | ||||||
|     PyThreadState *new_tstate = _PyThreadState_Swap(&runtime->gilstate, NULL); |     PyThreadState *new_tstate = _PyThreadState_Swap(runtime, NULL); | ||||||
|     if (new_tstate != tstate) { |     if (new_tstate != tstate) { | ||||||
|         Py_FatalError("wrong thread state"); |         Py_FatalError("wrong thread state"); | ||||||
|     } |     } | ||||||
|  | @ -643,7 +642,7 @@ PyThreadState * | ||||||
| PyEval_SaveThread(void) | PyEval_SaveThread(void) | ||||||
| { | { | ||||||
|     _PyRuntimeState *runtime = &_PyRuntime; |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|     PyThreadState *tstate = _PyThreadState_Swap(&runtime->gilstate, NULL); |     PyThreadState *tstate = _PyThreadState_Swap(runtime, NULL); | ||||||
|     _Py_EnsureTstateNotNULL(tstate); |     _Py_EnsureTstateNotNULL(tstate); | ||||||
| 
 | 
 | ||||||
|     struct _ceval_runtime_state *ceval = &runtime->ceval; |     struct _ceval_runtime_state *ceval = &runtime->ceval; | ||||||
|  | @ -660,8 +659,7 @@ PyEval_RestoreThread(PyThreadState *tstate) | ||||||
| 
 | 
 | ||||||
|     take_gil(tstate); |     take_gil(tstate); | ||||||
| 
 | 
 | ||||||
|     struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate; |     _PyThreadState_Swap(tstate->interp->runtime, tstate); | ||||||
|     _PyThreadState_Swap(gilstate, tstate); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -965,7 +963,7 @@ _Py_HandlePending(PyThreadState *tstate) | ||||||
|     /* GIL drop request */ |     /* GIL drop request */ | ||||||
|     if (_Py_atomic_load_relaxed_int32(&interp_ceval_state->gil_drop_request)) { |     if (_Py_atomic_load_relaxed_int32(&interp_ceval_state->gil_drop_request)) { | ||||||
|         /* Give another thread a chance */ |         /* Give another thread a chance */ | ||||||
|         if (_PyThreadState_Swap(&runtime->gilstate, NULL) != tstate) { |         if (_PyThreadState_Swap(runtime, NULL) != tstate) { | ||||||
|             Py_FatalError("tstate mix-up"); |             Py_FatalError("tstate mix-up"); | ||||||
|         } |         } | ||||||
|         drop_gil(ceval, interp_ceval_state, tstate); |         drop_gil(ceval, interp_ceval_state, tstate); | ||||||
|  | @ -974,7 +972,7 @@ _Py_HandlePending(PyThreadState *tstate) | ||||||
| 
 | 
 | ||||||
|         take_gil(tstate); |         take_gil(tstate); | ||||||
| 
 | 
 | ||||||
|         if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) { |         if (_PyThreadState_Swap(runtime, tstate) != NULL) { | ||||||
|             Py_FatalError("orphan tstate"); |             Py_FatalError("orphan tstate"); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -675,12 +675,7 @@ pycore_create_interpreter(_PyRuntimeState *runtime, | ||||||
|                           const PyConfig *src_config, |                           const PyConfig *src_config, | ||||||
|                           PyThreadState **tstate_p) |                           PyThreadState **tstate_p) | ||||||
| { | { | ||||||
|     /* Auto-thread-state API */ |     PyStatus status; | ||||||
|     PyStatus status = _PyGILState_Init(runtime); |  | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |  | ||||||
|         return status; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     PyInterpreterState *interp = PyInterpreterState_New(); |     PyInterpreterState *interp = PyInterpreterState_New(); | ||||||
|     if (interp == NULL) { |     if (interp == NULL) { | ||||||
|         return _PyStatus_ERR("can't make main interpreter"); |         return _PyStatus_ERR("can't make main interpreter"); | ||||||
|  | @ -692,6 +687,12 @@ pycore_create_interpreter(_PyRuntimeState *runtime, | ||||||
|         return status; |         return status; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /* Auto-thread-state API */ | ||||||
|  |     status = _PyGILState_Init(interp); | ||||||
|  |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|  |         return status; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     const _PyInterpreterConfig config = _PyInterpreterConfig_LEGACY_INIT; |     const _PyInterpreterConfig config = _PyInterpreterConfig_LEGACY_INIT; | ||||||
|     init_interp_settings(interp, &config); |     init_interp_settings(interp, &config); | ||||||
| 
 | 
 | ||||||
|  | @ -1795,10 +1796,8 @@ finalize_interp_clear(PyThreadState *tstate) | ||||||
| static void | static void | ||||||
| finalize_interp_delete(PyInterpreterState *interp) | finalize_interp_delete(PyInterpreterState *interp) | ||||||
| { | { | ||||||
|     if (_Py_IsMainInterpreter(interp)) { |  | ||||||
|     /* Cleanup auto-thread-state */ |     /* Cleanup auto-thread-state */ | ||||||
|     _PyGILState_Fini(interp); |     _PyGILState_Fini(interp); | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     /* We can't call _PyEval_FiniGIL() here because destroying the GIL lock can
 |     /* We can't call _PyEval_FiniGIL() here because destroying the GIL lock can
 | ||||||
|        fail when it is being awaited by another running daemon thread (see |        fail when it is being awaited by another running daemon thread (see | ||||||
|  |  | ||||||
							
								
								
									
										530
									
								
								Python/pystate.c
									
										
									
									
									
								
							
							
						
						
									
										530
									
								
								Python/pystate.c
									
										
									
									
									
								
							|  | @ -10,7 +10,7 @@ | ||||||
| #include "pycore_pyerrors.h" | #include "pycore_pyerrors.h" | ||||||
| #include "pycore_pylifecycle.h" | #include "pycore_pylifecycle.h" | ||||||
| #include "pycore_pymem.h"         // _PyMem_SetDefaultAllocator() | #include "pycore_pymem.h"         // _PyMem_SetDefaultAllocator() | ||||||
| #include "pycore_pystate.h"       // _PyThreadState_GET() | #include "pycore_pystate.h" | ||||||
| #include "pycore_runtime_init.h"  // _PyRuntimeState_INIT | #include "pycore_runtime_init.h"  // _PyRuntimeState_INIT | ||||||
| #include "pycore_sysmodule.h" | #include "pycore_sysmodule.h" | ||||||
| 
 | 
 | ||||||
|  | @ -37,16 +37,205 @@ to avoid the expense of doing their own locking). | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #define _PyRuntimeGILState_GetThreadState(gilstate) \ |  | ||||||
|     ((PyThreadState*)_Py_atomic_load_relaxed(&(gilstate)->tstate_current)) |  | ||||||
| #define _PyRuntimeGILState_SetThreadState(gilstate, value) \ |  | ||||||
|     _Py_atomic_store_relaxed(&(gilstate)->tstate_current, \ |  | ||||||
|                              (uintptr_t)(value)) |  | ||||||
| 
 |  | ||||||
| /* Forward declarations */ | /* Forward declarations */ | ||||||
| static PyThreadState *_PyGILState_GetThisThreadState(struct _gilstate_runtime_state *gilstate); |  | ||||||
| static void _PyThreadState_Delete(PyThreadState *tstate, int check_current); | static void _PyThreadState_Delete(PyThreadState *tstate, int check_current); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | /* the current thread state */ | ||||||
|  | 
 | ||||||
|  | static inline PyThreadState * | ||||||
|  | current_fast_get(_PyRuntimeState *runtime) | ||||||
|  | { | ||||||
|  |     // The GIL must be held by the current thread.
 | ||||||
|  |     return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->tstate_current); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void | ||||||
|  | current_fast_set(_PyRuntimeState *runtime, PyThreadState *tstate) | ||||||
|  | { | ||||||
|  |     // The GIL must be held by the current thread.
 | ||||||
|  |     assert(tstate != NULL); | ||||||
|  |     _Py_atomic_store_relaxed(&runtime->tstate_current, (uintptr_t)tstate); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void | ||||||
|  | current_fast_clear(_PyRuntimeState *runtime) | ||||||
|  | { | ||||||
|  |     // The GIL must be held by the current thread.
 | ||||||
|  |     _Py_atomic_store_relaxed(&runtime->tstate_current, (uintptr_t)NULL); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | current_tss_initialized(_PyRuntimeState *runtime) | ||||||
|  | { | ||||||
|  |     return PyThread_tss_is_created(&runtime->autoTSSkey); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static PyStatus | ||||||
|  | current_tss_init(_PyRuntimeState *runtime) | ||||||
|  | { | ||||||
|  |     assert(!current_tss_initialized(runtime)); | ||||||
|  |     if (PyThread_tss_create(&runtime->autoTSSkey) != 0) { | ||||||
|  |         return _PyStatus_NO_MEMORY(); | ||||||
|  |     } | ||||||
|  |     return _PyStatus_OK(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | current_tss_fini(_PyRuntimeState *runtime) | ||||||
|  | { | ||||||
|  |     assert(current_tss_initialized(runtime)); | ||||||
|  |     PyThread_tss_delete(&runtime->autoTSSkey); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline PyThreadState * | ||||||
|  | current_tss_get(_PyRuntimeState *runtime) | ||||||
|  | { | ||||||
|  |     assert(current_tss_initialized(runtime)); | ||||||
|  |     return (PyThreadState *)PyThread_tss_get(&runtime->autoTSSkey); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline int | ||||||
|  | _current_tss_set(_PyRuntimeState *runtime, PyThreadState *tstate) | ||||||
|  | { | ||||||
|  |     assert(tstate != NULL); | ||||||
|  |     assert(current_tss_initialized(runtime)); | ||||||
|  |     return PyThread_tss_set(&runtime->autoTSSkey, (void *)tstate); | ||||||
|  | } | ||||||
|  | static inline void | ||||||
|  | current_tss_set(_PyRuntimeState *runtime, PyThreadState *tstate) | ||||||
|  | { | ||||||
|  |     if (_current_tss_set(runtime, tstate) != 0) { | ||||||
|  |         Py_FatalError("failed to set current tstate (TSS)"); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void | ||||||
|  | current_tss_clear(_PyRuntimeState *runtime) | ||||||
|  | { | ||||||
|  |     assert(current_tss_initialized(runtime)); | ||||||
|  |     if (PyThread_tss_set(&runtime->autoTSSkey, NULL) != 0) { | ||||||
|  |         Py_FatalError("failed to clear current tstate (TSS)"); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #ifdef HAVE_FORK | ||||||
|  | /* Reset the TSS key - called by PyOS_AfterFork_Child().
 | ||||||
|  |  * This should not be necessary, but some - buggy - pthread implementations | ||||||
|  |  * don't reset TSS upon fork(), see issue #10517. | ||||||
|  |  */ | ||||||
|  | static PyStatus | ||||||
|  | current_tss_reinit(_PyRuntimeState *runtime) | ||||||
|  | { | ||||||
|  |     if (!current_tss_initialized(runtime)) { | ||||||
|  |         return _PyStatus_OK(); | ||||||
|  |     } | ||||||
|  |     PyThreadState *tstate = current_tss_get(runtime); | ||||||
|  | 
 | ||||||
|  |     current_tss_fini(runtime); | ||||||
|  |     PyStatus status = current_tss_init(runtime); | ||||||
|  |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|  |         return status; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* If the thread had an associated auto thread state, reassociate it with
 | ||||||
|  |      * the new key. */ | ||||||
|  |     if (tstate && _current_tss_set(runtime, tstate) != 0) { | ||||||
|  |         return _PyStatus_ERR("failed to set autoTSSkey"); | ||||||
|  |     } | ||||||
|  |     return _PyStatus_OK(); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | bind_tstate(PyThreadState *tstate) | ||||||
|  | { | ||||||
|  |     assert(tstate != NULL); | ||||||
|  |     assert(tstate->_status == PyThreadState_INITIALIZED); | ||||||
|  |     assert(tstate->thread_id == 0); | ||||||
|  |     assert(tstate->native_thread_id == 0); | ||||||
|  |     _PyRuntimeState *runtime = tstate->interp->runtime; | ||||||
|  | 
 | ||||||
|  |     /* Stick the thread state for this thread in thread specific storage.
 | ||||||
|  | 
 | ||||||
|  |        The only situation where you can legitimately have more than one | ||||||
|  |        thread state for an OS level thread is when there are multiple | ||||||
|  |        interpreters. | ||||||
|  | 
 | ||||||
|  |        You shouldn't really be using the PyGILState_ APIs anyway (see issues | ||||||
|  |        #10915 and #15751). | ||||||
|  | 
 | ||||||
|  |        The first thread state created for that given OS level thread will | ||||||
|  |        "win", which seems reasonable behaviour. | ||||||
|  |     */ | ||||||
|  |     /* When a thread state is created for a thread by some mechanism
 | ||||||
|  |        other than PyGILState_Ensure(), it's important that the GILState | ||||||
|  |        machinery knows about it so it doesn't try to create another | ||||||
|  |        thread state for the thread. | ||||||
|  |        (This is a better fix for SF bug #1010677 than the first one attempted.) | ||||||
|  |     */ | ||||||
|  |     // XXX Skipping like this does not play nice with multiple interpreters.
 | ||||||
|  |     if (current_tss_get(runtime) == NULL) { | ||||||
|  |         current_tss_set(runtime, tstate); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     tstate->thread_id = PyThread_get_thread_ident(); | ||||||
|  | #ifdef PY_HAVE_THREAD_NATIVE_ID | ||||||
|  |     tstate->native_thread_id = PyThread_get_thread_native_id(); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     tstate->_status = PyThreadState_BOUND; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | unbind_tstate(PyThreadState *tstate) | ||||||
|  | { | ||||||
|  |     assert(tstate != NULL); | ||||||
|  |     assert(tstate->_status == PyThreadState_BOUND); | ||||||
|  |     assert(tstate->thread_id > 0); | ||||||
|  | #ifdef PY_HAVE_THREAD_NATIVE_ID | ||||||
|  |     assert(tstate->native_thread_id > 0); | ||||||
|  | #endif | ||||||
|  |     _PyRuntimeState *runtime = tstate->interp->runtime; | ||||||
|  | 
 | ||||||
|  |     if (current_tss_initialized(runtime) && | ||||||
|  |         tstate == current_tss_get(runtime)) | ||||||
|  |     { | ||||||
|  |         current_tss_clear(runtime); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // We leave thread_id and native_thraed_id alone
 | ||||||
|  |     // since they can be useful for debugging.
 | ||||||
|  |     // Check the `_status` field to know if these values
 | ||||||
|  |     // are still valid.
 | ||||||
|  | 
 | ||||||
|  |     tstate->_status = PyThreadState_UNBOUND; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* This is not exported, as it is not reliable!  It can only
 | ||||||
|  |    ever be compared to the state for the *current* thread. | ||||||
|  |    * If not equal, then it doesn't matter that the actual | ||||||
|  |      value may change immediately after comparison, as it can't | ||||||
|  |      possibly change to the current thread's state. | ||||||
|  |    * If equal, then the current thread holds the lock, so the value can't | ||||||
|  |      change until we yield the lock. | ||||||
|  | */ | ||||||
|  | static int | ||||||
|  | holds_gil(PyThreadState *tstate) | ||||||
|  | { | ||||||
|  |     // XXX Fall back to tstate->interp->runtime->ceval.gil.last_holder
 | ||||||
|  |     // (and tstate->interp->runtime->ceval.gil.locked).
 | ||||||
|  |     assert(tstate != NULL); | ||||||
|  |     _PyRuntimeState *runtime = tstate->interp->runtime; | ||||||
|  |     /* Must be the tstate for this thread */ | ||||||
|  |     assert(tstate == current_tss_get(runtime)); | ||||||
|  |     return tstate == current_fast_get(runtime); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* the global runtime */ | ||||||
|  | 
 | ||||||
| /* Suppress deprecation warning for PyBytesObject.ob_shash */ | /* Suppress deprecation warning for PyBytesObject.ob_shash */ | ||||||
| _Py_COMP_DIAG_PUSH | _Py_COMP_DIAG_PUSH | ||||||
| _Py_COMP_DIAG_IGNORE_DEPR_DECLS | _Py_COMP_DIAG_IGNORE_DEPR_DECLS | ||||||
|  | @ -166,6 +355,13 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime) | ||||||
|         // Reset to _PyRuntimeState_INIT.
 |         // Reset to _PyRuntimeState_INIT.
 | ||||||
|         memcpy(runtime, &initial, sizeof(*runtime)); |         memcpy(runtime, &initial, sizeof(*runtime)); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     PyStatus status = current_tss_init(runtime); | ||||||
|  |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|  |         _PyRuntimeState_Fini(runtime); | ||||||
|  |         return status; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     init_runtime(runtime, open_code_hook, open_code_userdata, audit_hook_head, |     init_runtime(runtime, open_code_hook, open_code_userdata, audit_hook_head, | ||||||
|                  unicode_next_index, lock1, lock2, lock3, lock4); |                  unicode_next_index, lock1, lock2, lock3, lock4); | ||||||
| 
 | 
 | ||||||
|  | @ -175,6 +371,10 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime) | ||||||
| void | void | ||||||
| _PyRuntimeState_Fini(_PyRuntimeState *runtime) | _PyRuntimeState_Fini(_PyRuntimeState *runtime) | ||||||
| { | { | ||||||
|  |     if (current_tss_initialized(runtime)) { | ||||||
|  |         current_tss_fini(runtime); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /* Force the allocator used by _PyRuntimeState_Init(). */ |     /* Force the allocator used by _PyRuntimeState_Init(). */ | ||||||
|     PyMemAllocatorEx old_alloc; |     PyMemAllocatorEx old_alloc; | ||||||
|     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); | ||||||
|  | @ -227,15 +427,17 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime) | ||||||
|         return _PyStatus_ERR("Failed to reinitialize runtime locks"); |         return _PyStatus_ERR("Failed to reinitialize runtime locks"); | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     PyStatus status = current_tss_reinit(runtime); | ||||||
|  |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|  |         return status; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     return _PyStatus_OK(); |     return _PyStatus_OK(); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Forward declaration */ |  | ||||||
| static void _PyGILState_NoteThreadState( |  | ||||||
|     struct _gilstate_runtime_state *gilstate, PyThreadState* tstate); |  | ||||||
| 
 |  | ||||||
| PyStatus | PyStatus | ||||||
| _PyInterpreterState_Enable(_PyRuntimeState *runtime) | _PyInterpreterState_Enable(_PyRuntimeState *runtime) | ||||||
| { | { | ||||||
|  | @ -318,7 +520,8 @@ PyInterpreterState * | ||||||
| PyInterpreterState_New(void) | PyInterpreterState_New(void) | ||||||
| { | { | ||||||
|     PyInterpreterState *interp; |     PyInterpreterState *interp; | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|  |     PyThreadState *tstate = current_fast_get(runtime); | ||||||
| 
 | 
 | ||||||
|     /* tstate is NULL when Py_InitializeFromConfig() calls
 |     /* tstate is NULL when Py_InitializeFromConfig() calls
 | ||||||
|        PyInterpreterState_New() to create the main interpreter. */ |        PyInterpreterState_New() to create the main interpreter. */ | ||||||
|  | @ -335,7 +538,6 @@ PyInterpreterState_New(void) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Don't get runtime from tstate since tstate can be NULL. */ |     /* Don't get runtime from tstate since tstate can be NULL. */ | ||||||
|     _PyRuntimeState *runtime = &_PyRuntime; |  | ||||||
|     struct pyinterpreters *interpreters = &runtime->interpreters; |     struct pyinterpreters *interpreters = &runtime->interpreters; | ||||||
| 
 | 
 | ||||||
|     /* We completely serialize creation of multiple interpreters, since
 |     /* We completely serialize creation of multiple interpreters, since
 | ||||||
|  | @ -483,7 +685,7 @@ PyInterpreterState_Clear(PyInterpreterState *interp) | ||||||
|     // Use the current Python thread state to call audit hooks and to collect
 |     // Use the current Python thread state to call audit hooks and to collect
 | ||||||
|     // garbage. It can be different than the current Python thread state
 |     // garbage. It can be different than the current Python thread state
 | ||||||
|     // of 'interp'.
 |     // of 'interp'.
 | ||||||
|     PyThreadState *current_tstate = _PyThreadState_GET(); |     PyThreadState *current_tstate = current_fast_get(interp->runtime); | ||||||
| 
 | 
 | ||||||
|     interpreter_clear(interp, current_tstate); |     interpreter_clear(interp, current_tstate); | ||||||
| } | } | ||||||
|  | @ -518,7 +720,7 @@ PyInterpreterState_Delete(PyInterpreterState *interp) | ||||||
|     _PyEval_FiniState(&interp->ceval); |     _PyEval_FiniState(&interp->ceval); | ||||||
| 
 | 
 | ||||||
|     /* Delete current thread. After this, many C API calls become crashy. */ |     /* Delete current thread. After this, many C API calls become crashy. */ | ||||||
|     _PyThreadState_Swap(&runtime->gilstate, NULL); |     _PyThreadState_Swap(runtime, NULL); | ||||||
| 
 | 
 | ||||||
|     HEAD_LOCK(runtime); |     HEAD_LOCK(runtime); | ||||||
|     PyInterpreterState **p; |     PyInterpreterState **p; | ||||||
|  | @ -558,10 +760,9 @@ PyInterpreterState_Delete(PyInterpreterState *interp) | ||||||
| PyStatus | PyStatus | ||||||
| _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) | _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) | ||||||
| { | { | ||||||
|     struct _gilstate_runtime_state *gilstate = &runtime->gilstate; |  | ||||||
|     struct pyinterpreters *interpreters = &runtime->interpreters; |     struct pyinterpreters *interpreters = &runtime->interpreters; | ||||||
| 
 | 
 | ||||||
|     PyThreadState *tstate = _PyThreadState_Swap(gilstate, NULL); |     PyThreadState *tstate = _PyThreadState_Swap(runtime, NULL); | ||||||
|     if (tstate != NULL && tstate->interp != interpreters->main) { |     if (tstate != NULL && tstate->interp != interpreters->main) { | ||||||
|         return _PyStatus_ERR("not main interpreter"); |         return _PyStatus_ERR("not main interpreter"); | ||||||
|     } |     } | ||||||
|  | @ -591,7 +792,7 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) | ||||||
|     if (interpreters->head == NULL) { |     if (interpreters->head == NULL) { | ||||||
|         return _PyStatus_ERR("missing main interpreter"); |         return _PyStatus_ERR("missing main interpreter"); | ||||||
|     } |     } | ||||||
|     _PyThreadState_Swap(gilstate, tstate); |     _PyThreadState_Swap(runtime, tstate); | ||||||
|     return _PyStatus_OK(); |     return _PyStatus_OK(); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | @ -600,7 +801,7 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) | ||||||
| PyInterpreterState * | PyInterpreterState * | ||||||
| PyInterpreterState_Get(void) | PyInterpreterState_Get(void) | ||||||
| { | { | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     PyThreadState *tstate = current_fast_get(&_PyRuntime); | ||||||
|     _Py_EnsureTstateNotNULL(tstate); |     _Py_EnsureTstateNotNULL(tstate); | ||||||
|     PyInterpreterState *interp = tstate->interp; |     PyInterpreterState *interp = tstate->interp; | ||||||
|     if (interp == NULL) { |     if (interp == NULL) { | ||||||
|  | @ -691,8 +892,8 @@ void | ||||||
| _PyInterpreterState_IDDecref(PyInterpreterState *interp) | _PyInterpreterState_IDDecref(PyInterpreterState *interp) | ||||||
| { | { | ||||||
|     assert(interp->id_mutex != NULL); |     assert(interp->id_mutex != NULL); | ||||||
|  |     _PyRuntimeState *runtime = interp->runtime; | ||||||
| 
 | 
 | ||||||
|     struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; |  | ||||||
|     PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); |     PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); | ||||||
|     assert(interp->id_refcount != 0); |     assert(interp->id_refcount != 0); | ||||||
|     interp->id_refcount -= 1; |     interp->id_refcount -= 1; | ||||||
|  | @ -703,9 +904,9 @@ _PyInterpreterState_IDDecref(PyInterpreterState *interp) | ||||||
|         // XXX Using the "head" thread isn't strictly correct.
 |         // XXX Using the "head" thread isn't strictly correct.
 | ||||||
|         PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); |         PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); | ||||||
|         // XXX Possible GILState issues?
 |         // XXX Possible GILState issues?
 | ||||||
|         PyThreadState *save_tstate = _PyThreadState_Swap(gilstate, tstate); |         PyThreadState *save_tstate = _PyThreadState_Swap(runtime, tstate); | ||||||
|         Py_EndInterpreter(tstate); |         Py_EndInterpreter(tstate); | ||||||
|         _PyThreadState_Swap(gilstate, save_tstate); |         _PyThreadState_Swap(runtime, save_tstate); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -790,7 +991,7 @@ init_threadstate(PyThreadState *tstate, | ||||||
|                  PyInterpreterState *interp, uint64_t id, |                  PyInterpreterState *interp, uint64_t id, | ||||||
|                  PyThreadState *next) |                  PyThreadState *next) | ||||||
| { | { | ||||||
|     if (tstate->_initialized) { |     if (tstate->_status != PyThreadState_UNINITIALIZED) { | ||||||
|         Py_FatalError("thread state already initialized"); |         Py_FatalError("thread state already initialized"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -809,10 +1010,7 @@ init_threadstate(PyThreadState *tstate, | ||||||
|     tstate->next = next; |     tstate->next = next; | ||||||
|     assert(tstate->prev == NULL); |     assert(tstate->prev == NULL); | ||||||
| 
 | 
 | ||||||
|     tstate->thread_id = PyThread_get_thread_ident(); |     // thread_id and native_thread_id are set in bind_tstate().
 | ||||||
| #ifdef PY_HAVE_THREAD_NATIVE_ID |  | ||||||
|     tstate->native_thread_id = PyThread_get_thread_native_id(); |  | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
|     tstate->py_recursion_limit = interp->ceval.recursion_limit, |     tstate->py_recursion_limit = interp->ceval.recursion_limit, | ||||||
|     tstate->py_recursion_remaining = interp->ceval.recursion_limit, |     tstate->py_recursion_remaining = interp->ceval.recursion_limit, | ||||||
|  | @ -820,12 +1018,16 @@ init_threadstate(PyThreadState *tstate, | ||||||
| 
 | 
 | ||||||
|     tstate->exc_info = &tstate->exc_state; |     tstate->exc_info = &tstate->exc_state; | ||||||
| 
 | 
 | ||||||
|  |     // PyGILState_Release must not try to delete this thread state.
 | ||||||
|  |     // This is cleared when PyGILState_Ensure() creates the thread sate.
 | ||||||
|  |     tstate->gilstate_counter = 1; | ||||||
|  | 
 | ||||||
|     tstate->cframe = &tstate->root_cframe; |     tstate->cframe = &tstate->root_cframe; | ||||||
|     tstate->datastack_chunk = NULL; |     tstate->datastack_chunk = NULL; | ||||||
|     tstate->datastack_top = NULL; |     tstate->datastack_top = NULL; | ||||||
|     tstate->datastack_limit = NULL; |     tstate->datastack_limit = NULL; | ||||||
| 
 | 
 | ||||||
|     tstate->_initialized = 1; |     tstate->_status = PyThreadState_INITIALIZED; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static PyThreadState * | static PyThreadState * | ||||||
|  | @ -884,11 +1086,12 @@ PyThreadState_New(PyInterpreterState *interp) | ||||||
| { | { | ||||||
|     PyThreadState *tstate = new_threadstate(interp); |     PyThreadState *tstate = new_threadstate(interp); | ||||||
|     if (tstate) { |     if (tstate) { | ||||||
|         _PyThreadState_SetCurrent(tstate); |         bind_tstate(tstate); | ||||||
|     } |     } | ||||||
|     return tstate; |     return tstate; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // This must be followed by a call to _PyThreadState_Bind();
 | ||||||
| PyThreadState * | PyThreadState * | ||||||
| _PyThreadState_Prealloc(PyInterpreterState *interp) | _PyThreadState_Prealloc(PyInterpreterState *interp) | ||||||
| { | { | ||||||
|  | @ -904,9 +1107,9 @@ _PyThreadState_Init(PyThreadState *tstate) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| _PyThreadState_SetCurrent(PyThreadState *tstate) | _PyThreadState_Bind(PyThreadState *tstate) | ||||||
| { | { | ||||||
|     _PyGILState_NoteThreadState(&tstate->interp->runtime->gilstate, tstate); |     bind_tstate(tstate); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PyObject* | PyObject* | ||||||
|  | @ -968,7 +1171,7 @@ PyState_AddModule(PyObject* module, PyModuleDef* def) | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     PyThreadState *tstate = current_fast_get(&_PyRuntime); | ||||||
|     PyInterpreterState *interp = tstate->interp; |     PyInterpreterState *interp = tstate->interp; | ||||||
|     Py_ssize_t index = def->m_base.m_index; |     Py_ssize_t index = def->m_base.m_index; | ||||||
|     if (interp->modules_by_index && |     if (interp->modules_by_index && | ||||||
|  | @ -984,7 +1187,7 @@ PyState_AddModule(PyObject* module, PyModuleDef* def) | ||||||
| int | int | ||||||
| PyState_RemoveModule(PyModuleDef* def) | PyState_RemoveModule(PyModuleDef* def) | ||||||
| { | { | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     PyThreadState *tstate = current_fast_get(&_PyRuntime); | ||||||
|     PyInterpreterState *interp = tstate->interp; |     PyInterpreterState *interp = tstate->interp; | ||||||
| 
 | 
 | ||||||
|     if (def->m_slots) { |     if (def->m_slots) { | ||||||
|  | @ -1089,8 +1292,7 @@ PyThreadState_Clear(PyThreadState *tstate) | ||||||
| 
 | 
 | ||||||
| /* Common code for PyThreadState_Delete() and PyThreadState_DeleteCurrent() */ | /* Common code for PyThreadState_Delete() and PyThreadState_DeleteCurrent() */ | ||||||
| static void | static void | ||||||
| tstate_delete_common(PyThreadState *tstate, | tstate_delete_common(PyThreadState *tstate) | ||||||
|                      struct _gilstate_runtime_state *gilstate) |  | ||||||
| { | { | ||||||
|     _Py_EnsureTstateNotNULL(tstate); |     _Py_EnsureTstateNotNULL(tstate); | ||||||
|     PyInterpreterState *interp = tstate->interp; |     PyInterpreterState *interp = tstate->interp; | ||||||
|  | @ -1111,11 +1313,10 @@ tstate_delete_common(PyThreadState *tstate, | ||||||
|     } |     } | ||||||
|     HEAD_UNLOCK(runtime); |     HEAD_UNLOCK(runtime); | ||||||
| 
 | 
 | ||||||
|     if (gilstate->autoInterpreterState && |     // XXX Do this in PyThreadState_Swap() (and assert not-equal here)?
 | ||||||
|         PyThread_tss_get(&gilstate->autoTSSkey) == tstate) |     unbind_tstate(tstate); | ||||||
|     { | 
 | ||||||
|         PyThread_tss_set(&gilstate->autoTSSkey, NULL); |     // XXX Move to PyThreadState_Clear()?
 | ||||||
|     } |  | ||||||
|     _PyStackChunk *chunk = tstate->datastack_chunk; |     _PyStackChunk *chunk = tstate->datastack_chunk; | ||||||
|     tstate->datastack_chunk = NULL; |     tstate->datastack_chunk = NULL; | ||||||
|     while (chunk != NULL) { |     while (chunk != NULL) { | ||||||
|  | @ -1128,13 +1329,12 @@ tstate_delete_common(PyThreadState *tstate, | ||||||
| static void | static void | ||||||
| _PyThreadState_Delete(PyThreadState *tstate, int check_current) | _PyThreadState_Delete(PyThreadState *tstate, int check_current) | ||||||
| { | { | ||||||
|     struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate; |  | ||||||
|     if (check_current) { |     if (check_current) { | ||||||
|         if (tstate == _PyRuntimeGILState_GetThreadState(gilstate)) { |         if (tstate == current_fast_get(tstate->interp->runtime)) { | ||||||
|             _Py_FatalErrorFormat(__func__, "tstate %p is still current", tstate); |             _Py_FatalErrorFormat(__func__, "tstate %p is still current", tstate); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     tstate_delete_common(tstate, gilstate); |     tstate_delete_common(tstate); | ||||||
|     free_threadstate(tstate); |     free_threadstate(tstate); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1150,9 +1350,8 @@ void | ||||||
| _PyThreadState_DeleteCurrent(PyThreadState *tstate) | _PyThreadState_DeleteCurrent(PyThreadState *tstate) | ||||||
| { | { | ||||||
|     _Py_EnsureTstateNotNULL(tstate); |     _Py_EnsureTstateNotNULL(tstate); | ||||||
|     struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate; |     tstate_delete_common(tstate); | ||||||
|     tstate_delete_common(tstate, gilstate); |     current_fast_clear(tstate->interp->runtime); | ||||||
|     _PyRuntimeGILState_SetThreadState(gilstate, NULL); |  | ||||||
|     _PyEval_ReleaseLock(tstate); |     _PyEval_ReleaseLock(tstate); | ||||||
|     free_threadstate(tstate); |     free_threadstate(tstate); | ||||||
| } | } | ||||||
|  | @ -1160,8 +1359,7 @@ _PyThreadState_DeleteCurrent(PyThreadState *tstate) | ||||||
| void | void | ||||||
| PyThreadState_DeleteCurrent(void) | PyThreadState_DeleteCurrent(void) | ||||||
| { | { | ||||||
|     struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; |     PyThreadState *tstate = current_fast_get(&_PyRuntime); | ||||||
|     PyThreadState *tstate = _PyRuntimeGILState_GetThreadState(gilstate); |  | ||||||
|     _PyThreadState_DeleteCurrent(tstate); |     _PyThreadState_DeleteCurrent(tstate); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1211,38 +1409,45 @@ _PyThreadState_DeleteExcept(_PyRuntimeState *runtime, PyThreadState *tstate) | ||||||
| PyThreadState * | PyThreadState * | ||||||
| _PyThreadState_UncheckedGet(void) | _PyThreadState_UncheckedGet(void) | ||||||
| { | { | ||||||
|     return _PyThreadState_GET(); |     return current_fast_get(&_PyRuntime); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| PyThreadState * | PyThreadState * | ||||||
| PyThreadState_Get(void) | PyThreadState_Get(void) | ||||||
| { | { | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     PyThreadState *tstate = current_fast_get(&_PyRuntime); | ||||||
|     _Py_EnsureTstateNotNULL(tstate); |     _Py_EnsureTstateNotNULL(tstate); | ||||||
|     return tstate; |     return tstate; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| PyThreadState * | PyThreadState * | ||||||
| _PyThreadState_Swap(struct _gilstate_runtime_state *gilstate, PyThreadState *newts) | _PyThreadState_Swap(_PyRuntimeState *runtime, PyThreadState *newts) | ||||||
| { | { | ||||||
|     PyThreadState *oldts = _PyRuntimeGILState_GetThreadState(gilstate); |     PyThreadState *oldts = current_fast_get(runtime); | ||||||
| 
 | 
 | ||||||
|     _PyRuntimeGILState_SetThreadState(gilstate, newts); |     if (newts == NULL) { | ||||||
|  |         current_fast_clear(runtime); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         current_fast_set(runtime, newts); | ||||||
|  |     } | ||||||
|     /* It should not be possible for more than one thread state
 |     /* It should not be possible for more than one thread state
 | ||||||
|        to be used for a thread.  Check this the best we can in debug |        to be used for a thread.  Check this the best we can in debug | ||||||
|        builds. |        builds. | ||||||
|     */ |     */ | ||||||
|  |     // XXX The above isn't true when multiple interpreters are involved.
 | ||||||
| #if defined(Py_DEBUG) | #if defined(Py_DEBUG) | ||||||
|     if (newts) { |     if (newts && current_tss_initialized(runtime)) { | ||||||
|         /* This can be called from PyEval_RestoreThread(). Similar
 |         /* This can be called from PyEval_RestoreThread(). Similar
 | ||||||
|            to it, we need to ensure errno doesn't change. |            to it, we need to ensure errno doesn't change. | ||||||
|         */ |         */ | ||||||
|         int err = errno; |         int err = errno; | ||||||
|         PyThreadState *check = _PyGILState_GetThisThreadState(gilstate); |         PyThreadState *check = current_tss_get(runtime); | ||||||
|         if (check && check->interp == newts->interp && check != newts) |         if (check && check->interp == newts->interp && check != newts) { | ||||||
|             Py_FatalError("Invalid thread state for this thread"); |             Py_FatalError("Invalid thread state for this thread"); | ||||||
|  |         } | ||||||
|         errno = err; |         errno = err; | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
|  | @ -1252,7 +1457,7 @@ _PyThreadState_Swap(struct _gilstate_runtime_state *gilstate, PyThreadState *new | ||||||
| PyThreadState * | PyThreadState * | ||||||
| PyThreadState_Swap(PyThreadState *newts) | PyThreadState_Swap(PyThreadState *newts) | ||||||
| { | { | ||||||
|     return _PyThreadState_Swap(&_PyRuntime.gilstate, newts); |     return _PyThreadState_Swap(&_PyRuntime, newts); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* An extension mechanism to store arbitrary additional per-thread state.
 | /* An extension mechanism to store arbitrary additional per-thread state.
 | ||||||
|  | @ -1278,7 +1483,7 @@ _PyThreadState_GetDict(PyThreadState *tstate) | ||||||
| PyObject * | PyObject * | ||||||
| PyThreadState_GetDict(void) | PyThreadState_GetDict(void) | ||||||
| { | { | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     PyThreadState *tstate = current_fast_get(&_PyRuntime); | ||||||
|     if (tstate == NULL) { |     if (tstate == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|  | @ -1401,7 +1606,8 @@ PyThreadState_Next(PyThreadState *tstate) { | ||||||
| PyObject * | PyObject * | ||||||
| _PyThread_CurrentFrames(void) | _PyThread_CurrentFrames(void) | ||||||
| { | { | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|  |     PyThreadState *tstate = current_fast_get(runtime); | ||||||
|     if (_PySys_Audit(tstate, "sys._current_frames", NULL) < 0) { |     if (_PySys_Audit(tstate, "sys._current_frames", NULL) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|  | @ -1417,7 +1623,6 @@ _PyThread_CurrentFrames(void) | ||||||
|      * Because these lists can mutate even when the GIL is held, we |      * Because these lists can mutate even when the GIL is held, we | ||||||
|      * need to grab head_mutex for the duration. |      * need to grab head_mutex for the duration. | ||||||
|      */ |      */ | ||||||
|     _PyRuntimeState *runtime = tstate->interp->runtime; |  | ||||||
|     HEAD_LOCK(runtime); |     HEAD_LOCK(runtime); | ||||||
|     PyInterpreterState *i; |     PyInterpreterState *i; | ||||||
|     for (i = runtime->interpreters.head; i != NULL; i = i->next) { |     for (i = runtime->interpreters.head; i != NULL; i = i->next) { | ||||||
|  | @ -1457,7 +1662,8 @@ _PyThread_CurrentFrames(void) | ||||||
| PyObject * | PyObject * | ||||||
| _PyThread_CurrentExceptions(void) | _PyThread_CurrentExceptions(void) | ||||||
| { | { | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|  |     PyThreadState *tstate = current_fast_get(runtime); | ||||||
| 
 | 
 | ||||||
|     _Py_EnsureTstateNotNULL(tstate); |     _Py_EnsureTstateNotNULL(tstate); | ||||||
| 
 | 
 | ||||||
|  | @ -1476,7 +1682,6 @@ _PyThread_CurrentExceptions(void) | ||||||
|      * Because these lists can mutate even when the GIL is held, we |      * Because these lists can mutate even when the GIL is held, we | ||||||
|      * need to grab head_mutex for the duration. |      * need to grab head_mutex for the duration. | ||||||
|      */ |      */ | ||||||
|     _PyRuntimeState *runtime = tstate->interp->runtime; |  | ||||||
|     HEAD_LOCK(runtime); |     HEAD_LOCK(runtime); | ||||||
|     PyInterpreterState *i; |     PyInterpreterState *i; | ||||||
|     for (i = runtime->interpreters.head; i != NULL; i = i->next) { |     for (i = runtime->interpreters.head; i != NULL; i = i->next) { | ||||||
|  | @ -1515,40 +1720,37 @@ _PyThread_CurrentExceptions(void) | ||||||
| 
 | 
 | ||||||
| /* Python "auto thread state" API. */ | /* Python "auto thread state" API. */ | ||||||
| 
 | 
 | ||||||
| /* Keep this as a static, as it is not reliable!  It can only
 |  | ||||||
|    ever be compared to the state for the *current* thread. |  | ||||||
|    * If not equal, then it doesn't matter that the actual |  | ||||||
|      value may change immediately after comparison, as it can't |  | ||||||
|      possibly change to the current thread's state. |  | ||||||
|    * If equal, then the current thread holds the lock, so the value can't |  | ||||||
|      change until we yield the lock. |  | ||||||
| */ |  | ||||||
| static int |  | ||||||
| PyThreadState_IsCurrent(PyThreadState *tstate) |  | ||||||
| { |  | ||||||
|     /* Must be the tstate for this thread */ |  | ||||||
|     struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; |  | ||||||
|     assert(_PyGILState_GetThisThreadState(gilstate) == tstate); |  | ||||||
|     return tstate == _PyRuntimeGILState_GetThreadState(gilstate); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Internal initialization/finalization functions called by
 | /* Internal initialization/finalization functions called by
 | ||||||
|    Py_Initialize/Py_FinalizeEx |    Py_Initialize/Py_FinalizeEx | ||||||
| */ | */ | ||||||
| PyStatus | PyStatus | ||||||
| _PyGILState_Init(_PyRuntimeState *runtime) | _PyGILState_Init(PyInterpreterState *interp) | ||||||
| { | { | ||||||
|     struct _gilstate_runtime_state *gilstate = &runtime->gilstate; |     if (!_Py_IsMainInterpreter(interp)) { | ||||||
|     if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) { |         /* Currently, PyGILState is shared by all interpreters. The main
 | ||||||
|         return _PyStatus_NO_MEMORY(); |          * interpreter is responsible to initialize it. */ | ||||||
|  |         return _PyStatus_OK(); | ||||||
|     } |     } | ||||||
|     // PyThreadState_New() calls _PyGILState_NoteThreadState() which does
 |     _PyRuntimeState *runtime = interp->runtime; | ||||||
|     // nothing before autoInterpreterState is set.
 |     assert(current_tss_get(runtime) == NULL); | ||||||
|     assert(gilstate->autoInterpreterState == NULL); |     assert(runtime->gilstate.autoInterpreterState == NULL); | ||||||
|  |     runtime->gilstate.autoInterpreterState = interp; | ||||||
|     return _PyStatus_OK(); |     return _PyStatus_OK(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void | ||||||
|  | _PyGILState_Fini(PyInterpreterState *interp) | ||||||
|  | { | ||||||
|  |     if (!_Py_IsMainInterpreter(interp)) { | ||||||
|  |         /* Currently, PyGILState is shared by all interpreters. The main
 | ||||||
|  |          * interpreter is responsible to initialize it. */ | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     interp->runtime->gilstate.autoInterpreterState = NULL; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | // XXX Drop this.
 | ||||||
| PyStatus | PyStatus | ||||||
| _PyGILState_SetTstate(PyThreadState *tstate) | _PyGILState_SetTstate(PyThreadState *tstate) | ||||||
| { | { | ||||||
|  | @ -1561,14 +1763,12 @@ _PyGILState_SetTstate(PyThreadState *tstate) | ||||||
|          * interpreter is responsible to initialize it. */ |          * interpreter is responsible to initialize it. */ | ||||||
|         return _PyStatus_OK(); |         return _PyStatus_OK(); | ||||||
|     } |     } | ||||||
|  |     _PyRuntimeState *runtime = tstate->interp->runtime; | ||||||
| 
 | 
 | ||||||
|     struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate; |     assert(runtime->gilstate.autoInterpreterState == tstate->interp); | ||||||
|  |     assert(current_tss_get(runtime) == tstate); | ||||||
|  |     assert(tstate->gilstate_counter == 1); | ||||||
| 
 | 
 | ||||||
|     gilstate->autoInterpreterState = tstate->interp; |  | ||||||
|     assert(PyThread_tss_get(&gilstate->autoTSSkey) == NULL); |  | ||||||
|     assert(tstate->gilstate_counter == 0); |  | ||||||
| 
 |  | ||||||
|     _PyGILState_NoteThreadState(gilstate, tstate); |  | ||||||
|     return _PyStatus_OK(); |     return _PyStatus_OK(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1578,118 +1778,42 @@ _PyGILState_GetInterpreterStateUnsafe(void) | ||||||
|     return _PyRuntime.gilstate.autoInterpreterState; |     return _PyRuntime.gilstate.autoInterpreterState; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void |  | ||||||
| _PyGILState_Fini(PyInterpreterState *interp) |  | ||||||
| { |  | ||||||
|     struct _gilstate_runtime_state *gilstate = &interp->runtime->gilstate; |  | ||||||
|     PyThread_tss_delete(&gilstate->autoTSSkey); |  | ||||||
|     gilstate->autoInterpreterState = NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #ifdef HAVE_FORK |  | ||||||
| /* Reset the TSS key - called by PyOS_AfterFork_Child().
 |  | ||||||
|  * This should not be necessary, but some - buggy - pthread implementations |  | ||||||
|  * don't reset TSS upon fork(), see issue #10517. |  | ||||||
|  */ |  | ||||||
| PyStatus |  | ||||||
| _PyGILState_Reinit(_PyRuntimeState *runtime) |  | ||||||
| { |  | ||||||
|     struct _gilstate_runtime_state *gilstate = &runtime->gilstate; |  | ||||||
|     PyThreadState *tstate = _PyGILState_GetThisThreadState(gilstate); |  | ||||||
| 
 |  | ||||||
|     PyThread_tss_delete(&gilstate->autoTSSkey); |  | ||||||
|     if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) { |  | ||||||
|         return _PyStatus_NO_MEMORY(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* If the thread had an associated auto thread state, reassociate it with
 |  | ||||||
|      * the new key. */ |  | ||||||
|     if (tstate && |  | ||||||
|         PyThread_tss_set(&gilstate->autoTSSkey, (void *)tstate) != 0) |  | ||||||
|     { |  | ||||||
|         return _PyStatus_ERR("failed to set autoTSSkey"); |  | ||||||
|     } |  | ||||||
|     return _PyStatus_OK(); |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| /* When a thread state is created for a thread by some mechanism other than
 |  | ||||||
|    PyGILState_Ensure, it's important that the GILState machinery knows about |  | ||||||
|    it so it doesn't try to create another thread state for the thread (this is |  | ||||||
|    a better fix for SF bug #1010677 than the first one attempted). |  | ||||||
| */ |  | ||||||
| static void |  | ||||||
| _PyGILState_NoteThreadState(struct _gilstate_runtime_state *gilstate, PyThreadState* tstate) |  | ||||||
| { |  | ||||||
|     /* If autoTSSkey isn't initialized, this must be the very first
 |  | ||||||
|        threadstate created in Py_Initialize().  Don't do anything for now |  | ||||||
|        (we'll be back here when _PyGILState_Init is called). */ |  | ||||||
|     if (!gilstate->autoInterpreterState) { |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* Stick the thread state for this thread in thread specific storage.
 |  | ||||||
| 
 |  | ||||||
|        The only situation where you can legitimately have more than one |  | ||||||
|        thread state for an OS level thread is when there are multiple |  | ||||||
|        interpreters. |  | ||||||
| 
 |  | ||||||
|        You shouldn't really be using the PyGILState_ APIs anyway (see issues |  | ||||||
|        #10915 and #15751). |  | ||||||
| 
 |  | ||||||
|        The first thread state created for that given OS level thread will |  | ||||||
|        "win", which seems reasonable behaviour. |  | ||||||
|     */ |  | ||||||
|     if (PyThread_tss_get(&gilstate->autoTSSkey) == NULL) { |  | ||||||
|         if ((PyThread_tss_set(&gilstate->autoTSSkey, (void *)tstate)) != 0) { |  | ||||||
|             Py_FatalError("Couldn't create autoTSSkey mapping"); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* PyGILState_Release must not try to delete this thread state. */ |  | ||||||
|     tstate->gilstate_counter = 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* The public functions */ | /* The public functions */ | ||||||
| static PyThreadState * |  | ||||||
| _PyGILState_GetThisThreadState(struct _gilstate_runtime_state *gilstate) |  | ||||||
| { |  | ||||||
|     if (gilstate->autoInterpreterState == NULL) |  | ||||||
|         return NULL; |  | ||||||
|     return (PyThreadState *)PyThread_tss_get(&gilstate->autoTSSkey); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| PyThreadState * | PyThreadState * | ||||||
| PyGILState_GetThisThreadState(void) | PyGILState_GetThisThreadState(void) | ||||||
| { | { | ||||||
|     return _PyGILState_GetThisThreadState(&_PyRuntime.gilstate); |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|  |     if (!current_tss_initialized(runtime)) { | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  |     return current_tss_get(runtime); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| PyGILState_Check(void) | PyGILState_Check(void) | ||||||
| { | { | ||||||
|     struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|     if (!gilstate->check_enabled) { |     if (!runtime->gilstate.check_enabled) { | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!PyThread_tss_is_created(&gilstate->autoTSSkey)) { |     if (!current_tss_initialized(runtime)) { | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     PyThreadState *tstate = _PyRuntimeGILState_GetThreadState(gilstate); |     PyThreadState *tstate = current_fast_get(runtime); | ||||||
|     if (tstate == NULL) { |     if (tstate == NULL) { | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return (tstate == _PyGILState_GetThisThreadState(gilstate)); |     return (tstate == current_tss_get(runtime)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PyGILState_STATE | PyGILState_STATE | ||||||
| PyGILState_Ensure(void) | PyGILState_Ensure(void) | ||||||
| { | { | ||||||
|     _PyRuntimeState *runtime = &_PyRuntime; |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|     struct _gilstate_runtime_state *gilstate = &runtime->gilstate; |  | ||||||
| 
 | 
 | ||||||
|     /* Note that we do not auto-init Python here - apart from
 |     /* Note that we do not auto-init Python here - apart from
 | ||||||
|        potential races with 2 threads auto-initializing, pep-311 |        potential races with 2 threads auto-initializing, pep-311 | ||||||
|  | @ -1699,27 +1823,29 @@ PyGILState_Ensure(void) | ||||||
|     /* Ensure that _PyEval_InitThreads() and _PyGILState_Init() have been
 |     /* Ensure that _PyEval_InitThreads() and _PyGILState_Init() have been
 | ||||||
|        called by Py_Initialize() */ |        called by Py_Initialize() */ | ||||||
|     assert(_PyEval_ThreadsInitialized(runtime)); |     assert(_PyEval_ThreadsInitialized(runtime)); | ||||||
|     assert(gilstate->autoInterpreterState); |     assert(current_tss_initialized(runtime)); | ||||||
|  |     assert(runtime->gilstate.autoInterpreterState != NULL); | ||||||
| 
 | 
 | ||||||
|     PyThreadState *tcur = (PyThreadState *)PyThread_tss_get(&gilstate->autoTSSkey); |     PyThreadState *tcur = current_tss_get(runtime); | ||||||
|     int current; |     int has_gil; | ||||||
|     if (tcur == NULL) { |     if (tcur == NULL) { | ||||||
|         /* Create a new Python thread state for this thread */ |         /* Create a new Python thread state for this thread */ | ||||||
|         tcur = PyThreadState_New(gilstate->autoInterpreterState); |         tcur = PyThreadState_New(runtime->gilstate.autoInterpreterState); | ||||||
|         if (tcur == NULL) { |         if (tcur == NULL) { | ||||||
|             Py_FatalError("Couldn't create thread-state for new thread"); |             Py_FatalError("Couldn't create thread-state for new thread"); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /* This is our thread state!  We'll need to delete it in the
 |         /* This is our thread state!  We'll need to delete it in the
 | ||||||
|            matching call to PyGILState_Release(). */ |            matching call to PyGILState_Release(). */ | ||||||
|  |         assert(tcur->gilstate_counter == 1); | ||||||
|         tcur->gilstate_counter = 0; |         tcur->gilstate_counter = 0; | ||||||
|         current = 0; /* new thread state is never current */ |         has_gil = 0; /* new thread state is never current */ | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|         current = PyThreadState_IsCurrent(tcur); |         has_gil = holds_gil(tcur); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (current == 0) { |     if (!has_gil) { | ||||||
|         PyEval_RestoreThread(tcur); |         PyEval_RestoreThread(tcur); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -1730,14 +1856,14 @@ PyGILState_Ensure(void) | ||||||
|     */ |     */ | ||||||
|     ++tcur->gilstate_counter; |     ++tcur->gilstate_counter; | ||||||
| 
 | 
 | ||||||
|     return current ? PyGILState_LOCKED : PyGILState_UNLOCKED; |     return has_gil ? PyGILState_LOCKED : PyGILState_UNLOCKED; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| PyGILState_Release(PyGILState_STATE oldstate) | PyGILState_Release(PyGILState_STATE oldstate) | ||||||
| { | { | ||||||
|     _PyRuntimeState *runtime = &_PyRuntime; |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|     PyThreadState *tstate = PyThread_tss_get(&runtime->gilstate.autoTSSkey); |     PyThreadState *tstate = current_tss_get(runtime); | ||||||
|     if (tstate == NULL) { |     if (tstate == NULL) { | ||||||
|         Py_FatalError("auto-releasing thread-state, " |         Py_FatalError("auto-releasing thread-state, " | ||||||
|                       "but no thread-state for this thread"); |                       "but no thread-state for this thread"); | ||||||
|  | @ -1748,12 +1874,12 @@ PyGILState_Release(PyGILState_STATE oldstate) | ||||||
|        but while this is very new (April 2003), the extra check |        but while this is very new (April 2003), the extra check | ||||||
|        by release-only users can't hurt. |        by release-only users can't hurt. | ||||||
|     */ |     */ | ||||||
|     if (!PyThreadState_IsCurrent(tstate)) { |     if (!holds_gil(tstate)) { | ||||||
|         _Py_FatalErrorFormat(__func__, |         _Py_FatalErrorFormat(__func__, | ||||||
|                              "thread state %p must be current when releasing", |                              "thread state %p must be current when releasing", | ||||||
|                              tstate); |                              tstate); | ||||||
|     } |     } | ||||||
|     assert(PyThreadState_IsCurrent(tstate)); |     assert(holds_gil(tstate)); | ||||||
|     --tstate->gilstate_counter; |     --tstate->gilstate_counter; | ||||||
|     assert(tstate->gilstate_counter >= 0); /* illegal counter value */ |     assert(tstate->gilstate_counter >= 0); /* illegal counter value */ | ||||||
| 
 | 
 | ||||||
|  | @ -1769,13 +1895,14 @@ PyGILState_Release(PyGILState_STATE oldstate) | ||||||
|          * races; see bugs 225673 and 1061968 (that nasty bug has a |          * races; see bugs 225673 and 1061968 (that nasty bug has a | ||||||
|          * habit of coming back). |          * habit of coming back). | ||||||
|          */ |          */ | ||||||
|         assert(_PyRuntimeGILState_GetThreadState(&runtime->gilstate) == tstate); |         assert(current_fast_get(runtime) == tstate); | ||||||
|         _PyThreadState_DeleteCurrent(tstate); |         _PyThreadState_DeleteCurrent(tstate); | ||||||
|     } |     } | ||||||
|     /* Release the lock if necessary */ |     /* Release the lock if necessary */ | ||||||
|     else if (oldstate == PyGILState_UNLOCKED) |     else if (oldstate == PyGILState_UNLOCKED) { | ||||||
|         PyEval_SaveThread(); |         PyEval_SaveThread(); | ||||||
|     } |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /**************************/ | /**************************/ | ||||||
|  | @ -1905,7 +2032,8 @@ _PyObject_CheckCrossInterpreterData(PyObject *obj) | ||||||
| int | int | ||||||
| _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data) | _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data) | ||||||
| { | { | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|  |     PyThreadState *tstate = current_fast_get(runtime); | ||||||
| #ifdef Py_DEBUG | #ifdef Py_DEBUG | ||||||
|     // The caller must hold the GIL
 |     // The caller must hold the GIL
 | ||||||
|     _Py_EnsureTstateNotNULL(tstate); |     _Py_EnsureTstateNotNULL(tstate); | ||||||
|  | @ -1948,19 +2076,19 @@ _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data) | ||||||
| typedef void (*releasefunc)(PyInterpreterState *, void *); | typedef void (*releasefunc)(PyInterpreterState *, void *); | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| _call_in_interpreter(struct _gilstate_runtime_state *gilstate, | _call_in_interpreter(PyInterpreterState *interp, releasefunc func, void *arg) | ||||||
|                      PyInterpreterState *interp, releasefunc func, void *arg) |  | ||||||
| { | { | ||||||
|     /* We would use Py_AddPendingCall() if it weren't specific to the
 |     /* We would use Py_AddPendingCall() if it weren't specific to the
 | ||||||
|      * main interpreter (see bpo-33608).  In the meantime we take a |      * main interpreter (see bpo-33608).  In the meantime we take a | ||||||
|      * naive approach. |      * naive approach. | ||||||
|      */ |      */ | ||||||
|  |     _PyRuntimeState *runtime = interp->runtime; | ||||||
|     PyThreadState *save_tstate = NULL; |     PyThreadState *save_tstate = NULL; | ||||||
|     if (interp != _PyRuntimeGILState_GetThreadState(gilstate)->interp) { |     if (interp != current_fast_get(runtime)->interp) { | ||||||
|         // XXX Using the "head" thread isn't strictly correct.
 |         // XXX Using the "head" thread isn't strictly correct.
 | ||||||
|         PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); |         PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); | ||||||
|         // XXX Possible GILState issues?
 |         // XXX Possible GILState issues?
 | ||||||
|         save_tstate = _PyThreadState_Swap(gilstate, tstate); |         save_tstate = _PyThreadState_Swap(runtime, tstate); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // XXX Once the GIL is per-interpreter, this should be called with the
 |     // XXX Once the GIL is per-interpreter, this should be called with the
 | ||||||
|  | @ -1969,7 +2097,7 @@ _call_in_interpreter(struct _gilstate_runtime_state *gilstate, | ||||||
| 
 | 
 | ||||||
|     // Switch back.
 |     // Switch back.
 | ||||||
|     if (save_tstate != NULL) { |     if (save_tstate != NULL) { | ||||||
|         _PyThreadState_Swap(gilstate, save_tstate); |         _PyThreadState_Swap(runtime, save_tstate); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1993,8 +2121,7 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // "Release" the data and/or the object.
 |     // "Release" the data and/or the object.
 | ||||||
|     struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; |     _call_in_interpreter(interp, | ||||||
|     _call_in_interpreter(gilstate, interp, |  | ||||||
|                          (releasefunc)_PyCrossInterpreterData_Clear, data); |                          (releasefunc)_PyCrossInterpreterData_Clear, data); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | @ -2314,8 +2441,9 @@ _PyInterpreterState_GetConfigCopy(PyConfig *config) | ||||||
| const PyConfig* | const PyConfig* | ||||||
| _Py_GetConfig(void) | _Py_GetConfig(void) | ||||||
| { | { | ||||||
|  |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|     assert(PyGILState_Check()); |     assert(PyGILState_Check()); | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     PyThreadState *tstate = current_fast_get(runtime); | ||||||
|     _Py_EnsureTstateNotNULL(tstate); |     _Py_EnsureTstateNotNULL(tstate); | ||||||
|     return _PyInterpreterState_GetConfig(tstate->interp); |     return _PyInterpreterState_GetConfig(tstate->interp); | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Eric Snow
						Eric Snow