[pypy-commit] stmgc c8-new-page-handling: don't apply undo copies in stm_validate() if we have our own modified version (probably not the whole story yet..)

Raemi noreply at buildbot.pypy.org
Fri Sep 26 16:01:47 CEST 2014


Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: c8-new-page-handling
Changeset: r1432:e565123efe0d
Date: 2014-09-26 16:01 +0200
http://bitbucket.org/pypy/stmgc/changeset/e565123efe0d/

Log:	don't apply undo copies in stm_validate() if we have our own
	modified version (probably not the whole story yet..)

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -9,7 +9,8 @@
    inner loop.
 */
 static void import_objects(
-        int from_segnum,            /* or -1: from undo->backup */
+        int from_segnum,            /* or -1: from undo->backup,
+                                       or -2: from undo->backup if not stm_was_read(obj) */
         uintptr_t pagenum,          /* or -1: "all accessible" */
         struct stm_undo_s *undo,
         struct stm_undo_s *end)
@@ -32,6 +33,9 @@
                 continue;
         }
 
+        if (from_segnum == -2 && _stm_was_read(obj))
+            continue;           /* only copy unmodified */
+
         dprintf(("import slice seg=%d obj=%p off=%lu sz=%d pg=%lu\n",
                  from_segnum, obj, SLICE_OFFSET(undo->slice),
                  SLICE_SIZE(undo->slice), current_page_num));
@@ -48,7 +52,8 @@
 
 /* ############# signal handler ############# */
 
-static void copy_bk_objs_in_page_from(int from_segnum, uintptr_t pagenum)
+static void copy_bk_objs_in_page_from(int from_segnum, uintptr_t pagenum,
+                                      bool only_if_not_modified)
 {
     /* looks at all bk copies of objects overlapping page 'pagenum' and
        copies the part in 'pagenum' back to the current segment */
@@ -58,7 +63,8 @@
     struct stm_undo_s *undo = (struct stm_undo_s *)list->items;
     struct stm_undo_s *end = (struct stm_undo_s *)(list->items + list->count);
 
-    import_objects(-1, pagenum, undo, end);
+    import_objects(only_if_not_modified ? -2 : -1,
+                   pagenum, undo, end);
 }
 
 static void go_to_the_past(uintptr_t pagenum,
@@ -138,7 +144,7 @@
              (char*)(get_virt_page_of(copy_from_segnum, pagenum) * 4096UL));
 
     /* if there were modifications in the page, revert them. */
-    copy_bk_objs_in_page_from(copy_from_segnum, pagenum);
+    copy_bk_objs_in_page_from(copy_from_segnum, pagenum, false);
 
     /* we need to go from 'src_version' to 'target_version'.  This
        might need a walk into the past. */
@@ -290,14 +296,15 @@
             }
         }
 
-        struct stm_undo_s *undo = cl->written;
-        struct stm_undo_s *end = cl->written + cl->written_count;
+        if (cl->written_count) {
+            struct stm_undo_s *undo = cl->written;
+            struct stm_undo_s *end = cl->written + cl->written_count;
 
-        segment_copied_from |= (1UL << cl->segment_num);
-        import_objects(cl->segment_num, -1, undo, end);
+            segment_copied_from |= (1UL << cl->segment_num);
+            import_objects(cl->segment_num, -1, undo, end);
+        }
 
         /* last fully validated entry */
-
         STM_PSEGMENT->last_commit_log_entry = cl;
     }
 
@@ -308,7 +315,10 @@
     for (segnum = 0; segment_copied_from != 0; segnum++) {
         if (segment_copied_from & (1UL << segnum)) {
             segment_copied_from &= ~(1UL << segnum);
-            copy_bk_objs_in_page_from(segnum, -1);
+            /* here we can actually have our own modified version, so
+               make sure to only copy things that are not modified in our
+               segment... */
+            copy_bk_objs_in_page_from(segnum, -1, true);
         }
     }
 
diff --git a/c8/test/test_basic.py b/c8/test/test_basic.py
--- a/c8/test/test_basic.py
+++ b/c8/test/test_basic.py
@@ -763,3 +763,23 @@
 
         # seg1 segfaults, validates, and aborts:
         py.test.raises(Conflict, stm_get_char, lp2)
+
+    def test_bug(self):
+        lp_char_5 = stm_allocate_old(384)
+
+        self.start_transaction() # R1
+        stm_set_char(lp_char_5, 'i', 384 - 1, False)
+        stm_set_char(lp_char_5, 'i', HDR, False)
+        #
+        #
+        self.switch(3)
+        self.start_transaction()  # R1
+        self.commit_transaction() # R2
+
+        self.start_transaction()  # R2
+        stm_set_char(lp_char_5, 'o', 384 - 1, False) # bk_copy
+        stm_set_char(lp_char_5, 'o', HDR, False)
+        #
+        #
+        self.switch(0) # validate -> R2
+        assert stm_get_char(lp_char_5, 384 - 1) == 'i'
diff --git a/c8/test/test_random.py b/c8/test/test_random.py
--- a/c8/test/test_random.py
+++ b/c8/test/test_random.py
@@ -497,7 +497,8 @@
 
 def op_switch_thread(ex, global_state, thread_state, new_thread_state=None):
     if new_thread_state is None:
-        new_thread_state = global_state.rnd.choice(global_state.thread_states)
+        new_thread_state = global_state.rnd.choice(
+            global_state.thread_states + [thread_state] * 3) # more likely not switch
 
     if new_thread_state != thread_state:
         if thread_state.transaction_state:


More information about the pypy-commit mailing list