[pypy-commit] stmgc default: Tweak tweak tweak: a deadlock was possible there

arigo noreply at buildbot.pypy.org
Thu Jun 18 18:35:52 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r1862:ee0e63d791cb
Date: 2015-06-18 18:36 +0200
http://bitbucket.org/pypy/stmgc/changeset/ee0e63d791cb/

Log:	Tweak tweak tweak: a deadlock was possible there

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -495,6 +495,33 @@
 static void readd_wb_executed_flags(void);
 static void check_all_write_barrier_flags(char *segbase, struct list_s *list);
 
+static void wait_for_inevitable(void)
+{
+    intptr_t detached = 0;
+
+    s_mutex_lock();
+    if (safe_point_requested()) {
+        /* XXXXXX if the safe point below aborts, in
+           _validate_and_attach(), 'new' leaks */
+        enter_safe_point_if_requested();
+    }
+    else if (STM_PSEGMENT->last_commit_log_entry->next == INEV_RUNNING) {
+        /* loop until C_SEGMENT_FREE_OR_SAFE_POINT_REQ is signalled, but
+           try to detach an inevitable transaction regularly */
+        while (1) {
+            detached = fetch_detached_transaction();
+            if (detached != 0)
+                break;
+            if (cond_wait_timeout(C_SEGMENT_FREE_OR_SAFE_POINT_REQ, 0.00001))
+                break;
+        }
+    }
+    s_mutex_unlock();
+
+    if (detached != 0)
+        commit_fetched_detached_transaction(detached);
+}
+
 /* This is called to do stm_validate() and then attach 'new' at the
    head of the 'commit_log_root' chained list.  This function sleeps
    and retries until it succeeds or aborts.
@@ -523,24 +550,10 @@
 #endif
 
     if (STM_PSEGMENT->last_commit_log_entry->next == INEV_RUNNING) {
-        s_mutex_lock();
-        if (safe_point_requested()) {
-            /* XXXXXX if the safe point below aborts, 'new' leaks */
-            enter_safe_point_if_requested();
-        }
-        else if (STM_PSEGMENT->last_commit_log_entry->next == INEV_RUNNING) {
-            cond_wait(C_SEGMENT_FREE_OR_SAFE_POINT_REQ);
-        }
-        s_mutex_unlock();
+        wait_for_inevitable();
         goto retry_from_start;   /* redo _stm_validate() now */
     }
 
-    intptr_t detached = fetch_detached_transaction();
-    if (detached != 0) {
-        commit_fetched_detached_transaction(detached);
-        goto retry_from_start;
-    }
-
     /* we must not remove the WB_EXECUTED flags before validation as
        it is part of a condition in import_objects() called by
        copy_bk_objs_in_page_from to not overwrite our modifications.
@@ -1564,12 +1577,31 @@
             timing_become_inevitable(); /* for tests: another transaction */
             stm_abort_transaction();    /* is already inevitable, abort   */
 #endif
+
+            intptr_t detached = 0;
+
             s_mutex_lock();
             if (any_soon_finished_or_inevitable_thread_segment() &&
                     !safe_point_requested()) {
-                cond_wait(C_SEGMENT_FREE_OR_SAFE_POINT_REQ);
+
+                /* wait until C_SEGMENT_FREE_OR_SAFE_POINT_REQ is signalled */
+                while (!cond_wait_timeout(C_SEGMENT_FREE_OR_SAFE_POINT_REQ,
+                                          0.000054321)) {
+                    /* try to detach another inevitable transaction, but
+                       only after waiting a bit.  This is necessary to avoid
+                       deadlocks in some situations, which are hopefully
+                       not too common.  We don't want two threads constantly
+                       detaching each other. */
+                    detached = fetch_detached_transaction();
+                    if (detached != 0)
+                        break;
+                }
             }
             s_mutex_unlock();
+
+            if (detached != 0)
+                commit_fetched_detached_transaction(detached);
+
             num_waits++;
             goto retry_from_start;
         }


More information about the pypy-commit mailing list