Index: Python/pystate.c =================================================================== --- Python/pystate.c (révision 88020) +++ Python/pystate.c (copie de travail) @@ -37,8 +37,7 @@ /* The single PyInterpreterState used by this process' GILState implementation */ -static PyInterpreterState *autoInterpreterState = NULL; -static int autoTLSkey = 0; +static PyInterpreterState *main_interp = NULL; #else #define HEAD_INIT() /* Nothing */ #define HEAD_LOCK() /* Nothing */ @@ -53,7 +52,7 @@ PyThreadFrameGetter _PyThreadState_GetFrame = NULL; #ifdef WITH_THREAD -static void _PyGILState_NoteThreadState(PyThreadState* tstate); +static void _PyGILState_NoteThreadState(PyInterpreterState *, PyThreadState *); #endif @@ -68,6 +67,10 @@ #ifdef WITH_THREAD if (head_mutex == NULL) Py_FatalError("Can't initialize threads for interpreter"); + interp->auto_tls_key = PyThread_create_key(); + if (interp->auto_tls_key == -1) + Py_FatalError("Could not allocate TLS entry"); + assert(PyThread_get_key_value(interp->auto_tls_key) == NULL); #endif interp->modules = NULL; interp->modules_reloading = NULL; @@ -147,6 +150,9 @@ if (interp->tstate_head != NULL) Py_FatalError("PyInterpreterState_Delete: remaining threads"); *p = interp->next; +#ifdef WITH_THREAD + PyThread_delete_key(interp->auto_tls_key); +#endif HEAD_UNLOCK(); free(interp); } @@ -201,7 +207,7 @@ tstate->c_traceobj = NULL; if (init) - _PyThreadState_Init(tstate); + _PyThreadState_Init(interp, tstate); HEAD_LOCK(); tstate->next = interp->tstate_head; @@ -225,10 +231,10 @@ } void -_PyThreadState_Init(PyThreadState *tstate) +_PyThreadState_Init(PyInterpreterState *interp, PyThreadState *tstate) { #ifdef WITH_THREAD - _PyGILState_NoteThreadState(tstate); + _PyGILState_NoteThreadState(interp, tstate); #endif } @@ -340,8 +346,8 @@ Py_FatalError("PyThreadState_Delete: tstate is still current"); tstate_delete_common(tstate); #ifdef WITH_THREAD - if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate) - PyThread_delete_key_value(autoTLSkey); + if (main_interp && PyThread_get_key_value(main_interp->auto_tls_key) == tstate) + PyThread_delete_key_value(main_interp->auto_tls_key); #endif /* WITH_THREAD */ } @@ -357,8 +363,8 @@ "PyThreadState_DeleteCurrent: no current tstate"); _Py_atomic_store_relaxed(&_PyThreadState_Current, NULL); tstate_delete_common(tstate); - if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate) - PyThread_delete_key_value(autoTLSkey); + if (main_interp && PyThread_get_key_value(main_interp->auto_tls_key) == tstate) + PyThread_delete_key_value(main_interp->auto_tls_key); PyEval_ReleaseLock(); } #endif /* WITH_THREAD */ @@ -568,21 +574,16 @@ _PyGILState_Init(PyInterpreterState *i, PyThreadState *t) { assert(i && t); /* must init with valid states */ - autoTLSkey = PyThread_create_key(); - if (autoTLSkey == -1) - Py_FatalError("Could not allocate TLS entry"); - autoInterpreterState = i; - assert(PyThread_get_key_value(autoTLSkey) == NULL); - assert(t->gilstate_counter == 0); + main_interp = i; + assert(t->gilstate_counter == 1); - _PyGILState_NoteThreadState(t); + _PyGILState_NoteThreadState(i, t); } void _PyGILState_Fini(void) { - PyThread_delete_key(autoTLSkey); - autoInterpreterState = NULL; + main_interp = NULL; } /* When a thread state is created for a thread by some mechanism other than @@ -591,13 +592,13 @@ a better fix for SF bug #1010677 than the first one attempted). */ static void -_PyGILState_NoteThreadState(PyThreadState* tstate) +_PyGILState_NoteThreadState(PyInterpreterState *interp, PyThreadState* tstate) { - /* If autoTLSkey isn't initialized, this must be the very first + /* If the main interpreter 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 (!autoInterpreterState) - return; +// if (!main_interp) +// return; /* Stick the thread state for this thread in thread local storage. @@ -613,8 +614,8 @@ state created for that given OS level thread will "win", which seems reasonable behaviour. */ - if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0) - Py_FatalError("Couldn't create autoTLSkey mapping"); + if (PyThread_set_key_value(interp->auto_tls_key, (void *)tstate) < 0) + Py_FatalError("Couldn't create auto_tls_key mapping"); /* PyGILState_Release must not try to delete this thread state. */ tstate->gilstate_counter = 1; @@ -624,13 +625,13 @@ PyThreadState * PyGILState_GetThisThreadState(void) { - if (autoInterpreterState == NULL) + if (main_interp == NULL) return NULL; - return (PyThreadState *)PyThread_get_key_value(autoTLSkey); + return (PyThreadState *)PyThread_get_key_value(main_interp->auto_tls_key); } PyGILState_STATE -PyGILState_Ensure(void) +PyGILState_EnsureEx(PyInterpreterState *interp) { int current; PyThreadState *tcur; @@ -639,11 +640,11 @@ spells out other issues. Embedders are expected to have called Py_Initialize() and usually PyEval_InitThreads(). */ - assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */ - tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey); + assert(interp); + tcur = (PyThreadState *)PyThread_get_key_value(interp->auto_tls_key); if (tcur == NULL) { /* Create a new thread state for this thread */ - tcur = PyThreadState_New(autoInterpreterState); + tcur = PyThreadState_New(interp); if (tcur == NULL) Py_FatalError("Couldn't create thread-state for new thread"); /* This is our thread state! We'll need to delete it in the @@ -664,11 +665,17 @@ return current ? PyGILState_LOCKED : PyGILState_UNLOCKED; } +PyGILState_STATE +PyGILState_Ensure() +{ + return PyGILState_EnsureEx(main_interp); +} + void -PyGILState_Release(PyGILState_STATE oldstate) +PyGILState_ReleaseEx(PyInterpreterState *interp, PyGILState_STATE oldstate) { PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value( - autoTLSkey); + interp->auto_tls_key); if (tcur == NULL) Py_FatalError("auto-releasing thread-state, " "but no thread-state for this thread"); @@ -702,6 +709,12 @@ PyEval_SaveThread(); } +void +PyGILState_Release(PyGILState_STATE oldstate) +{ + PyGILState_ReleaseEx(main_interp, oldstate); +} + #ifdef __cplusplus } #endif Index: Include/pystate.h =================================================================== --- Include/pystate.h (révision 88020) +++ Include/pystate.h (copie de travail) @@ -38,7 +38,10 @@ #ifdef WITH_TSC int tscdump; #endif - + /* For PyGILState_* APIs */ +#ifdef WITH_THREAD + int auto_tls_key; +#endif } PyInterpreterState; #endif @@ -126,7 +129,7 @@ PyAPI_FUNC(PyThreadState *) PyThreadState_New(PyInterpreterState *); PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *); -PyAPI_FUNC(void) _PyThreadState_Init(PyThreadState *); +PyAPI_FUNC(void) _PyThreadState_Init(PyInterpreterState *, PyThreadState *); PyAPI_FUNC(void) PyThreadState_Clear(PyThreadState *); PyAPI_FUNC(void) PyThreadState_Delete(PyThreadState *); #ifdef WITH_THREAD @@ -180,6 +183,7 @@ Failure is a fatal error. */ PyAPI_FUNC(PyGILState_STATE) PyGILState_Ensure(void); +PyAPI_FUNC(PyGILState_STATE) PyGILState_EnsureEx(PyInterpreterState *); /* Release any resources previously acquired. After this call, Python's state will be the same as it was prior to the corresponding @@ -190,6 +194,7 @@ PyGILState_Release on the same thread. */ PyAPI_FUNC(void) PyGILState_Release(PyGILState_STATE); +PyAPI_FUNC(void) PyGILState_ReleaseEx(PyInterpreterState *, PyGILState_STATE); /* Helper/diagnostic function - get the current thread state for this thread. May return NULL if no GILState API has been used Index: Modules/_ctypes/ctypes.h =================================================================== --- Modules/_ctypes/ctypes.h (révision 88020) +++ Modules/_ctypes/ctypes.h (copie de travail) @@ -62,6 +62,7 @@ void *pcl_exec; /* the C callable, executable */ ffi_cif cif; int flags; + PyInterpreterState *interp; PyObject *converters; PyObject *callable; PyObject *restype; Index: Modules/_ctypes/callbacks.c =================================================================== --- Modules/_ctypes/callbacks.c (révision 88020) +++ Modules/_ctypes/callbacks.c (copie de travail) @@ -151,6 +151,7 @@ static void _CallPythonObject(void *mem, ffi_type *restype, SETFUNC setfunc, + PyInterpreterState *interp, PyObject *callable, PyObject *converters, int flags, @@ -163,7 +164,7 @@ PyObject *error_object = NULL; int *space; #ifdef WITH_THREAD - PyGILState_STATE state = PyGILState_Ensure(); + PyGILState_STATE state = PyGILState_EnsureEx(interp); #endif nArgs = PySequence_Length(converters); @@ -307,7 +308,7 @@ Done: Py_XDECREF(arglist); #ifdef WITH_THREAD - PyGILState_Release(state); + PyGILState_ReleaseEx(interp, state); #endif } @@ -321,6 +322,7 @@ _CallPythonObject(resp, p->ffi_restype, p->setfunc, + p->interp, p->callable, p->converters, p->flags, @@ -338,6 +340,7 @@ return NULL; } + p->interp = PyThreadState_Get()->interp; p->pcl_exec = NULL; p->pcl_write = NULL; memset(&p->cif, 0, sizeof(p->cif)); Index: Modules/_threadmodule.c =================================================================== --- Modules/_threadmodule.c (révision 88020) +++ Modules/_threadmodule.c (copie de travail) @@ -984,7 +984,7 @@ tstate = boot->tstate; tstate->thread_id = PyThread_get_thread_ident(); - _PyThreadState_Init(tstate); + _PyThreadState_Init(boot->interp, tstate); PyEval_AcquireThread(tstate); nb_threads++; res = PyEval_CallObjectWithKeywords(