]> granicus.if.org Git - python/commitdiff
Issue #17912: Use a doubly linked-list for thread states.
authorCharles-Francois Natali <cf.natali@gmail.com>
Wed, 8 May 2013 19:09:52 +0000 (21:09 +0200)
committerCharles-Francois Natali <cf.natali@gmail.com>
Wed, 8 May 2013 19:09:52 +0000 (21:09 +0200)
Include/pystate.h
Python/pystate.c

index a8fcc73bcb3b4ad97ad0f39bd24e34312333c3db..cd1d7765be0c9dfb3c4febf2ee91c9ee1b220af1 100644 (file)
@@ -69,6 +69,7 @@ typedef struct _ts PyThreadState;
 typedef struct _ts {
     /* See Python/ceval.c for comments explaining most fields */
 
+    struct _ts *prev;
     struct _ts *next;
     PyInterpreterState *interp;
 
index 2a6f16c87f119175ab1780211f7c671a07dd4a02..a8ed13867bbac812ac5348d67abc9684f1f0d347 100644 (file)
@@ -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