summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorCharles-Francois Natali <cf.natali@gmail.com>2013-05-08 19:09:52 (GMT)
committerCharles-Francois Natali <cf.natali@gmail.com>2013-05-08 19:09:52 (GMT)
commitf28dfdd07b57fa16f7d489e7ac99d9a15f1bef80 (patch)
treef32b7032a307596537d237bb18ade33676d11f46 /Python
parent04e70d19e7a5ab0cea7d3d231606180226e16f06 (diff)
downloadcpython-f28dfdd07b57fa16f7d489e7ac99d9a15f1bef80.zip
cpython-f28dfdd07b57fa16f7d489e7ac99d9a15f1bef80.tar.gz
cpython-f28dfdd07b57fa16f7d489e7ac99d9a15f1bef80.tar.bz2
Issue #17912: Use a doubly linked-list for thread states.
Diffstat (limited to 'Python')
-rw-r--r--Python/pystate.c58
1 files changed, 17 insertions, 41 deletions
diff --git a/Python/pystate.c b/Python/pystate.c
index 2a6f16c..a8ed138 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