[pypy-commit] stmgc c8-small-uniform: fix another (currently untestable) bug

Raemi noreply at buildbot.pypy.org
Wed Dec 3 08:31:15 CET 2014


Author: Remi Meier <remi.meier at gmail.com>
Branch: c8-small-uniform
Changeset: r1513:222d1845dff3
Date: 2014-12-02 17:00 +0100
http://bitbucket.org/pypy/stmgc/changeset/222d1845dff3/

Log:	fix another (currently untestable) bug

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -278,94 +278,108 @@
         return;
     }
 
-    /* Find the set of segments we need to copy from and lock them: */
-    uint64_t segments_to_lock = 1UL << my_segnum;
-    cl = first_cl;
-    while ((next_cl = cl->next) != NULL) {
-        if (next_cl == INEV_RUNNING) {
+    bool needs_abort = false;
+    
+    while(1) {
+        /* retry IF: */
+        /* if at the time of "HERE" (s.b.) there happen to be
+           more commits (and bk copies) then it could be that
+           copy_bk_objs_in_page_from (s.b.) reads a bk copy that
+           is itself more recent than last_cl. This is fixed
+           by re-validating. */
+        first_cl = STM_PSEGMENT->last_commit_log_entry;
+        if (first_cl->next == NULL)
+            break;
+
+        /* Find the set of segments we need to copy from and lock them: */
+        uint64_t segments_to_lock = 1UL << my_segnum;
+        cl = first_cl;
+        while ((next_cl = cl->next) != NULL) {
+            if (next_cl == INEV_RUNNING) {
 #if STM_TESTS
-            if (free_if_abort != (void *)-1)
-                free(free_if_abort);
-            stm_abort_transaction();
+                if (free_if_abort != (void *)-1)
+                    free(free_if_abort);
+                stm_abort_transaction();
 #endif
-            /* only validate entries up to INEV */
-            break;
+                /* only validate entries up to INEV */
+                break;
+            }
+            assert(next_cl->rev_num > cl->rev_num);
+            cl = next_cl;
+
+            if (cl->written_count) {
+                segments_to_lock |= (1UL << cl->segment_num);
+            }
         }
-        assert(next_cl->rev_num > cl->rev_num);
-        cl = next_cl;
+        last_cl = cl;
+        /* HERE */
+        acquire_modification_lock_set(segments_to_lock);
 
-        if (cl->written_count) {
-            segments_to_lock |= (1UL << cl->segment_num);
-        }
-    }
-    last_cl = cl;
-    acquire_modification_lock_set(segments_to_lock);
 
+        /* import objects from first_cl to last_cl: */
+        if (first_cl != last_cl) {
+            uint64_t segment_really_copied_from = 0UL;
 
-    /* import objects from first_cl to last_cl: */
-    bool needs_abort = false;
-    if (first_cl != last_cl) {
-        uint64_t segment_really_copied_from = 0UL;
-
-        cl = first_cl;
-        while ((cl = cl->next) != NULL) {
-            if (!needs_abort) {
-                struct stm_undo_s *undo = cl->written;
-                struct stm_undo_s *end = cl->written + cl->written_count;
-                for (; undo < end; undo++) {
-                    if (_stm_was_read(undo->object)) {
-                        /* first reset all modified objects from the backup
-                           copies as soon as the first conflict is detected;
-                           then we will proceed below to update our segment from
-                           the old (but unmodified) version to the newer version.
-                        */
-                        reset_modified_from_backup_copies(my_segnum);
-                        needs_abort = true;
-                        break;
+            cl = first_cl;
+            while ((cl = cl->next) != NULL) {
+                if (!needs_abort) {
+                    struct stm_undo_s *undo = cl->written;
+                    struct stm_undo_s *end = cl->written + cl->written_count;
+                    for (; undo < end; undo++) {
+                        if (_stm_was_read(undo->object)) {
+                            /* first reset all modified objects from the backup
+                               copies as soon as the first conflict is detected;
+                               then we will proceed below to update our segment from
+                               the old (but unmodified) version to the newer version.
+                            */
+                            reset_modified_from_backup_copies(my_segnum);
+                            needs_abort = true;
+                            break;
+                        }
                     }
                 }
+
+                if (cl->written_count) {
+                    struct stm_undo_s *undo = cl->written;
+                    struct stm_undo_s *end = cl->written + cl->written_count;
+
+                    segment_really_copied_from |= (1UL << cl->segment_num);
+                    import_objects(cl->segment_num, -1, undo, end);
+
+                    /* here we can actually have our own modified version, so
+                       make sure to only copy things that are not modified in our
+                       segment... (if we do not abort) */
+                    copy_bk_objs_in_page_from
+                        (cl->segment_num, -1,     /* any page */
+                         !needs_abort);  /* if we abort, we still want to copy everything */
+                }
+
+                /* last fully validated entry */
+                STM_PSEGMENT->last_commit_log_entry = cl;
+                if (cl == last_cl)
+                    break;
             }
+            assert(cl == last_cl);
 
-            if (cl->written_count) {
-                struct stm_undo_s *undo = cl->written;
-                struct stm_undo_s *end = cl->written + cl->written_count;
+            /* XXX: this optimization fails in test_basic.py, bug3 */
+            /* OPT_ASSERT(segment_really_copied_from < (1 << NB_SEGMENTS)); */
+            /* int segnum; */
+            /* for (segnum = 0; segnum < NB_SEGMENTS; segnum++) { */
+            /*     if (segment_really_copied_from & (1UL << segnum)) { */
+            /*         /\* here we can actually have our own modified version, so */
+            /*            make sure to only copy things that are not modified in our */
+            /*            segment... (if we do not abort) *\/ */
+            /*         copy_bk_objs_in_page_from( */
+            /*             segnum, -1,     /\* any page *\/ */
+            /*             !needs_abort);  /\* if we abort, we still want to copy everything *\/ */
+            /*     } */
+            /* } */
+        }
 
-                segment_really_copied_from |= (1UL << cl->segment_num);
-                import_objects(cl->segment_num, -1, undo, end);
-
-                /* here we can actually have our own modified version, so
-                   make sure to only copy things that are not modified in our
-                   segment... (if we do not abort) */
-                copy_bk_objs_in_page_from
-                    (cl->segment_num, -1,     /* any page */
-                     !needs_abort);  /* if we abort, we still want to copy everything */
-            }
-
-            /* last fully validated entry */
-            STM_PSEGMENT->last_commit_log_entry = cl;
-            if (cl == last_cl)
-                break;
-        }
-        assert(cl == last_cl);
-
-        /* XXX: this optimization fails in test_basic.py, bug3 */
-        /* OPT_ASSERT(segment_really_copied_from < (1 << NB_SEGMENTS)); */
-        /* int segnum; */
-        /* for (segnum = 0; segnum < NB_SEGMENTS; segnum++) { */
-        /*     if (segment_really_copied_from & (1UL << segnum)) { */
-        /*         /\* here we can actually have our own modified version, so */
-        /*            make sure to only copy things that are not modified in our */
-        /*            segment... (if we do not abort) *\/ */
-        /*         copy_bk_objs_in_page_from( */
-        /*             segnum, -1,     /\* any page *\/ */
-        /*             !needs_abort);  /\* if we abort, we still want to copy everything *\/ */
-        /*     } */
-        /* } */
+        /* done with modifications */
+        release_modification_lock_set(segments_to_lock);
     }
 
-    /* done with modifications */
-    release_modification_lock_set(segments_to_lock);
-
     if (needs_abort) {
         if (free_if_abort != (void *)-1)
             free(free_if_abort);


More information about the pypy-commit mailing list