Index: Python/pystate.c =================================================================== --- Python/pystate.c (révision 88020) +++ Python/pystate.c (copie de travail) @@ -34,11 +34,10 @@ extern "C" { #endif -/* The single PyInterpreterState used by this process' - GILState implementation +/* The single PyInterpreterState used by the legacy PyGILState_* API + (non-Ex variants) */ -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 } @@ -336,12 +342,13 @@ void PyThreadState_Delete(PyThreadState *tstate) { + PyInterpreterState *interp = tstate->interp; if (tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current)) 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 (PyThread_get_key_value(interp->auto_tls_key) == tstate) + PyThread_delete_key_value(interp->auto_tls_key); #endif /* WITH_THREAD */ } @@ -352,13 +359,14 @@ { PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed( &_PyThreadState_Current); + PyInterpreterState *interp = tstate->interp; if (tstate == NULL) Py_FatalError( "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 (interp && PyThread_get_key_value(interp->auto_tls_key) == tstate) + PyThread_delete_key_value(interp->auto_tls_key); PyEval_ReleaseLock(); } #endif /* WITH_THREAD */ @@ -393,6 +401,7 @@ to it, we need to ensure errno doesn't change. */ int err = errno; + /* XXX why this and not oldts instead? */ PyThreadState *check = PyGILState_GetThisThreadState(); if (check && check->interp == newts->interp && check != newts) Py_FatalError("Invalid thread state for this thread"); @@ -557,7 +566,6 @@ PyThreadState_IsCurrent(PyThreadState *tstate) { /* Must be the tstate for this thread */ - assert(PyGILState_GetThisThreadState()==tstate); return tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current); } @@ -568,21 +576,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,14 +594,8 @@ 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 - threadstate created in Py_Initialize(). Don't do anything for now - (we'll be back here when _PyGILState_Init is called). */ - if (!autoInterpreterState) - return; - /* Stick the thread state for this thread in thread local storage. The only situation where you can legitimately have more than one @@ -613,8 +610,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; @@ -622,15 +619,21 @@ /* The public functions */ PyThreadState * +PyGILState_GetThisThreadStateEx(PyInterpreterState *interp) +{ + return (PyThreadState *)PyThread_get_key_value(interp->auto_tls_key); +} + +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 +642,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 +667,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"); @@ -679,7 +688,6 @@ */ if (! PyThreadState_IsCurrent(tcur)) Py_FatalError("This thread state must be current when releasing"); - assert(PyThreadState_IsCurrent(tcur)); --tcur->gilstate_counter; assert(tcur->gilstate_counter >= 0); /* illegal counter value */ @@ -702,6 +710,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 @@ -198,6 +203,7 @@ on the main thread. */ PyAPI_FUNC(PyThreadState *) PyGILState_GetThisThreadState(void); +PyAPI_FUNC(PyThreadState *) PyGILState_GetThisThreadStateEx(PyInterpreterState *); /* The implementation of sys._current_frames() Returns a dict mapping thread id to that thread's current frame. 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(