mirror of
https://github.com/python/cpython.git
synced 2025-09-09 18:32:22 +00:00
Issue #17912: Use a doubly linked-list for thread states.
This commit is contained in:
parent
04e70d19e7
commit
f28dfdd07b
2 changed files with 18 additions and 41 deletions
|
@ -69,6 +69,7 @@ typedef struct _ts PyThreadState;
|
||||||
typedef struct _ts {
|
typedef struct _ts {
|
||||||
/* See Python/ceval.c for comments explaining most fields */
|
/* See Python/ceval.c for comments explaining most fields */
|
||||||
|
|
||||||
|
struct _ts *prev;
|
||||||
struct _ts *next;
|
struct _ts *next;
|
||||||
PyInterpreterState *interp;
|
PyInterpreterState *interp;
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,10 @@ new_threadstate(PyInterpreterState *interp, int init)
|
||||||
_PyThreadState_Init(tstate);
|
_PyThreadState_Init(tstate);
|
||||||
|
|
||||||
HEAD_LOCK();
|
HEAD_LOCK();
|
||||||
|
tstate->prev = NULL;
|
||||||
tstate->next = interp->tstate_head;
|
tstate->next = interp->tstate_head;
|
||||||
|
if (tstate->next)
|
||||||
|
tstate->next->prev = tstate;
|
||||||
interp->tstate_head = tstate;
|
interp->tstate_head = tstate;
|
||||||
HEAD_UNLOCK();
|
HEAD_UNLOCK();
|
||||||
}
|
}
|
||||||
|
@ -349,35 +352,18 @@ static void
|
||||||
tstate_delete_common(PyThreadState *tstate)
|
tstate_delete_common(PyThreadState *tstate)
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp;
|
PyInterpreterState *interp;
|
||||||
PyThreadState **p;
|
|
||||||
PyThreadState *prev_p = NULL;
|
|
||||||
if (tstate == NULL)
|
if (tstate == NULL)
|
||||||
Py_FatalError("PyThreadState_Delete: NULL tstate");
|
Py_FatalError("PyThreadState_Delete: NULL tstate");
|
||||||
interp = tstate->interp;
|
interp = tstate->interp;
|
||||||
if (interp == NULL)
|
if (interp == NULL)
|
||||||
Py_FatalError("PyThreadState_Delete: NULL interp");
|
Py_FatalError("PyThreadState_Delete: NULL interp");
|
||||||
HEAD_LOCK();
|
HEAD_LOCK();
|
||||||
for (p = &interp->tstate_head; ; p = &(*p)->next) {
|
if (tstate->prev)
|
||||||
if (*p == NULL)
|
tstate->prev->next = tstate->next;
|
||||||
Py_FatalError(
|
else
|
||||||
"PyThreadState_Delete: invalid tstate");
|
interp->tstate_head = tstate->next;
|
||||||
if (*p == tstate)
|
if (tstate->next)
|
||||||
break;
|
tstate->next->prev = tstate->prev;
|
||||||
/* 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;
|
|
||||||
HEAD_UNLOCK();
|
HEAD_UNLOCK();
|
||||||
free(tstate);
|
free(tstate);
|
||||||
}
|
}
|
||||||
|
@ -429,26 +415,16 @@ _PyThreadState_DeleteExcept(PyThreadState *tstate)
|
||||||
HEAD_LOCK();
|
HEAD_LOCK();
|
||||||
/* 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. */
|
||||||
XXX This would be simpler with a doubly-linked list. */
|
|
||||||
garbage = interp->tstate_head;
|
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;
|
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();
|
HEAD_UNLOCK();
|
||||||
/* 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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue