From 8dcde94c6068d7bb9c006091217617e2c11f75a9 Mon Sep 17 00:00:00 2001 From: Kristj?n Valur J?nsson Date: Sat, 23 Mar 2013 03:36:16 -0700 Subject: Issue #17522: Add the PyGILState_Check() API. --- Python/pystate.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'Python/pystate.c') diff --git a/Python/pystate.c b/Python/pystate.c index cfd61d0098..70038936d6 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -697,6 +697,15 @@ PyGILState_GetThisThreadState(void) return (PyThreadState *)PyThread_get_key_value(autoTLSkey); } +int +PyGILState_Check(void) +{ + /* can't use PyThreadState_Get() since it will assert that it has the GIL */ + PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed( + &_PyThreadState_Current); + return tstate && (tstate == PyGILState_GetThisThreadState()); +} + PyGILState_STATE PyGILState_Ensure(void) { -- cgit v1.2.1 From 3c24040c4c2cb747153c3480cae23babebe6457d Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sun, 5 May 2013 23:47:09 +0200 Subject: Issue #17094: Clear stale thread states after fork(). Note that this is a potentially disruptive change since it may release some system resources which would otherwise remain perpetually alive (e.g. database connections kept in thread-local storage). --- Python/pystate.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'Python/pystate.c') diff --git a/Python/pystate.c b/Python/pystate.c index 70038936d6..2a6f16c87f 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -414,6 +414,53 @@ PyThreadState_DeleteCurrent() #endif /* WITH_THREAD */ +/* + * Delete all thread states except the one passed as argument. + * Note that, if there is a current thread state, it *must* be the one + * passed as argument. Also, this won't touch any other interpreters + * than the current one, since we don't know which thread state should + * be kept in those other interpreteres. + */ +void +_PyThreadState_DeleteExcept(PyThreadState *tstate) +{ + PyInterpreterState *interp = tstate->interp; + PyThreadState *p, *next, *garbage; + HEAD_LOCK(); + /* Remove all thread states, except tstate, from the linked list of + thread states. This will allow calling PyThreadState_Clear() + without holding the lock. + XXX This would be simpler with a doubly-linked list. */ + garbage = interp->tstate_head; + interp->tstate_head = tstate; + if (garbage == tstate) { + garbage = garbage->next; + tstate->next = NULL; + } + else { + for (p = garbage; p; p = p->next) { + if (p->next == tstate) { + p->next = tstate->next; + tstate->next = NULL; + break; + } + } + } + if (tstate->next != NULL) + Py_FatalError("_PyThreadState_DeleteExcept: tstate not found " + "in interpreter thread states"); + HEAD_UNLOCK(); + /* Clear and deallocate all stale thread states. Even if this + executes Python code, we should be safe since it executes + in the current thread, not one of the stale threads. */ + for (p = garbage; p; p = next) { + next = p->next; + PyThreadState_Clear(p); + free(p); + } +} + + PyThreadState * PyThreadState_Get(void) { -- cgit v1.2.1 From 888977e55b0f7b8a0827956da732e7e099b6c308 Mon Sep 17 00:00:00 2001 From: Charles-Francois Natali Date: Wed, 8 May 2013 21:09:52 +0200 Subject: Issue #17912: Use a doubly linked-list for thread states. --- Python/pystate.c | 58 +++++++++++++++++--------------------------------------- 1 file changed, 17 insertions(+), 41 deletions(-) (limited to 'Python/pystate.c') diff --git a/Python/pystate.c b/Python/pystate.c index 2a6f16c87f..a8ed13867b 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -213,7 +213,10 @@ new_threadstate(PyInterpreterState *interp, int init) _PyThreadState_Init(tstate); HEAD_LOCK(); + tstate->prev = NULL; tstate->next = interp->tstate_head; + if (tstate->next) + tstate->next->prev = tstate; interp->tstate_head = tstate; HEAD_UNLOCK(); } @@ -349,35 +352,18 @@ static void tstate_delete_common(PyThreadState *tstate) { PyInterpreterState *interp; - PyThreadState **p; - PyThreadState *prev_p = NULL; if (tstate == NULL) Py_FatalError("PyThreadState_Delete: NULL tstate"); interp = tstate->interp; if (interp == NULL) Py_FatalError("PyThreadState_Delete: NULL interp"); HEAD_LOCK(); - for (p = &interp->tstate_head; ; p = &(*p)->next) { - if (*p == NULL) - Py_FatalError( - "PyThreadState_Delete: invalid tstate"); - if (*p == tstate) - break; - /* Sanity check. These states should never happen but if - * they do we must abort. Otherwise we'll end up spinning in - * in a tight loop with the lock held. A similar check is done - * in thread.c find_key(). */ - if (*p == prev_p) - Py_FatalError( - "PyThreadState_Delete: small circular list(!)" - " and tstate not found."); - prev_p = *p; - if ((*p)->next == interp->tstate_head) - Py_FatalError( - "PyThreadState_Delete: circular list(!) and" - " tstate not found."); - } - *p = tstate->next; + if (tstate->prev) + tstate->prev->next = tstate->next; + else + interp->tstate_head = tstate->next; + if (tstate->next) + tstate->next->prev = tstate->prev; HEAD_UNLOCK(); free(tstate); } @@ -429,26 +415,16 @@ _PyThreadState_DeleteExcept(PyThreadState *tstate) HEAD_LOCK(); /* Remove all thread states, except tstate, from the linked list of thread states. This will allow calling PyThreadState_Clear() - without holding the lock. - XXX This would be simpler with a doubly-linked list. */ + without holding the lock. */ garbage = interp->tstate_head; + if (garbage == tstate) + garbage = tstate->next; + if (tstate->prev) + tstate->prev->next = tstate->next; + if (tstate->next) + tstate->next->prev = tstate->prev; + tstate->prev = tstate->next = NULL; interp->tstate_head = tstate; - if (garbage == tstate) { - garbage = garbage->next; - tstate->next = NULL; - } - else { - for (p = garbage; p; p = p->next) { - if (p->next == tstate) { - p->next = tstate->next; - tstate->next = NULL; - break; - } - } - } - if (tstate->next != NULL) - Py_FatalError("_PyThreadState_DeleteExcept: tstate not found " - "in interpreter thread states"); HEAD_UNLOCK(); /* Clear and deallocate all stale thread states. Even if this executes Python code, we should be safe since it executes -- cgit v1.2.1