Author: Tobias Weber <tobias_webe...@gmx.de>
Branch: c8-adaptive-trx-length-per-thread
Changeset: r2100:66f838f8595b
Date: 2017-07-11 13:15 +0200
http://bitbucket.org/pypy/stmgc/changeset/66f838f8595b/

Log:    Merge starvation fix

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -1638,7 +1638,7 @@
 
 void _stm_become_inevitable(const char *msg)
 {
-    int num_waits = 0;
+    int num_waits = 1;
 
     timing_become_inevitable();
 
@@ -1649,42 +1649,42 @@
     if (msg != MSG_INEV_DONT_SLEEP) {
         dprintf(("become_inevitable: %s\n", msg));
 
-        if (any_soon_finished_or_inevitable_thread_segment() &&
-                num_waits <= NB_SEGMENTS) {
+        if (any_soon_finished_or_inevitable_thread_segment()) {
 #if STM_TESTS                           /* for tests: another transaction */
             stm_abort_transaction();    /*   is already inevitable, abort */
 #endif
 
+            signal_commit_to_inevitable_transaction();
+
             s_mutex_lock();
             if (any_soon_finished_or_inevitable_thread_segment() &&
-                    !safe_point_requested()) {
-
-                signal_commit_to_inevitable_transaction();
+                    !safe_point_requested() &&
+                    num_waits <= NB_SEGMENTS) {
 
                 /* wait until C_SEGMENT_FREE_OR_SAFE_POINT_REQ is signalled */
                 EMIT_WAIT(STM_WAIT_OTHER_INEVITABLE);
-                if (!cond_wait_timeout(C_SEGMENT_FREE_OR_SAFE_POINT_REQ, 
0.00001)) {
-                    s_mutex_unlock();
-                    /* 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. */
-                    intptr_t detached = fetch_detached_transaction();
-                    if (detached != 0) {
-                       EMIT_WAIT_DONE();
-                       commit_fetched_detached_transaction(detached);
-                    }
-                    goto retry_from_start;
+                if (cond_wait_timeout(C_SEGMENT_FREE_OR_SAFE_POINT_REQ, 
0.00001)) {
+                    num_waits++;
                 }
-                num_waits++;
             }
             s_mutex_unlock();
+            /* XXX 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. */
+            intptr_t detached = fetch_detached_transaction();
+            if (detached != 0) {
+               EMIT_WAIT_DONE();
+               commit_fetched_detached_transaction(detached);
+               EMIT_WAIT(STM_WAIT_OTHER_INEVITABLE);
+            }
             goto retry_from_start;
         }
         else {
             EMIT_WAIT_DONE();
             if (!_validate_and_turn_inevitable()) {
+                EMIT_WAIT(STM_WAIT_OTHER_INEVITABLE);
                 goto retry_from_start;
             }
         }
diff --git a/c8/stm/detach.c b/c8/stm/detach.c
--- a/c8/stm/detach.c
+++ b/c8/stm/detach.c
@@ -229,14 +229,18 @@
     return STM_PSEGMENT->atomic_nesting_levels;
 }
 
+// max intptr_t value is 7FFFFFFFFFFFFFFF on 64-bit => larger than 2 * huge 
value
 #define HUGE_INTPTR_VALUE  0x3000000000000000L
 
 void stm_enable_atomic(stm_thread_local_t *tl)
 {
     if (!stm_is_atomic(tl)) {
+        // do for outermost atomic block only
         tl->self_or_0_if_atomic = 0;
         /* increment 'nursery_mark' by HUGE_INTPTR_VALUE, so that
-           stm_should_break_transaction() returns always false */
+           stm_should_break_transaction() returns always false.
+           preserves the previous nursery_mark, unless it is < 0
+           or >= huge value */
         intptr_t mark = (intptr_t)STM_SEGMENT->nursery_mark;
         if (mark < 0)
             mark = 0;
@@ -256,6 +260,7 @@
     STM_PSEGMENT->atomic_nesting_levels--;
 
     if (STM_PSEGMENT->atomic_nesting_levels == 0) {
+        // revert changes by stm_enable_atomic only if we left the outermost 
atomic block
         tl->self_or_0_if_atomic = (intptr_t)tl;
         /* decrement 'nursery_mark' by HUGE_INTPTR_VALUE, to cancel
            what was done in stm_enable_atomic() */
diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c
--- a/c8/stm/nursery.c
+++ b/c8/stm/nursery.c
@@ -543,7 +543,7 @@
     pseg->pub.nursery_mark -= nursery_used;
 
     if (pseg->commit_if_not_atomic
-        // && pseg->transaction_state == TS_INEVITABLE // TODO why does this 
break the mechanism? 
+        // && pseg->transaction_state == TS_INEVITABLE // TODO why does this 
break the mechanism?
         && pseg->pub.running_thread->self_or_0_if_atomic != 0) {
         // transaction is inevitable, not atomic, and commit has been 
signalled by waiting thread: commit immediately
         pseg->pub.nursery_mark = 0;
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to