[pypy-commit] stmgc marker: Self/other marker in case of inevitable/inevitable conflict

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


Author: Armin Rigo <arigo at tunes.org>
Branch: marker
Changeset: r1183:2a4a393ac14c
Date: 2014-04-26 18:58 +0200
http://bitbucket.org/pypy/stmgc/changeset/2a4a393ac14c/

Log:	Self/other marker in case of inevitable/inevitable conflict

diff --git a/c7/stm/contention.c b/c7/stm/contention.c
--- a/c7/stm/contention.c
+++ b/c7/stm/contention.c
@@ -184,7 +184,9 @@
         dprintf(("abort in contention\n"));
         STM_SEGMENT->nursery_end = abort_category;
         if (kind == WRITE_WRITE_CONTENTION)
-            lookup_other_thread_recorded_marker(other_segment_num, obj);
+            marker_lookup_other_thread_write_write(other_segment_num, obj);
+        else if (kind == INEVITABLE_CONTENTION)
+            marker_lookup_other_thread_inev(other_segment_num);
         abort_with_mutex();
     }
 
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -211,6 +211,11 @@
     change_timing_state(STM_TIME_RUN_CURRENT);
     STM_PSEGMENT->start_time = tl->_timing_cur_start;
     STM_PSEGMENT->safe_point = SP_RUNNING;
+#ifndef NDEBUG
+    STM_PSEGMENT->marker_inev[1] = 99999999999999999L;
+#endif
+    if (jmpbuf == NULL)
+        marker_fetch_inev();
     STM_PSEGMENT->transaction_state = (jmpbuf != NULL ? TS_REGULAR
                                                       : TS_INEVITABLE);
     STM_SEGMENT->jmpbuf_ptr = jmpbuf;
@@ -727,6 +732,7 @@
     if (STM_PSEGMENT->transaction_state == TS_REGULAR) {
         dprintf(("become_inevitable: %s\n", msg));
 
+        marker_fetch_inev();
         wait_for_end_of_inevitable_transaction(NULL);
         STM_PSEGMENT->transaction_state = TS_INEVITABLE;
         STM_SEGMENT->jmpbuf_ptr = NULL;
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -174,6 +174,7 @@
     /* Temporarily stores the marker information */
     char marker_self[_STM_MARKER_LEN];
     char marker_other[_STM_MARKER_LEN];
+    uintptr_t marker_inev[2];
 };
 
 enum /* safe_point */ {
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -428,6 +428,10 @@
         for (i = list_count(lst); i > 0; i -= 2) {
             mark_visit_object((object_t *)list_item(lst, i - 1), base);
         }
+        if (get_priv_segment(j)->transaction_state == TS_INEVITABLE) {
+            uintptr_t marker_inev_obj = get_priv_segment(j)->marker_inev[1];
+            mark_visit_object((object_t *)marker_inev_obj, base);
+        }
     }
 }
 
diff --git a/c7/stm/marker.c b/c7/stm/marker.c
--- a/c7/stm/marker.c
+++ b/c7/stm/marker.c
@@ -84,8 +84,8 @@
     pseg->marker_self[0] = 0;
 }
 
-static void lookup_other_thread_recorded_marker(uint8_t other_segment_num,
-                                                object_t *obj)
+static void marker_lookup_other_thread_write_write(uint8_t other_segment_num,
+                                                   object_t *obj)
 {
     struct stm_priv_segment_info_s *my_pseg, *other_pseg;
     char *other_segment_base = get_segment_base(other_segment_num);
@@ -122,3 +122,23 @@
 
     release_segment_lock(other_segment_base);
 }
+
+static void marker_lookup_other_thread_inev(uint8_t other_segment_num)
+{
+    /* same as marker_lookup_other_thread_write_write(), but for
+       an inevitable contention instead of a write-write contention */
+    struct stm_priv_segment_info_s *my_pseg, *other_pseg;
+    assert(_has_mutex());
+    other_pseg = get_priv_segment(other_segment_num);
+    my_pseg = get_priv_segment(STM_SEGMENT->segment_num);
+    marker_expand(other_pseg->marker_inev, other_pseg->pub.segment_base,
+                  my_pseg->marker_other);
+}
+
+static void marker_fetch_inev(void)
+{
+    uintptr_t marker[2];
+    marker_fetch(STM_SEGMENT->running_thread, marker);
+    STM_PSEGMENT->marker_inev[0] = marker[0];
+    STM_PSEGMENT->marker_inev[1] = marker[1];
+}
diff --git a/c7/stm/marker.h b/c7/stm/marker.h
--- a/c7/stm/marker.h
+++ b/c7/stm/marker.h
@@ -6,5 +6,7 @@
 static void marker_copy(stm_thread_local_t *tl,
                         struct stm_priv_segment_info_s *pseg,
                         enum stm_time_e attribute_to, double time);
-static void lookup_other_thread_recorded_marker(uint8_t other_segment_num,
-                                                object_t *obj);
+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_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
@@ -203,3 +203,31 @@
         assert tl.longest_marker_state == lib.STM_TIME_RUN_ABORTED_WRITE_WRITE
         assert ffi.string(tl.longest_marker_self) == '21'
         assert ffi.string(tl.longest_marker_other) == '19'
+
+    def test_double_abort_markers_cb_inevitable(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
+        #
+        self.start_transaction()
+        self.push_root(ffi.cast("object_t *", 19))
+        self.push_root(ffi.cast("object_t *", ffi.NULL))
+        self.become_inevitable()
+        self.pop_root()
+        self.pop_root()
+        self.push_root(ffi.cast("object_t *", 17))
+        self.push_root(ffi.cast("object_t *", ffi.NULL))
+        #
+        self.switch(1)
+        self.start_transaction()
+        self.push_root(ffi.cast("object_t *", 21))
+        self.push_root(ffi.cast("object_t *", ffi.NULL))
+        py.test.raises(Conflict, self.become_inevitable)
+        #
+        tl = self.get_stm_thread_local()
+        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'


More information about the pypy-commit mailing list