mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-36710: Add runtime variable in pystate.c (GH-12956)
Add 'gilstate', 'runtime' or 'xidregistry' parameter to many functions on pystate.c to avoid lying on _PyRuntime global.
This commit is contained in:
		
							parent
							
								
									5422e3cfb7
								
							
						
					
					
						commit
						10c8e6af91
					
				
					 1 changed files with 233 additions and 156 deletions
				
			
		
							
								
								
									
										389
									
								
								Python/pystate.c
									
										
									
									
									
								
							
							
						
						
									
										389
									
								
								Python/pystate.c
									
										
									
									
									
								
							|  | @ -6,11 +6,6 @@ | ||||||
| #include "pycore_pymem.h" | #include "pycore_pymem.h" | ||||||
| #include "pycore_pystate.h" | #include "pycore_pystate.h" | ||||||
| 
 | 
 | ||||||
| #define _PyThreadState_SET(value) \ |  | ||||||
|     _Py_atomic_store_relaxed(&_PyRuntime.gilstate.tstate_current, \ |  | ||||||
|                              (uintptr_t)(value)) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /* --------------------------------------------------------------------------
 | /* --------------------------------------------------------------------------
 | ||||||
| CAUTION | CAUTION | ||||||
| 
 | 
 | ||||||
|  | @ -34,6 +29,18 @@ 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 */ | ||||||
|  | static PyThreadState *_PyGILState_GetThisThreadState(struct _gilstate_runtime_state *gilstate); | ||||||
|  | static void _PyThreadState_Delete(_PyRuntimeState *runtime, PyThreadState *tstate); | ||||||
|  | static PyThreadState *_PyThreadState_Swap(struct _gilstate_runtime_state *gilstate, PyThreadState *newts); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| static _PyInitError | static _PyInitError | ||||||
| _PyRuntimeState_Init_impl(_PyRuntimeState *runtime) | _PyRuntimeState_Init_impl(_PyRuntimeState *runtime) | ||||||
| { | { | ||||||
|  | @ -137,9 +144,10 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define HEAD_LOCK() PyThread_acquire_lock(_PyRuntime.interpreters.mutex, \ | #define HEAD_LOCK(runtime) \ | ||||||
|                                           WAIT_LOCK) |     PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK) | ||||||
| #define HEAD_UNLOCK() PyThread_release_lock(_PyRuntime.interpreters.mutex) | #define HEAD_UNLOCK(runtime) \ | ||||||
|  |     PyThread_release_lock((runtime)->interpreters.mutex) | ||||||
| 
 | 
 | ||||||
| /* Forward declaration */ | /* Forward declaration */ | ||||||
| static void _PyGILState_NoteThreadState( | static void _PyGILState_NoteThreadState( | ||||||
|  | @ -148,21 +156,22 @@ static void _PyGILState_NoteThreadState( | ||||||
| _PyInitError | _PyInitError | ||||||
| _PyInterpreterState_Enable(_PyRuntimeState *runtime) | _PyInterpreterState_Enable(_PyRuntimeState *runtime) | ||||||
| { | { | ||||||
|     runtime->interpreters.next_id = 0; |     struct pyinterpreters *interpreters = &runtime->interpreters; | ||||||
|  |     interpreters->next_id = 0; | ||||||
| 
 | 
 | ||||||
|     /* Py_Finalize() calls _PyRuntimeState_Fini() which clears the mutex.
 |     /* Py_Finalize() calls _PyRuntimeState_Fini() which clears the mutex.
 | ||||||
|        Create a new mutex if needed. */ |        Create a new mutex if needed. */ | ||||||
|     if (runtime->interpreters.mutex == NULL) { |     if (interpreters->mutex == NULL) { | ||||||
|         /* Force default allocator, since _PyRuntimeState_Fini() must
 |         /* Force default allocator, since _PyRuntimeState_Fini() must
 | ||||||
|            use the same allocator than this function. */ |            use the same allocator than this function. */ | ||||||
|         PyMemAllocatorEx old_alloc; |         PyMemAllocatorEx old_alloc; | ||||||
|         _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |         _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); | ||||||
| 
 | 
 | ||||||
|         runtime->interpreters.mutex = PyThread_allocate_lock(); |         interpreters->mutex = PyThread_allocate_lock(); | ||||||
| 
 | 
 | ||||||
|         PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |         PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); | ||||||
| 
 | 
 | ||||||
|         if (runtime->interpreters.mutex == NULL) { |         if (interpreters->mutex == NULL) { | ||||||
|             return _Py_INIT_ERR("Can't initialize threads for interpreter"); |             return _Py_INIT_ERR("Can't initialize threads for interpreter"); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -173,9 +182,7 @@ _PyInterpreterState_Enable(_PyRuntimeState *runtime) | ||||||
| PyInterpreterState * | PyInterpreterState * | ||||||
| PyInterpreterState_New(void) | PyInterpreterState_New(void) | ||||||
| { | { | ||||||
|     PyInterpreterState *interp = (PyInterpreterState *) |     PyInterpreterState *interp = PyMem_RawMalloc(sizeof(PyInterpreterState)); | ||||||
|                                  PyMem_RawMalloc(sizeof(PyInterpreterState)); |  | ||||||
| 
 |  | ||||||
|     if (interp == NULL) { |     if (interp == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|  | @ -193,23 +200,27 @@ PyInterpreterState_New(void) | ||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     HEAD_LOCK(); |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|     if (_PyRuntime.interpreters.next_id < 0) { |     struct pyinterpreters *interpreters = &runtime->interpreters; | ||||||
|  | 
 | ||||||
|  |     HEAD_LOCK(runtime); | ||||||
|  |     if (interpreters->next_id < 0) { | ||||||
|         /* overflow or Py_Initialize() not called! */ |         /* overflow or Py_Initialize() not called! */ | ||||||
|         PyErr_SetString(PyExc_RuntimeError, |         PyErr_SetString(PyExc_RuntimeError, | ||||||
|                         "failed to get an interpreter ID"); |                         "failed to get an interpreter ID"); | ||||||
|         PyMem_RawFree(interp); |         PyMem_RawFree(interp); | ||||||
|         interp = NULL; |         interp = NULL; | ||||||
|     } else { |  | ||||||
|         interp->id = _PyRuntime.interpreters.next_id; |  | ||||||
|         _PyRuntime.interpreters.next_id += 1; |  | ||||||
|         interp->next = _PyRuntime.interpreters.head; |  | ||||||
|         if (_PyRuntime.interpreters.main == NULL) { |  | ||||||
|             _PyRuntime.interpreters.main = interp; |  | ||||||
|         } |  | ||||||
|         _PyRuntime.interpreters.head = interp; |  | ||||||
|     } |     } | ||||||
|     HEAD_UNLOCK(); |     else { | ||||||
|  |         interp->id = interpreters->next_id; | ||||||
|  |         interpreters->next_id += 1; | ||||||
|  |         interp->next = interpreters->head; | ||||||
|  |         if (interpreters->main == NULL) { | ||||||
|  |             interpreters->main = interp; | ||||||
|  |         } | ||||||
|  |         interpreters->head = interp; | ||||||
|  |     } | ||||||
|  |     HEAD_UNLOCK(runtime); | ||||||
| 
 | 
 | ||||||
|     if (interp == NULL) { |     if (interp == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  | @ -221,14 +232,14 @@ PyInterpreterState_New(void) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void | static void | ||||||
| PyInterpreterState_Clear(PyInterpreterState *interp) | _PyInterpreterState_Clear(_PyRuntimeState *runtime, PyInterpreterState *interp) | ||||||
| { | { | ||||||
|     PyThreadState *p; |     HEAD_LOCK(runtime); | ||||||
|     HEAD_LOCK(); |     for (PyThreadState *p = interp->tstate_head; p != NULL; p = p->next) { | ||||||
|     for (p = interp->tstate_head; p != NULL; p = p->next) |  | ||||||
|         PyThreadState_Clear(p); |         PyThreadState_Clear(p); | ||||||
|     HEAD_UNLOCK(); |     } | ||||||
|  |     HEAD_UNLOCK(runtime); | ||||||
|     _PyCoreConfig_Clear(&interp->core_config); |     _PyCoreConfig_Clear(&interp->core_config); | ||||||
|     Py_CLEAR(interp->codec_search_path); |     Py_CLEAR(interp->codec_search_path); | ||||||
|     Py_CLEAR(interp->codec_search_cache); |     Py_CLEAR(interp->codec_search_cache); | ||||||
|  | @ -251,45 +262,63 @@ PyInterpreterState_Clear(PyInterpreterState *interp) | ||||||
|     // objects have been cleaned up at the point.
 |     // objects have been cleaned up at the point.
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void | ||||||
|  | PyInterpreterState_Clear(PyInterpreterState *interp) | ||||||
|  | { | ||||||
|  |     _PyInterpreterState_Clear(&_PyRuntime, interp); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| zapthreads(PyInterpreterState *interp) | zapthreads(_PyRuntimeState *runtime, PyInterpreterState *interp) | ||||||
| { | { | ||||||
|     PyThreadState *p; |     PyThreadState *p; | ||||||
|     /* No need to lock the mutex here because this should only happen
 |     /* No need to lock the mutex here because this should only happen
 | ||||||
|        when the threads are all really dead (XXX famous last words). */ |        when the threads are all really dead (XXX famous last words). */ | ||||||
|     while ((p = interp->tstate_head) != NULL) { |     while ((p = interp->tstate_head) != NULL) { | ||||||
|         PyThreadState_Delete(p); |         _PyThreadState_Delete(runtime, p); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | static void | ||||||
|  | _PyInterpreterState_Delete(_PyRuntimeState *runtime, | ||||||
|  |                            PyInterpreterState *interp) | ||||||
|  | { | ||||||
|  |     struct pyinterpreters *interpreters = &runtime->interpreters; | ||||||
|  |     zapthreads(runtime, interp); | ||||||
|  |     HEAD_LOCK(runtime); | ||||||
|  |     PyInterpreterState **p; | ||||||
|  |     for (p = &interpreters->head; ; p = &(*p)->next) { | ||||||
|  |         if (*p == NULL) { | ||||||
|  |             Py_FatalError("PyInterpreterState_Delete: invalid interp"); | ||||||
|  |         } | ||||||
|  |         if (*p == interp) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     if (interp->tstate_head != NULL) { | ||||||
|  |         Py_FatalError("PyInterpreterState_Delete: remaining threads"); | ||||||
|  |     } | ||||||
|  |     *p = interp->next; | ||||||
|  |     if (interpreters->main == interp) { | ||||||
|  |         interpreters->main = NULL; | ||||||
|  |         if (interpreters->head != NULL) { | ||||||
|  |             Py_FatalError("PyInterpreterState_Delete: remaining subinterpreters"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     HEAD_UNLOCK(runtime); | ||||||
|  |     if (interp->id_mutex != NULL) { | ||||||
|  |         PyThread_free_lock(interp->id_mutex); | ||||||
|  |     } | ||||||
|  |     PyMem_RawFree(interp); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| void | void | ||||||
| PyInterpreterState_Delete(PyInterpreterState *interp) | PyInterpreterState_Delete(PyInterpreterState *interp) | ||||||
| { | { | ||||||
|     PyInterpreterState **p; |     _PyInterpreterState_Delete(&_PyRuntime, interp); | ||||||
|     zapthreads(interp); |  | ||||||
|     HEAD_LOCK(); |  | ||||||
|     for (p = &_PyRuntime.interpreters.head; ; p = &(*p)->next) { |  | ||||||
|         if (*p == NULL) |  | ||||||
|             Py_FatalError( |  | ||||||
|                 "PyInterpreterState_Delete: invalid interp"); |  | ||||||
|         if (*p == interp) |  | ||||||
|             break; |  | ||||||
|     } |  | ||||||
|     if (interp->tstate_head != NULL) |  | ||||||
|         Py_FatalError("PyInterpreterState_Delete: remaining threads"); |  | ||||||
|     *p = interp->next; |  | ||||||
|     if (_PyRuntime.interpreters.main == interp) { |  | ||||||
|         _PyRuntime.interpreters.main = NULL; |  | ||||||
|         if (_PyRuntime.interpreters.head != NULL) |  | ||||||
|             Py_FatalError("PyInterpreterState_Delete: remaining subinterpreters"); |  | ||||||
|     } |  | ||||||
|     HEAD_UNLOCK(); |  | ||||||
|     if (interp->id_mutex != NULL) { |  | ||||||
|         PyThread_free_lock(interp->id_mutex); |  | ||||||
|     } |  | ||||||
|     PyMem_RawFree(interp); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -300,14 +329,15 @@ PyInterpreterState_Delete(PyInterpreterState *interp) | ||||||
| void | void | ||||||
| _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(NULL); |     PyThreadState *tstate = _PyThreadState_Swap(gilstate, NULL); | ||||||
|     if (tstate != NULL && tstate->interp != interpreters->main) { |     if (tstate != NULL && tstate->interp != interpreters->main) { | ||||||
|         Py_FatalError("PyInterpreterState_DeleteExceptMain: not main interpreter"); |         Py_FatalError("PyInterpreterState_DeleteExceptMain: not main interpreter"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     HEAD_LOCK(); |     HEAD_LOCK(runtime); | ||||||
|     PyInterpreterState *interp = interpreters->head; |     PyInterpreterState *interp = interpreters->head; | ||||||
|     interpreters->head = NULL; |     interpreters->head = NULL; | ||||||
|     while (interp != NULL) { |     while (interp != NULL) { | ||||||
|  | @ -318,8 +348,8 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         PyInterpreterState_Clear(interp);  // XXX must activate?
 |         _PyInterpreterState_Clear(runtime, interp);  // XXX must activate?
 | ||||||
|         zapthreads(interp); |         zapthreads(runtime, interp); | ||||||
|         if (interp->id_mutex != NULL) { |         if (interp->id_mutex != NULL) { | ||||||
|             PyThread_free_lock(interp->id_mutex); |             PyThread_free_lock(interp->id_mutex); | ||||||
|         } |         } | ||||||
|  | @ -327,12 +357,12 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) | ||||||
|         interp = interp->next; |         interp = interp->next; | ||||||
|         PyMem_RawFree(prev_interp); |         PyMem_RawFree(prev_interp); | ||||||
|     } |     } | ||||||
|     HEAD_UNLOCK(); |     HEAD_UNLOCK(runtime); | ||||||
| 
 | 
 | ||||||
|     if (interpreters->head == NULL) { |     if (interpreters->head == NULL) { | ||||||
|         Py_FatalError("PyInterpreterState_DeleteExceptMain: missing main"); |         Py_FatalError("PyInterpreterState_DeleteExceptMain: missing main"); | ||||||
|     } |     } | ||||||
|     PyThreadState_Swap(tstate); |     _PyThreadState_Swap(gilstate, tstate); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -363,9 +393,9 @@ PyInterpreterState_GetID(PyInterpreterState *interp) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static PyInterpreterState * | static PyInterpreterState * | ||||||
| interp_look_up_id(PY_INT64_T requested_id) | interp_look_up_id(_PyRuntimeState *runtime, PY_INT64_T requested_id) | ||||||
| { | { | ||||||
|     PyInterpreterState *interp = PyInterpreterState_Head(); |     PyInterpreterState *interp = runtime->interpreters.head; | ||||||
|     while (interp != NULL) { |     while (interp != NULL) { | ||||||
|         PY_INT64_T id = PyInterpreterState_GetID(interp); |         PY_INT64_T id = PyInterpreterState_GetID(interp); | ||||||
|         if (id < 0) { |         if (id < 0) { | ||||||
|  | @ -384,9 +414,10 @@ _PyInterpreterState_LookUpID(PY_INT64_T requested_id) | ||||||
| { | { | ||||||
|     PyInterpreterState *interp = NULL; |     PyInterpreterState *interp = NULL; | ||||||
|     if (requested_id >= 0) { |     if (requested_id >= 0) { | ||||||
|         HEAD_LOCK(); |         _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|         interp = interp_look_up_id(requested_id); |         HEAD_LOCK(runtime); | ||||||
|         HEAD_UNLOCK(); |         interp = interp_look_up_id(runtime, requested_id); | ||||||
|  |         HEAD_UNLOCK(runtime); | ||||||
|     } |     } | ||||||
|     if (interp == NULL && !PyErr_Occurred()) { |     if (interp == NULL && !PyErr_Occurred()) { | ||||||
|         PyErr_Format(PyExc_RuntimeError, |         PyErr_Format(PyExc_RuntimeError, | ||||||
|  | @ -431,6 +462,7 @@ _PyInterpreterState_IDDecref(PyInterpreterState *interp) | ||||||
|     if (interp->id_mutex == NULL) { |     if (interp->id_mutex == NULL) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |     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; | ||||||
|  | @ -441,9 +473,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(tstate); |         PyThreadState *save_tstate = _PyThreadState_Swap(gilstate, tstate); | ||||||
|         Py_EndInterpreter(tstate); |         Py_EndInterpreter(tstate); | ||||||
|         PyThreadState_Swap(save_tstate); |         _PyThreadState_Swap(gilstate, save_tstate); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -498,6 +530,7 @@ threadstate_getframe(PyThreadState *self) | ||||||
| static PyThreadState * | static PyThreadState * | ||||||
| new_threadstate(PyInterpreterState *interp, int init) | new_threadstate(PyInterpreterState *interp, int init) | ||||||
| { | { | ||||||
|  |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|     PyThreadState *tstate = (PyThreadState *)PyMem_RawMalloc(sizeof(PyThreadState)); |     PyThreadState *tstate = (PyThreadState *)PyMem_RawMalloc(sizeof(PyThreadState)); | ||||||
|     if (tstate == NULL) { |     if (tstate == NULL) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  | @ -556,16 +589,16 @@ new_threadstate(PyInterpreterState *interp, int init) | ||||||
|     tstate->id = ++interp->tstate_next_unique_id; |     tstate->id = ++interp->tstate_next_unique_id; | ||||||
| 
 | 
 | ||||||
|     if (init) { |     if (init) { | ||||||
|         _PyThreadState_Init(&_PyRuntime, tstate); |         _PyThreadState_Init(runtime, tstate); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     HEAD_LOCK(); |     HEAD_LOCK(runtime); | ||||||
|     tstate->prev = NULL; |     tstate->prev = NULL; | ||||||
|     tstate->next = interp->tstate_head; |     tstate->next = interp->tstate_head; | ||||||
|     if (tstate->next) |     if (tstate->next) | ||||||
|         tstate->next->prev = tstate; |         tstate->next->prev = tstate; | ||||||
|     interp->tstate_head = tstate; |     interp->tstate_head = tstate; | ||||||
|     HEAD_UNLOCK(); |     HEAD_UNLOCK(runtime); | ||||||
| 
 | 
 | ||||||
|     return tstate; |     return tstate; | ||||||
| } | } | ||||||
|  | @ -750,22 +783,23 @@ 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(_PyRuntimeState *runtime, PyThreadState *tstate) | ||||||
| { | { | ||||||
|     PyInterpreterState *interp; |     if (tstate == NULL) { | ||||||
|     if (tstate == NULL) |  | ||||||
|         Py_FatalError("PyThreadState_Delete: NULL tstate"); |         Py_FatalError("PyThreadState_Delete: NULL tstate"); | ||||||
|     interp = tstate->interp; |     } | ||||||
|     if (interp == NULL) |     PyInterpreterState *interp = tstate->interp; | ||||||
|  |     if (interp == NULL) { | ||||||
|         Py_FatalError("PyThreadState_Delete: NULL interp"); |         Py_FatalError("PyThreadState_Delete: NULL interp"); | ||||||
|     HEAD_LOCK(); |     } | ||||||
|  |     HEAD_LOCK(runtime); | ||||||
|     if (tstate->prev) |     if (tstate->prev) | ||||||
|         tstate->prev->next = tstate->next; |         tstate->prev->next = tstate->next; | ||||||
|     else |     else | ||||||
|         interp->tstate_head = tstate->next; |         interp->tstate_head = tstate->next; | ||||||
|     if (tstate->next) |     if (tstate->next) | ||||||
|         tstate->next->prev = tstate->prev; |         tstate->next->prev = tstate->prev; | ||||||
|     HEAD_UNLOCK(); |     HEAD_UNLOCK(runtime); | ||||||
|     if (tstate->on_delete != NULL) { |     if (tstate->on_delete != NULL) { | ||||||
|         tstate->on_delete(tstate->on_delete_data); |         tstate->on_delete(tstate->on_delete_data); | ||||||
|     } |     } | ||||||
|  | @ -773,37 +807,53 @@ tstate_delete_common(PyThreadState *tstate) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void | static void | ||||||
| PyThreadState_Delete(PyThreadState *tstate) | _PyThreadState_Delete(_PyRuntimeState *runtime, PyThreadState *tstate) | ||||||
| { | { | ||||||
|     if (tstate == _PyThreadState_GET()) |     struct _gilstate_runtime_state *gilstate = &runtime->gilstate; | ||||||
|  |     if (tstate == _PyRuntimeGILState_GetThreadState(gilstate)) { | ||||||
|         Py_FatalError("PyThreadState_Delete: tstate is still current"); |         Py_FatalError("PyThreadState_Delete: tstate is still current"); | ||||||
|     if (_PyRuntime.gilstate.autoInterpreterState && |  | ||||||
|         PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == tstate) |  | ||||||
|     { |  | ||||||
|         PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, NULL); |  | ||||||
|     } |     } | ||||||
|     tstate_delete_common(tstate); |     if (gilstate->autoInterpreterState && | ||||||
|  |         PyThread_tss_get(&gilstate->autoTSSkey) == tstate) | ||||||
|  |     { | ||||||
|  |         PyThread_tss_set(&gilstate->autoTSSkey, NULL); | ||||||
|  |     } | ||||||
|  |     tstate_delete_common(runtime, tstate); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| PyThreadState_DeleteCurrent() | PyThreadState_Delete(PyThreadState *tstate) | ||||||
| { | { | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     return _PyThreadState_Delete(&_PyRuntime, tstate); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | _PyThreadState_DeleteCurrent(_PyRuntimeState *runtime) | ||||||
|  | { | ||||||
|  |     struct _gilstate_runtime_state *gilstate = &runtime->gilstate; | ||||||
|  |     PyThreadState *tstate = _PyRuntimeGILState_GetThreadState(gilstate); | ||||||
|     if (tstate == NULL) |     if (tstate == NULL) | ||||||
|         Py_FatalError( |         Py_FatalError( | ||||||
|             "PyThreadState_DeleteCurrent: no current tstate"); |             "PyThreadState_DeleteCurrent: no current tstate"); | ||||||
|     tstate_delete_common(tstate); |     tstate_delete_common(runtime, tstate); | ||||||
|     if (_PyRuntime.gilstate.autoInterpreterState && |     if (gilstate->autoInterpreterState && | ||||||
|         PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == tstate) |         PyThread_tss_get(&gilstate->autoTSSkey) == tstate) | ||||||
|     { |     { | ||||||
|         PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, NULL); |         PyThread_tss_set(&gilstate->autoTSSkey, NULL); | ||||||
|     } |     } | ||||||
|     _PyThreadState_SET(NULL); |     _PyRuntimeGILState_SetThreadState(gilstate, NULL); | ||||||
|     PyEval_ReleaseLock(); |     PyEval_ReleaseLock(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void | ||||||
|  | PyThreadState_DeleteCurrent() | ||||||
|  | { | ||||||
|  |     _PyThreadState_DeleteCurrent(&_PyRuntime); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Delete all thread states except the one passed as argument. |  * Delete all thread states except the one passed as argument. | ||||||
|  | @ -815,9 +865,10 @@ PyThreadState_DeleteCurrent() | ||||||
| void | void | ||||||
| _PyThreadState_DeleteExcept(PyThreadState *tstate) | _PyThreadState_DeleteExcept(PyThreadState *tstate) | ||||||
| { | { | ||||||
|  |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|     PyInterpreterState *interp = tstate->interp; |     PyInterpreterState *interp = tstate->interp; | ||||||
|     PyThreadState *p, *next, *garbage; |     PyThreadState *p, *next, *garbage; | ||||||
|     HEAD_LOCK(); |     HEAD_LOCK(runtime); | ||||||
|     /* Remove all thread states, except tstate, from the linked list of
 |     /* Remove all thread states, except tstate, from the linked list of
 | ||||||
|        thread states.  This will allow calling PyThreadState_Clear() |        thread states.  This will allow calling PyThreadState_Clear() | ||||||
|        without holding the lock. */ |        without holding the lock. */ | ||||||
|  | @ -830,7 +881,7 @@ _PyThreadState_DeleteExcept(PyThreadState *tstate) | ||||||
|         tstate->next->prev = tstate->prev; |         tstate->next->prev = tstate->prev; | ||||||
|     tstate->prev = tstate->next = NULL; |     tstate->prev = tstate->next = NULL; | ||||||
|     interp->tstate_head = tstate; |     interp->tstate_head = tstate; | ||||||
|     HEAD_UNLOCK(); |     HEAD_UNLOCK(runtime); | ||||||
|     /* Clear and deallocate all stale thread states.  Even if this
 |     /* Clear and deallocate all stale thread states.  Even if this
 | ||||||
|        executes Python code, we should be safe since it executes |        executes Python code, we should be safe since it executes | ||||||
|        in the current thread, not one of the stale threads. */ |        in the current thread, not one of the stale threads. */ | ||||||
|  | @ -860,12 +911,12 @@ PyThreadState_Get(void) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| PyThreadState * | static PyThreadState * | ||||||
| PyThreadState_Swap(PyThreadState *newts) | _PyThreadState_Swap(struct _gilstate_runtime_state *gilstate, PyThreadState *newts) | ||||||
| { | { | ||||||
|     PyThreadState *oldts = _PyThreadState_GET(); |     PyThreadState *oldts = _PyRuntimeGILState_GetThreadState(gilstate); | ||||||
| 
 | 
 | ||||||
|     _PyThreadState_SET(newts); |     _PyRuntimeGILState_SetThreadState(gilstate, 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. | ||||||
|  | @ -876,7 +927,7 @@ PyThreadState_Swap(PyThreadState *newts) | ||||||
|            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(); |         PyThreadState *check = _PyGILState_GetThisThreadState(gilstate); | ||||||
|         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; | ||||||
|  | @ -885,6 +936,12 @@ PyThreadState_Swap(PyThreadState *newts) | ||||||
|     return oldts; |     return oldts; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | PyThreadState * | ||||||
|  | PyThreadState_Swap(PyThreadState *newts) | ||||||
|  | { | ||||||
|  |     return _PyThreadState_Swap(&_PyRuntime.gilstate, newts); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* An extension mechanism to store arbitrary additional per-thread state.
 | /* An extension mechanism to store arbitrary additional per-thread state.
 | ||||||
|    PyThreadState_GetDict() returns a dictionary that can be used to hold such |    PyThreadState_GetDict() returns a dictionary that can be used to hold such | ||||||
|    state; the caller should pick a unique key and store its state there.  If |    state; the caller should pick a unique key and store its state there.  If | ||||||
|  | @ -928,7 +985,8 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc) | ||||||
|      * list of thread states we're traversing, so to prevent that we lock |      * list of thread states we're traversing, so to prevent that we lock | ||||||
|      * head_mutex for the duration. |      * head_mutex for the duration. | ||||||
|      */ |      */ | ||||||
|     HEAD_LOCK(); |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|  |     HEAD_LOCK(runtime); | ||||||
|     for (p = interp->tstate_head; p != NULL; p = p->next) { |     for (p = interp->tstate_head; p != NULL; p = p->next) { | ||||||
|         if (p->thread_id == id) { |         if (p->thread_id == id) { | ||||||
|             /* Tricky:  we need to decref the current value
 |             /* Tricky:  we need to decref the current value
 | ||||||
|  | @ -941,13 +999,13 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc) | ||||||
|             PyObject *old_exc = p->async_exc; |             PyObject *old_exc = p->async_exc; | ||||||
|             Py_XINCREF(exc); |             Py_XINCREF(exc); | ||||||
|             p->async_exc = exc; |             p->async_exc = exc; | ||||||
|             HEAD_UNLOCK(); |             HEAD_UNLOCK(runtime); | ||||||
|             Py_XDECREF(old_exc); |             Py_XDECREF(old_exc); | ||||||
|             _PyEval_SignalAsyncExc(); |             _PyEval_SignalAsyncExc(); | ||||||
|             return 1; |             return 1; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     HEAD_UNLOCK(); |     HEAD_UNLOCK(runtime); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1003,8 +1061,9 @@ _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. | ||||||
|      */ |      */ | ||||||
|     HEAD_LOCK(); |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|     for (i = _PyRuntime.interpreters.head; i != NULL; i = i->next) { |     HEAD_LOCK(runtime); | ||||||
|  |     for (i = runtime->interpreters.head; i != NULL; i = i->next) { | ||||||
|         PyThreadState *t; |         PyThreadState *t; | ||||||
|         for (t = i->tstate_head; t != NULL; t = t->next) { |         for (t = i->tstate_head; t != NULL; t = t->next) { | ||||||
|             PyObject *id; |             PyObject *id; | ||||||
|  | @ -1021,11 +1080,11 @@ _PyThread_CurrentFrames(void) | ||||||
|                 goto Fail; |                 goto Fail; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     HEAD_UNLOCK(); |     HEAD_UNLOCK(runtime); | ||||||
|     return result; |     return result; | ||||||
| 
 | 
 | ||||||
|  Fail: |  Fail: | ||||||
|     HEAD_UNLOCK(); |     HEAD_UNLOCK(runtime); | ||||||
|     Py_DECREF(result); |     Py_DECREF(result); | ||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
|  | @ -1044,8 +1103,9 @@ static int | ||||||
| PyThreadState_IsCurrent(PyThreadState *tstate) | PyThreadState_IsCurrent(PyThreadState *tstate) | ||||||
| { | { | ||||||
|     /* Must be the tstate for this thread */ |     /* Must be the tstate for this thread */ | ||||||
|     assert(PyGILState_GetThisThreadState()==tstate); |     struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; | ||||||
|     return tstate == _PyThreadState_GET(); |     assert(_PyGILState_GetThisThreadState(gilstate) == tstate); | ||||||
|  |     return tstate == _PyRuntimeGILState_GetThreadState(gilstate); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Internal initialization/finalization functions called by
 | /* Internal initialization/finalization functions called by
 | ||||||
|  | @ -1093,7 +1153,7 @@ void | ||||||
| _PyGILState_Reinit(_PyRuntimeState *runtime) | _PyGILState_Reinit(_PyRuntimeState *runtime) | ||||||
| { | { | ||||||
|     struct _gilstate_runtime_state *gilstate = &runtime->gilstate; |     struct _gilstate_runtime_state *gilstate = &runtime->gilstate; | ||||||
|     PyThreadState *tstate = PyGILState_GetThisThreadState(); |     PyThreadState *tstate = _PyGILState_GetThisThreadState(gilstate); | ||||||
| 
 | 
 | ||||||
|     PyThread_tss_delete(&gilstate->autoTSSkey); |     PyThread_tss_delete(&gilstate->autoTSSkey); | ||||||
|     if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) { |     if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) { | ||||||
|  | @ -1147,36 +1207,45 @@ _PyGILState_NoteThreadState(struct _gilstate_runtime_state *gilstate, PyThreadSt | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* 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) | ||||||
| { | { | ||||||
|     if (_PyRuntime.gilstate.autoInterpreterState == NULL) |     return _PyGILState_GetThisThreadState(&_PyRuntime.gilstate); | ||||||
|         return NULL; |  | ||||||
|     return (PyThreadState *)PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| PyGILState_Check(void) | PyGILState_Check(void) | ||||||
| { | { | ||||||
|     PyThreadState *tstate; |  | ||||||
| 
 | 
 | ||||||
|     if (!_PyGILState_check_enabled) |     if (!_PyGILState_check_enabled) { | ||||||
|         return 1; |  | ||||||
| 
 |  | ||||||
|     if (!PyThread_tss_is_created(&_PyRuntime.gilstate.autoTSSkey)) { |  | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     tstate = _PyThreadState_GET(); |     struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; | ||||||
|     if (tstate == NULL) |     if (!PyThread_tss_is_created(&gilstate->autoTSSkey)) { | ||||||
|         return 0; |         return 1; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return (tstate == PyGILState_GetThisThreadState()); |     PyThreadState *tstate = _PyRuntimeGILState_GetThreadState(gilstate); | ||||||
|  |     if (tstate == NULL) { | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return (tstate == _PyGILState_GetThisThreadState(gilstate)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PyGILState_STATE | PyGILState_STATE | ||||||
| PyGILState_Ensure(void) | PyGILState_Ensure(void) | ||||||
| { | { | ||||||
|  |     struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; | ||||||
|     int current; |     int current; | ||||||
|     PyThreadState *tcur; |     PyThreadState *tcur; | ||||||
|     int need_init_threads = 0; |     int need_init_threads = 0; | ||||||
|  | @ -1187,14 +1256,14 @@ PyGILState_Ensure(void) | ||||||
|        called Py_Initialize() and usually PyEval_InitThreads(). |        called Py_Initialize() and usually PyEval_InitThreads(). | ||||||
|     */ |     */ | ||||||
|     /* Py_Initialize() hasn't been called! */ |     /* Py_Initialize() hasn't been called! */ | ||||||
|     assert(_PyRuntime.gilstate.autoInterpreterState); |     assert(gilstate->autoInterpreterState); | ||||||
| 
 | 
 | ||||||
|     tcur = (PyThreadState *)PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey); |     tcur = (PyThreadState *)PyThread_tss_get(&gilstate->autoTSSkey); | ||||||
|     if (tcur == NULL) { |     if (tcur == NULL) { | ||||||
|         need_init_threads = 1; |         need_init_threads = 1; | ||||||
| 
 | 
 | ||||||
|         /* Create a new thread state for this thread */ |         /* Create a new thread state for this thread */ | ||||||
|         tcur = PyThreadState_New(_PyRuntime.gilstate.autoInterpreterState); |         tcur = PyThreadState_New(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
 | ||||||
|  | @ -1230,18 +1299,21 @@ PyGILState_Ensure(void) | ||||||
| void | void | ||||||
| PyGILState_Release(PyGILState_STATE oldstate) | PyGILState_Release(PyGILState_STATE oldstate) | ||||||
| { | { | ||||||
|     PyThreadState *tcur = (PyThreadState *)PyThread_tss_get( |     _PyRuntimeState *runtime = &_PyRuntime; | ||||||
|                                 &_PyRuntime.gilstate.autoTSSkey); |     PyThreadState *tcur = PyThread_tss_get(&runtime->gilstate.autoTSSkey); | ||||||
|     if (tcur == NULL) |     if (tcur == 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"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /* We must hold the GIL and have our thread state current */ |     /* We must hold the GIL and have our thread state current */ | ||||||
|     /* XXX - remove the check - the assert should be fine,
 |     /* XXX - remove the check - the assert should be fine,
 | ||||||
|        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(tcur)) |     if (!PyThreadState_IsCurrent(tcur)) { | ||||||
|         Py_FatalError("This thread state must be current when releasing"); |         Py_FatalError("This thread state must be current when releasing"); | ||||||
|  |     } | ||||||
|     assert(PyThreadState_IsCurrent(tcur)); |     assert(PyThreadState_IsCurrent(tcur)); | ||||||
|     --tcur->gilstate_counter; |     --tcur->gilstate_counter; | ||||||
|     assert(tcur->gilstate_counter >= 0); /* illegal counter value */ |     assert(tcur->gilstate_counter >= 0); /* illegal counter value */ | ||||||
|  | @ -1258,7 +1330,7 @@ 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). | ||||||
|          */ |          */ | ||||||
|         PyThreadState_DeleteCurrent(); |         _PyThreadState_DeleteCurrent(runtime); | ||||||
|     } |     } | ||||||
|     /* Release the lock if necessary */ |     /* Release the lock if necessary */ | ||||||
|     else if (oldstate == PyGILState_UNLOCKED) |     else if (oldstate == PyGILState_UNLOCKED) | ||||||
|  | @ -1363,7 +1435,8 @@ _release_xidata(void *arg) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| _call_in_interpreter(PyInterpreterState *interp, | _call_in_interpreter(struct _gilstate_runtime_state *gilstate, | ||||||
|  |                      PyInterpreterState *interp, | ||||||
|                      void (*func)(void *), void *arg) |                      void (*func)(void *), 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
 | ||||||
|  | @ -1371,18 +1444,18 @@ _call_in_interpreter(PyInterpreterState *interp, | ||||||
|      * naive approach. |      * naive approach. | ||||||
|      */ |      */ | ||||||
|     PyThreadState *save_tstate = NULL; |     PyThreadState *save_tstate = NULL; | ||||||
|     if (interp != _PyInterpreterState_Get()) { |     if (interp != _PyRuntimeGILState_GetThreadState(gilstate)->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(tstate); |         save_tstate = _PyThreadState_Swap(gilstate, tstate); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     func(arg); |     func(arg); | ||||||
| 
 | 
 | ||||||
|     // Switch back.
 |     // Switch back.
 | ||||||
|     if (save_tstate != NULL) { |     if (save_tstate != NULL) { | ||||||
|         PyThreadState_Swap(save_tstate); |         _PyThreadState_Swap(gilstate, save_tstate); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1405,7 +1478,8 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // "Release" the data and/or the object.
 |     // "Release" the data and/or the object.
 | ||||||
|     _call_in_interpreter(interp, _release_xidata, data); |     struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; | ||||||
|  |     _call_in_interpreter(gilstate, interp, _release_xidata, data); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PyObject * | PyObject * | ||||||
|  | @ -1421,7 +1495,8 @@ _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data) | ||||||
|    crossinterpdatafunc. It would be simpler and more efficient. */ |    crossinterpdatafunc. It would be simpler and more efficient. */ | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
| _register_xidata(PyTypeObject *cls, crossinterpdatafunc getdata) | _register_xidata(struct _xidregistry *xidregistry, PyTypeObject *cls, | ||||||
|  |                  crossinterpdatafunc getdata) | ||||||
| { | { | ||||||
|     // Note that we effectively replace already registered classes
 |     // Note that we effectively replace already registered classes
 | ||||||
|     // rather than failing.
 |     // rather than failing.
 | ||||||
|  | @ -1430,12 +1505,12 @@ _register_xidata(PyTypeObject *cls, crossinterpdatafunc getdata) | ||||||
|         return -1; |         return -1; | ||||||
|     newhead->cls = cls; |     newhead->cls = cls; | ||||||
|     newhead->getdata = getdata; |     newhead->getdata = getdata; | ||||||
|     newhead->next = _PyRuntime.xidregistry.head; |     newhead->next = xidregistry->head; | ||||||
|     _PyRuntime.xidregistry.head = newhead; |     xidregistry->head = newhead; | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void _register_builtins_for_crossinterpreter_data(void); | static void _register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry); | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls, | _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls, | ||||||
|  | @ -1453,12 +1528,13 @@ _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls, | ||||||
|     // Make sure the class isn't ever deallocated.
 |     // Make sure the class isn't ever deallocated.
 | ||||||
|     Py_INCREF((PyObject *)cls); |     Py_INCREF((PyObject *)cls); | ||||||
| 
 | 
 | ||||||
|     PyThread_acquire_lock(_PyRuntime.xidregistry.mutex, WAIT_LOCK); |     struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ; | ||||||
|     if (_PyRuntime.xidregistry.head == NULL) { |     PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK); | ||||||
|         _register_builtins_for_crossinterpreter_data(); |     if (xidregistry->head == NULL) { | ||||||
|  |         _register_builtins_for_crossinterpreter_data(xidregistry); | ||||||
|     } |     } | ||||||
|     int res = _register_xidata(cls, getdata); |     int res = _register_xidata(xidregistry, cls, getdata); | ||||||
|     PyThread_release_lock(_PyRuntime.xidregistry.mutex); |     PyThread_release_lock(xidregistry->mutex); | ||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1469,13 +1545,14 @@ _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls, | ||||||
| crossinterpdatafunc | crossinterpdatafunc | ||||||
| _PyCrossInterpreterData_Lookup(PyObject *obj) | _PyCrossInterpreterData_Lookup(PyObject *obj) | ||||||
| { | { | ||||||
|  |     struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ; | ||||||
|     PyObject *cls = PyObject_Type(obj); |     PyObject *cls = PyObject_Type(obj); | ||||||
|     crossinterpdatafunc getdata = NULL; |     crossinterpdatafunc getdata = NULL; | ||||||
|     PyThread_acquire_lock(_PyRuntime.xidregistry.mutex, WAIT_LOCK); |     PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK); | ||||||
|     struct _xidregitem *cur = _PyRuntime.xidregistry.head; |     struct _xidregitem *cur = xidregistry->head; | ||||||
|     if (cur == NULL) { |     if (cur == NULL) { | ||||||
|         _register_builtins_for_crossinterpreter_data(); |         _register_builtins_for_crossinterpreter_data(xidregistry); | ||||||
|         cur = _PyRuntime.xidregistry.head; |         cur = xidregistry->head; | ||||||
|     } |     } | ||||||
|     for(; cur != NULL; cur = cur->next) { |     for(; cur != NULL; cur = cur->next) { | ||||||
|         if (cur->cls == (PyTypeObject *)cls) { |         if (cur->cls == (PyTypeObject *)cls) { | ||||||
|  | @ -1484,7 +1561,7 @@ _PyCrossInterpreterData_Lookup(PyObject *obj) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     Py_DECREF(cls); |     Py_DECREF(cls); | ||||||
|     PyThread_release_lock(_PyRuntime.xidregistry.mutex); |     PyThread_release_lock(xidregistry->mutex); | ||||||
|     return getdata; |     return getdata; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1591,25 +1668,25 @@ _none_shared(PyObject *obj, _PyCrossInterpreterData *data) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| _register_builtins_for_crossinterpreter_data(void) | _register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry) | ||||||
| { | { | ||||||
|     // None
 |     // None
 | ||||||
|     if (_register_xidata((PyTypeObject *)PyObject_Type(Py_None), _none_shared) != 0) { |     if (_register_xidata(xidregistry, (PyTypeObject *)PyObject_Type(Py_None), _none_shared) != 0) { | ||||||
|         Py_FatalError("could not register None for cross-interpreter sharing"); |         Py_FatalError("could not register None for cross-interpreter sharing"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // int
 |     // int
 | ||||||
|     if (_register_xidata(&PyLong_Type, _long_shared) != 0) { |     if (_register_xidata(xidregistry, &PyLong_Type, _long_shared) != 0) { | ||||||
|         Py_FatalError("could not register int for cross-interpreter sharing"); |         Py_FatalError("could not register int for cross-interpreter sharing"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // bytes
 |     // bytes
 | ||||||
|     if (_register_xidata(&PyBytes_Type, _bytes_shared) != 0) { |     if (_register_xidata(xidregistry, &PyBytes_Type, _bytes_shared) != 0) { | ||||||
|         Py_FatalError("could not register bytes for cross-interpreter sharing"); |         Py_FatalError("could not register bytes for cross-interpreter sharing"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // str
 |     // str
 | ||||||
|     if (_register_xidata(&PyUnicode_Type, _str_shared) != 0) { |     if (_register_xidata(xidregistry, &PyUnicode_Type, _str_shared) != 0) { | ||||||
|         Py_FatalError("could not register str for cross-interpreter sharing"); |         Py_FatalError("could not register str for cross-interpreter sharing"); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Victor Stinner
						Victor Stinner