[pypy-commit] stmgc default: fix the read-write conflict location in case of a conflict between

arigo noreply at buildbot.pypy.org
Mon Feb 9 19:11:14 CET 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r1616:65a89cd8a6c0
Date: 2015-02-09 19:11 +0100
http://bitbucket.org/pypy/stmgc/changeset/65a89cd8a6c0/

Log:	fix the read-write conflict location in case of a conflict between a
	stmdict.keys() and a write of an entry

diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -435,26 +435,31 @@
 
         char *remote_base = get_segment_base(i);
         object_t *conflicting_obj;
+        uintptr_t j, limit;
+        struct list_s *lst;
 
-        LIST_FOREACH_R(
-            STM_PSEGMENT->modified_old_objects,
-            object_t * /*item*/,
-            ({
-                if (was_read_remote(remote_base, item)) {
-                    conflicting_obj = item;
-                    goto found_conflict;
-                }
-            }));
+        /* Look in forward order: this is an attempt to report the _first_
+           write that conflicts with another segment's reads
+        */
+        lst = STM_PSEGMENT->modified_old_objects;
+        limit = list_count(lst);
+        for (j = 0; j < limit; j++) {
+            object_t *obj = (object_t *)list_item(lst, j);
+            if (was_read_remote(remote_base, obj)) {
+                conflicting_obj = obj;
+                goto found_conflict;
+            }
+        }
 
-        LIST_FOREACH_R(
-            STM_PSEGMENT->modified_old_hashtables,
-            object_t * /*item*/,
-            ({
-                if (was_read_remote(remote_base, item)) {
-                    conflicting_obj = item;
-                    goto found_conflict;
-                }
-            }));
+        lst = STM_PSEGMENT->modified_old_hashtables;
+        limit = list_count(lst);
+        for (j = 0; j < limit; j += 2) {
+            object_t *hobj = (object_t *)list_item(lst, j);
+            if (was_read_remote(remote_base, hobj)) {
+                conflicting_obj = (object_t *)list_item(lst, j + 1);
+                goto found_conflict;
+            }
+        }
 
         continue;
 
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -96,7 +96,8 @@
     uintptr_t modified_old_objects_markers_num_old;
 
     /* This list contains all old hashtables that have entries that we
-       modified.  Note that several transactions can all commit if
+       modified.  It's actually a list of pairs hashtable/sample_entry.
+       Note that several transactions can all commit if
        they have the same hashtable listed here.  The point of this
        list is only that if another segment does a global "read" of
        the hashtable (stm_hashtable_list), then it conflicts with this
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -475,26 +475,13 @@
     }
 }
 
+static void clean_up_segment_lists(void)
+{
 #pragma push_macro("STM_PSEGMENT")
 #pragma push_macro("STM_SEGMENT")
 #undef STM_PSEGMENT
 #undef STM_SEGMENT
 
-static void remove_objects_that_die(struct list_s *lst)
-{
-    if (lst != NULL) {
-        uintptr_t n = list_count(lst);
-        while (n > 0) {
-            object_t *obj = (object_t *)list_item(lst, --n);
-            if (!mark_visited_test(obj)) {
-                list_set_item(lst, n, list_pop_item(lst));
-            }
-        }
-    }
-}
-
-static void clean_up_segment_lists(void)
-{
     long i;
     for (i = 1; i <= NB_SEGMENTS; i++) {
         struct stm_priv_segment_info_s *pseg = get_priv_segment(i);
@@ -553,14 +540,39 @@
             }));
         list_clear(lst);
 
-        /* Remove from 'large_overflow_objects' and 'modified_old_hashtables'
-           all objects that die */
-        remove_objects_that_die(pseg->large_overflow_objects);
-        remove_objects_that_die(pseg->modified_old_hashtables);
+        /* Remove from 'large_overflow_objects' all objects that die */
+        lst = pseg->large_overflow_objects;
+        if (lst != NULL) {
+            uintptr_t n = list_count(lst);
+            while (n > 0) {
+                object_t *obj = (object_t *)list_item(lst, --n);
+                if (!mark_visited_test(obj))
+                    list_set_item(lst, n, list_pop_item(lst));
+            }
+        }
+
+        /* Remove from 'modified_old_hashtables' all old hashtables that
+           die, but keeping the order */
+        {
+            lst = pseg->modified_old_hashtables;
+            uintptr_t j, k = 0, limit = list_count(lst);
+            for (j = 0; j < limit; j += 2) {
+                object_t *hobj = (object_t *)list_item(lst, j);
+                if (mark_visited_test(hobj)) {
+                    /* hobj does not die */
+                    if (j != k) {
+                        list_set_item(lst, k, (uintptr_t)hobj);
+                        list_set_item(lst, k + 1, list_item(lst, j + 1));
+                    }
+                    k += 2;
+                }
+            }
+            lst->count = k;
+        }
     }
-}
 #pragma pop_macro("STM_SEGMENT")
 #pragma pop_macro("STM_PSEGMENT")
+}
 
 static inline bool largemalloc_keep_object_at(char *data)
 {
diff --git a/c7/stm/hashtable.c b/c7/stm/hashtable.c
--- a/c7/stm/hashtable.c
+++ b/c7/stm/hashtable.c
@@ -358,12 +358,13 @@
                avoid them --- at least the list should never be longer
                than 'modified_old_objects'. */
             i = list_count(STM_PSEGMENT->modified_old_hashtables);
-            if (i > 0 && list_item(STM_PSEGMENT->modified_old_hashtables, i - 1)
+            if (i > 0 && list_item(STM_PSEGMENT->modified_old_hashtables, i - 2)
                          == (uintptr_t)hobj) {
                 /* already added */
             }
             else {
-                LIST_APPEND(STM_PSEGMENT->modified_old_hashtables, hobj);
+                LIST_APPEND2(STM_PSEGMENT->modified_old_hashtables,
+                             hobj, entry);
             }
         }
     }
diff --git a/c7/stm/list.h b/c7/stm/list.h
--- a/c7/stm/list.h
+++ b/c7/stm/list.h
@@ -45,6 +45,9 @@
     return lst;
 }
 
+#define LIST_APPEND2(lst, e1, e2)   ((lst) = list_append2((lst),   \
+                                        (uintptr_t)(e1), (uintptr_t)(e2)))
+
 
 static inline void list_clear(struct list_s *lst)
 {


More information about the pypy-commit mailing list