[pypy-commit] stmgc marker: Report correctly write-read contention.

arigo noreply at buildbot.pypy.org
Sat Apr 26 19:18:13 CEST 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: marker
Changeset: r1184:5cc5bccf74cd
Date: 2014-04-26 19:18 +0200
http://bitbucket.org/pypy/stmgc/changeset/5cc5bccf74cd/

Log:	Report correctly write-read contention.

diff --git a/c7/stm/contention.c b/c7/stm/contention.c
--- a/c7/stm/contention.c
+++ b/c7/stm/contention.c
@@ -187,6 +187,8 @@
             marker_lookup_other_thread_write_write(other_segment_num, obj);
         else if (kind == INEVITABLE_CONTENTION)
             marker_lookup_other_thread_inev(other_segment_num);
+        else if (kind == WRITE_READ_CONTENTION)
+            marker_lookup_same_thread_write_read(obj);
         abort_with_mutex();
     }
 
@@ -285,9 +287,10 @@
     s_mutex_unlock();
 }
 
-static void write_read_contention_management(uint8_t other_segment_num)
+static void write_read_contention_management(uint8_t other_segment_num,
+                                             object_t *obj)
 {
-    contention_management(other_segment_num, WRITE_READ_CONTENTION, NULL);
+    contention_management(other_segment_num, WRITE_READ_CONTENTION, obj);
 }
 
 static void inevitable_contention_management(uint8_t other_segment_num)
diff --git a/c7/stm/contention.h b/c7/stm/contention.h
--- a/c7/stm/contention.h
+++ b/c7/stm/contention.h
@@ -1,7 +1,8 @@
 
 static void write_write_contention_management(uintptr_t lock_idx,
                                               object_t *obj);
-static void write_read_contention_management(uint8_t other_segment_num);
+static void write_read_contention_management(uint8_t other_segment_num,
+                                             object_t *obj);
 static void inevitable_contention_management(uint8_t other_segment_num);
 
 static inline bool is_abort(uintptr_t nursery_end) {
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -288,7 +288,7 @@
             ({
                 if (was_read_remote(remote_base, item, remote_version)) {
                     /* A write-read conflict! */
-                    write_read_contention_management(i);
+                    write_read_contention_management(i, item);
 
                     /* If we reach this point, we didn't abort, but maybe we
                        had to wait for the other thread to commit.  If we
diff --git a/c7/stm/marker.c b/c7/stm/marker.c
--- a/c7/stm/marker.c
+++ b/c7/stm/marker.c
@@ -82,6 +82,28 @@
         memcpy(tl->longest_marker_other, pseg->marker_other, _STM_MARKER_LEN);
     }
     pseg->marker_self[0] = 0;
+    pseg->marker_other[0] = 0;
+}
+
+static void marker_lookup_from_thread(struct stm_priv_segment_info_s *pseg,
+                                      object_t *obj, char *outmarker)
+{
+    outmarker[0] = 0;
+
+    long i;
+    struct list_s *mlst = pseg->modified_old_objects;
+    struct list_s *mlstm = pseg->modified_old_objects_markers;
+    for (i = list_count(mlst); --i >= 0; ) {
+        if (list_item(mlst, i) == (uintptr_t)obj) {
+            uintptr_t marker[2];
+            assert(list_count(mlstm) == 2 * list_count(mlst));
+            marker[0] = list_item(mlstm, i * 2 + 0);
+            marker[1] = list_item(mlstm, i * 2 + 1);
+
+            marker_expand(marker, pseg->pub.segment_base, outmarker);
+            break;
+        }
+    }
 }
 
 static void marker_lookup_other_thread_write_write(uint8_t other_segment_num,
@@ -91,7 +113,6 @@
     char *other_segment_base = get_segment_base(other_segment_num);
     acquire_segment_lock(other_segment_base);
     assert(_has_mutex());
-    STM_PSEGMENT->marker_other[0] = 0;
 
     /* here, we acquired the other thread's segment_lock, which means that:
 
@@ -101,24 +122,10 @@
        (2) it is not mutating 'modified_old_objects' right now (we have
            the global mutex_lock at this point too).
     */
+    my_pseg = get_priv_segment(STM_SEGMENT->segment_num);
+    other_pseg = get_priv_segment(other_segment_num);
 
-    other_pseg = get_priv_segment(other_segment_num);
-    long i;
-    struct list_s *mlst = other_pseg->modified_old_objects;
-    struct list_s *mlstm = other_pseg->modified_old_objects_markers;
-    for (i = list_count(mlst); --i >= 0; ) {
-        if (list_item(mlst, i) == (uintptr_t)obj) {
-            uintptr_t marker[2];
-            assert(list_count(mlstm) == 2 * list_count(mlst));
-            marker[0] = list_item(mlstm, i * 2 + 0);
-            marker[1] = list_item(mlstm, i * 2 + 1);
-
-            my_pseg = get_priv_segment(STM_SEGMENT->segment_num);
-            marker_expand(marker, other_pseg->pub.segment_base,
-                          my_pseg->marker_other);
-            break;
-        }
-    }
+    marker_lookup_from_thread(other_pseg, obj, my_pseg->marker_other);
 
     release_segment_lock(other_segment_base);
 }
@@ -135,6 +142,14 @@
                   my_pseg->marker_other);
 }
 
+static void marker_lookup_same_thread_write_read(object_t *obj)
+{
+    struct stm_priv_segment_info_s *my_pseg;
+
+    my_pseg = get_priv_segment(STM_SEGMENT->segment_num);
+    marker_lookup_from_thread(my_pseg, obj, my_pseg->marker_self);
+}
+
 static void marker_fetch_inev(void)
 {
     uintptr_t marker[2];
diff --git a/c7/stm/marker.h b/c7/stm/marker.h
--- a/c7/stm/marker.h
+++ b/c7/stm/marker.h
@@ -9,4 +9,5 @@
 static void marker_lookup_other_thread_write_write(uint8_t other_segment_num,
                                                    object_t *obj);
 static void marker_lookup_other_thread_inev(uint8_t other_segment_num);
+static void marker_lookup_same_thread_write_read(object_t *obj);
 static void marker_fetch_inev(void);
diff --git a/c7/test/test_marker.py b/c7/test/test_marker.py
--- a/c7/test/test_marker.py
+++ b/c7/test/test_marker.py
@@ -80,7 +80,7 @@
         assert tl.longest_marker_state == lib.STM_TIME_RUN_ABORTED_OTHER
         assert 0.099 <= tl.longest_marker_time <= 0.9
         assert ffi.string(tl.longest_marker_self) == '29 %r' % (p,)
-        assert tl.longest_marker_other[0] == '\x00'
+        assert ffi.string(tl.longest_marker_other) == ''
 
     def test_macros(self):
         self.start_transaction()
@@ -231,3 +231,31 @@
         assert tl.longest_marker_state == lib.STM_TIME_RUN_ABORTED_INEVITABLE
         assert ffi.string(tl.longest_marker_self) == '21'
         assert ffi.string(tl.longest_marker_other) == '19'
+
+    def test_read_write_contention(self):
+        @ffi.callback("void(char *, uintptr_t, object_t *, char *, size_t)")
+        def expand_marker(base, number, ptr, outbuf, outbufsize):
+            s = '%d\x00' % (number,)
+            assert len(s) <= outbufsize
+            outbuf[0:len(s)] = s
+        lib.stmcb_expand_marker = expand_marker
+        p = stm_allocate_old(16)
+        #
+        self.start_transaction()
+        assert stm_get_char(p) == '\x00'
+        #
+        self.switch(1)
+        self.start_transaction()
+        self.push_root(ffi.cast("object_t *", 19))
+        self.push_root(ffi.cast("object_t *", ffi.NULL))
+        stm_set_char(p, 'A')
+        self.pop_root()
+        self.pop_root()
+        self.push_root(ffi.cast("object_t *", 17))
+        self.push_root(ffi.cast("object_t *", ffi.NULL))
+        py.test.raises(Conflict, self.commit_transaction)
+        #
+        tl = self.get_stm_thread_local()
+        assert tl.longest_marker_state == lib.STM_TIME_RUN_ABORTED_WRITE_READ
+        assert ffi.string(tl.longest_marker_self) == '19'
+        assert ffi.string(tl.longest_marker_other) == ''


More information about the pypy-commit mailing list