[pypy-commit] stmgc default: fix for previously committed test and do some more resetting

Raemi pypy.commits at gmail.com
Thu Jul 7 08:17:05 EDT 2016


Author: Remi Meier <remi.meier at gmail.com>
Branch: 
Changeset: r1994:bfbab11bd95f
Date: 2016-07-07 14:14 +0200
http://bitbucket.org/pypy/stmgc/changeset/bfbab11bd95f/

Log:	fix for previously committed test and do some more resetting

	After an in-validation-reset of a noconflict obj, the obj was still
	marked as having been read before. Also, an obj with cards is not in
	old_objects_with_cards_set anymore after a collection. Thus we
	should clear all cards unconditionally during a reset.

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -233,7 +233,7 @@
                     for (; undo < end; undo++) {
                         object_t *obj;
 
-                        if (undo->type != TYPE_POSITION_MARKER) {
+                        if (LIKELY(undo->type != TYPE_POSITION_MARKER)) {
                             /* common case: 'undo->object' was written to
                                in this past commit, so we must check that
                                it was not read by us. */
@@ -263,7 +263,10 @@
                                an abort. However, from now on, we also assume
                                that an abort would not roll-back to what is in
                                the backup copy, as we don't trace the bkcpy
-                               during major GCs.
+                               during major GCs. (Seg0 may contain the version
+                               found in the other segment and thus not have to
+                               content of our bk_copy)
+
                                We choose the approach to reset all our changes
                                to this obj here, so that we can throw away the
                                backup copy completely: */
@@ -396,11 +399,15 @@
 */
 static void _validate_and_attach(struct stm_commit_log_entry_s *new)
 {
+    uintptr_t cle_length = 0;
     struct stm_commit_log_entry_s *old;
 
     OPT_ASSERT(new != NULL);
     OPT_ASSERT(new != INEV_RUNNING);
 
+    cle_length = list_count(STM_PSEGMENT->modified_old_objects);
+    assert(cle_length == new->written_count * 3);
+
     soon_finished_or_inevitable_thread_segment();
 
  retry_from_start:
@@ -409,6 +416,16 @@
         stm_abort_transaction();
     }
 
+    if (cle_length != list_count(STM_PSEGMENT->modified_old_objects)) {
+        /* something changed the list of modified objs during _stm_validate; or
+         * during a major GC that also does _stm_validate(). That "something"
+         * can only be a reset of a noconflict obj. Thus, we recreate the CL
+         * entry */
+        free_cle(new);
+        new = _create_commit_log_entry();
+        cle_length = list_count(STM_PSEGMENT->modified_old_objects);
+    }
+
 #if STM_TESTS
     if (STM_PSEGMENT->transaction_state != TS_INEVITABLE
         && STM_PSEGMENT->last_commit_log_entry->next == INEV_RUNNING) {
@@ -607,6 +624,10 @@
     size_t start_offset;
     if (first_call) {
         start_offset = 0;
+
+        /* flags like a never-touched obj */
+        assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
+        assert(!(obj->stm_flags & GCFLAG_WB_EXECUTED));
     } else {
         start_offset = -1;
     }
@@ -1288,10 +1309,21 @@
 
     reset_modified_from_backup_copies(segment_num, obj);
 
+    /* reset read marker (must not be considered read either) */
+    ((struct stm_read_marker_s *)
+     (pseg->pub.segment_base + (((uintptr_t)obj) >> 4)))->rm = 0;
+
+    /* reset possibly marked cards */
+    if (get_page_status_in(segment_num, (uintptr_t)obj / 4096) == PAGE_ACCESSIBLE
+        && obj_should_use_cards(pseg->pub.segment_base, obj)) {
+        /* if header is not accessible, we didn't mark any cards */
+        _reset_object_cards(pseg, obj, CARD_CLEAR, false, false);
+    }
+
+    /* remove from all other lists */
     LIST_FOREACH_R(pseg->old_objects_with_cards_set, object_t * /*item*/,
        {
            if (item == obj) {
-               _reset_object_cards(pseg, item, CARD_CLEAR, false, false);
                /* copy last element over this one (HACK) */
                _lst->count -= 1;
                _lst->items[_i] = _lst->items[_lst->count];
@@ -1330,7 +1362,7 @@
             continue;
 
         object_t *obj = undo->object;
-        if (only_obj != NULL && obj != only_obj)
+        if (UNLIKELY(only_obj != NULL) && LIKELY(obj != only_obj))
             continue;
 
         char *dst = REAL_ADDRESS(pseg->pub.segment_base, obj);
@@ -1345,17 +1377,15 @@
 
         free_bk(undo);
 
-        if (only_obj != NULL) {
-            /* WB_EXECUTED should be set on small objs, but not on card objs */
-            assert(IMPLY(only_obj != NULL,
-                         (((struct object_s *)dst)->stm_flags
-                          & GCFLAG_NO_CONFLICT)));
+        if (UNLIKELY(only_obj != NULL)) {
+            assert(((struct object_s *)dst)->stm_flags & GCFLAG_NO_CONFLICT);
+
             /* copy last element over this one */
             end--;
             list->count -= 3;
-            if (undo < end)
-                *undo = *end;
-            undo--;  /* next itr */
+            *undo = *end;
+            /* to neutralise the increment for the next iter: */
+            undo--;
         }
     }
 
@@ -1664,13 +1694,13 @@
     assert(STM_PSEGMENT->privatization_lock);
     assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
     assert(!(obj->stm_flags & GCFLAG_WB_EXECUTED));
+    assert(!(obj->stm_flags & GCFLAG_CARDS_SET));
 
     ssize_t obj_size = stmcb_size_rounded_up(
         (struct object_s *)REAL_ADDRESS(STM_SEGMENT->segment_base, obj));
     OPT_ASSERT(obj_size >= 16);
 
     if (LIKELY(is_small_uniform(obj))) {
-        assert(!(obj->stm_flags & GCFLAG_CARDS_SET));
         OPT_ASSERT(obj_size <= GC_LAST_SMALL_SIZE);
         _synchronize_fragment((stm_char *)obj, obj_size);
         return;
diff --git a/c8/test/test_noconfl.py b/c8/test/test_noconfl.py
--- a/c8/test/test_noconfl.py
+++ b/c8/test/test_noconfl.py
@@ -175,6 +175,8 @@
 
         stm_set_char(o, 'a')
         stm_set_char(oh, 'x', use_cards=True)
+        assert stm_was_read(o)
+        assert stm_was_read(oh)
         assert o in modified_old_objects()
         assert oh in modified_old_objects()
         assert o in objects_pointing_to_nursery()
@@ -189,6 +191,8 @@
         self.commit_transaction()
 
         self.switch(0, False)
+        assert stm_was_read(o)
+        assert stm_was_read(oh)
         assert stm_get_char(o) == 'a'
         assert stm_get_char(oh) == 'x'
         assert o in modified_old_objects()
@@ -197,6 +201,8 @@
         assert oh not in objects_pointing_to_nursery()
         assert oh in old_objects_with_cards_set()
         stm_validate()
+        assert not stm_was_read(o)
+        assert not stm_was_read(oh)
         assert stm_get_char(o) == 'b'
         assert stm_get_char(oh) == 'y'
         assert o not in modified_old_objects()


More information about the pypy-commit mailing list