Author: Remi Meier <[email protected]>
Branch: c8-new-page-handling
Changeset: r1503:15d0affd8675
Date: 2014-11-11 13:56 +0100
http://bitbucket.org/pypy/stmgc/changeset/15d0affd8675/

Log:    fix deadlock

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -157,6 +157,8 @@
     page_privatize_in(my_segnum, pagenum);
     assert(get_page_status_in(my_segnum, pagenum) == PAGE_PRIVATE);
 
+    /* before copying anything, acquire modification locks from our and
+       the other segment */
     uint64_t to_lock = (1UL << copy_from_segnum)| (1UL << my_segnum);
     acquire_modification_lock_set(to_lock);
     pagecopy((char*)(get_virt_page_of(my_segnum, pagenum) * 4096UL),
@@ -169,7 +171,6 @@
        might need a walk into the past. */
     struct stm_commit_log_entry_s *src_version, *target_version;
     src_version = get_priv_segment(copy_from_segnum)->last_commit_log_entry;
-    OPT_ASSERT(src_version->rev_num == most_recent_rev);
     target_version = STM_PSEGMENT->last_commit_log_entry;
 
 
@@ -229,7 +230,7 @@
 
     fprintf(stderr, "commit log:\n");
     while ((cl = cl->next)) {
-        if (cl == (void *)-1) {
+        if (cl == INEV_RUNNING) {
             fprintf(stderr, "  INEVITABLE\n");
             return;
         }
@@ -262,7 +263,7 @@
     /* Don't check this 'cl'. This entry is already checked */
 
     if (STM_PSEGMENT->transaction_state == TS_INEVITABLE) {
-        assert(first_cl->next == (void*)-1);
+        assert(first_cl->next == INEV_RUNNING);
         return;
     }
 
@@ -270,13 +271,13 @@
     uint64_t segments_to_lock = 1UL << my_segnum;
     cl = first_cl;
     while ((next_cl = cl->next) != NULL) {
-        if (next_cl == (void *)-1) {
+        if (next_cl == INEV_RUNNING) {
 #if STM_TESTS
             if (free_if_abort != (void *)-1)
                 free(free_if_abort);
             stm_abort_transaction();
 #endif
-            /* only go this far when validating */
+            /* only validate entries up to INEV */
             break;
         }
         assert(next_cl->rev_num > cl->rev_num);
@@ -324,7 +325,10 @@
 
             /* last fully validated entry */
             STM_PSEGMENT->last_commit_log_entry = cl;
+            if (cl == last_cl)
+                break;
         }
+        assert(cl == last_cl);
 
         OPT_ASSERT(segment_really_copied_from < (1 << NB_SEGMENTS));
         int segnum;
@@ -346,6 +350,8 @@
     if (needs_abort) {
         if (free_if_abort != (void *)-1)
             free(free_if_abort);
+        /* pages may be inconsistent */
+
         stm_abort_transaction();
     }
 }
@@ -381,18 +387,25 @@
         /* try to attach to commit log: */
         old = STM_PSEGMENT->last_commit_log_entry;
         if (old->next == NULL) {
-            if ((uintptr_t)new != -1) /* INEVITABLE */
+            if (new != INEV_RUNNING) /* INEVITABLE */
                 new->rev_num = old->rev_num + 1;
 
             if (__sync_bool_compare_and_swap(&old->next, NULL, new))
                 break;   /* success! */
+        } else if (old->next == INEV_RUNNING) {
+            /* we failed because there is an INEV transaction running */
+            usleep(10);
         }
+
+        /* check for requested safe point. otherwise an INEV transaction
+           may try to commit but cannot because of the busy-loop here. */
+        _stm_collectable_safe_point();
     }
 }
 
 static void _validate_and_turn_inevitable(void)
 {
-    _validate_and_attach((struct stm_commit_log_entry_s *)-1);
+    _validate_and_attach((struct stm_commit_log_entry_s *)INEV_RUNNING);
 }
 
 static void _validate_and_add_to_commit_log(void)
@@ -403,9 +416,9 @@
     if (STM_PSEGMENT->transaction_state == TS_INEVITABLE) {
         old = STM_PSEGMENT->last_commit_log_entry;
         new->rev_num = old->rev_num + 1;
-        OPT_ASSERT(old->next == (void *)-1);
+        OPT_ASSERT(old->next == INEV_RUNNING);
 
-        bool yes = __sync_bool_compare_and_swap(&old->next, (void*)-1, new);
+        bool yes = __sync_bool_compare_and_swap(&old->next, INEV_RUNNING, new);
         OPT_ASSERT(yes);
     }
     else {
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -123,6 +123,7 @@
    data from 'written[n].backup' is the content of (slices of) the
    object as they were *before* that commit occurred.
 */
+#define INEV_RUNNING ((void*)-1)
 struct stm_commit_log_entry_s {
     struct stm_commit_log_entry_s *volatile next;
     int segment_num;
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to