[pypy-commit] stmgc c8-marker: Improve the markers for inevitable transactions

arigo noreply at buildbot.pypy.org
Tue Mar 10 15:56:18 CET 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: c8-marker
Changeset: r1710:a4e4d3ad014a
Date: 2015-03-10 15:56 +0100
http://bitbucket.org/pypy/stmgc/changeset/a4e4d3ad014a/

Log:	Improve the markers for inevitable transactions

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -464,7 +464,7 @@
 
 static void wait_for_other_inevitable(struct stm_commit_log_entry_s *old)
 {
-    timing_wait_other_inevitable();
+    timing_event(STM_SEGMENT->running_thread, STM_WAIT_OTHER_INEVITABLE);
 
     while (old->next == INEV_RUNNING && !safe_point_requested()) {
         spin_loop();
@@ -1171,7 +1171,7 @@
 
 /************************************************************/
 
-static void _finish_transaction(enum stm_event_e event, bool was_inev)
+static void _finish_transaction(enum stm_event_e event)
 {
     stm_thread_local_t *tl = STM_SEGMENT->running_thread;
 
@@ -1182,10 +1182,7 @@
     list_clear(STM_PSEGMENT->objects_pointing_to_nursery);
     list_clear(STM_PSEGMENT->old_objects_with_cards_set);
     list_clear(STM_PSEGMENT->large_overflow_objects);
-    if (was_inev)
-        timing_commit_inev_position();
-    else
-        timing_event(tl, event);
+    timing_event(tl, event);
 
     release_thread_segment(tl);
     /* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
@@ -1285,7 +1282,7 @@
 
     /* done */
     stm_thread_local_t *tl = STM_SEGMENT->running_thread;
-    _finish_transaction(STM_TRANSACTION_COMMIT, was_inev);
+    _finish_transaction(STM_TRANSACTION_COMMIT);
     /* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
 
     s_mutex_unlock();
@@ -1420,7 +1417,7 @@
                                                    : NURSERY_END;
     }
 
-    _finish_transaction(STM_TRANSACTION_ABORT, false);
+    _finish_transaction(STM_TRANSACTION_ABORT);
     /* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
 
     return tl;
@@ -1459,10 +1456,10 @@
     if (STM_PSEGMENT->transaction_state == TS_REGULAR) {
         dprintf(("become_inevitable: %s\n", msg));
         _stm_collectable_safe_point();
+        timing_become_inevitable();
 
         _validate_and_turn_inevitable();
         STM_PSEGMENT->transaction_state = TS_INEVITABLE;
-        timing_record_inev_position();
 
         stm_rewind_jmp_forget(STM_SEGMENT->running_thread);
         invoke_and_clear_user_callbacks(0);   /* for commit */
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -141,9 +141,6 @@
     pthread_t running_pthread;
 #endif
 
-    /* marker where this thread became inevitable */
-    stm_loc_marker_t marker_inev;
-
     /* light finalizers */
     struct list_s *young_objects_with_light_finalizers;
     struct list_s *old_objects_with_light_finalizers;
diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c
--- a/c8/stm/gcpage.c
+++ b/c8/stm/gcpage.c
@@ -408,9 +408,6 @@
             if (modified->type == TYPE_POSITION_MARKER)
                 mark_visit_possibly_new_object(modified->marker_object, pseg);
         }
-
-        if (pseg->transaction_state == TS_INEVITABLE)
-            mark_visit_possibly_new_object(pseg->marker_inev.object, pseg);
     }
 }
 
diff --git a/c8/stm/marker.c b/c8/stm/marker.c
--- a/c8/stm/marker.c
+++ b/c8/stm/marker.c
@@ -89,32 +89,12 @@
                        STM_CONTENTION_WRITE_READ, &marker);
 }
 
-static void _timing_record_inev_position(void)
+static void _timing_become_inevitable(void)
 {
     stm_loc_marker_t marker;
     marker_fetch(STM_SEGMENT->running_thread, &marker);
-    STM_PSEGMENT->marker_inev.odd_number = marker.odd_number;
-    STM_PSEGMENT->marker_inev.object = marker.object;
-}
-
-static void _timing_commit_inev_position(void)
-{
-    stm_loc_marker_t marker;
-    marker.odd_number = STM_PSEGMENT->marker_inev.odd_number;
-    marker.object = STM_PSEGMENT->marker_inev.object;
     stmcb_timing_event(STM_SEGMENT->running_thread,
-                       STM_TRANSACTION_COMMIT, &marker);
-}
-
-static void timing_wait_other_inevitable(void)
-{
-    if (stmcb_timing_event == NULL)
-        return;
-
-    stm_loc_marker_t marker;
-    marker_fetch(STM_SEGMENT->running_thread, &marker);
-    stmcb_timing_event(STM_SEGMENT->running_thread,
-                       STM_WAIT_OTHER_INEVITABLE, &marker);
+                       STM_BECOME_INEVITABLE, &marker);
 }
 
 
diff --git a/c8/stm/marker.h b/c8/stm/marker.h
--- a/c8/stm/marker.h
+++ b/c8/stm/marker.h
@@ -2,9 +2,7 @@
 static void _timing_record_write_position(void);
 static void timing_write_read_contention(struct stm_undo_s *start,
                                          struct stm_undo_s *contention);
-static void _timing_record_inev_position(void);
-static void _timing_commit_inev_position(void);
-static void timing_wait_other_inevitable(void);
+static void _timing_become_inevitable(void);
 
 
 #define timing_enabled()   (stmcb_timing_event != NULL)
@@ -15,8 +13,5 @@
 #define timing_record_write_position()                                  \
     (timing_enabled() ? _timing_record_write_position() : (void)0)
 
-#define timing_record_inev_position()                                   \
-    (timing_enabled() ? _timing_record_inev_position() : (void)0)
-
-#define timing_commit_inev_position()                                   \
-    (timing_enabled() ? _timing_commit_inev_position() : (void)0)
+#define timing_become_inevitable()                                      \
+    (timing_enabled() ? _timing_become_inevitable() : (void)0)
diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c
--- a/c8/stm/nursery.c
+++ b/c8/stm/nursery.c
@@ -425,13 +425,6 @@
         if (undo->type == TYPE_POSITION_MARKER)
             minor_trace_if_young(&undo->marker_object);
     }
-
-    if (STM_PSEGMENT->transaction_state == TS_INEVITABLE) {
-        object_t **pmarker_inev_obj = (object_t **)
-            REAL_ADDRESS(STM_SEGMENT->segment_base,
-                         &STM_PSEGMENT->marker_inev.object);
-        minor_trace_if_young(pmarker_inev_obj);
-    }
 }
 
 static void collect_objs_still_young_but_with_finalizers(void)
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -354,11 +354,12 @@
        saying where the write was done.  Followed by STM_TRANSACTION_ABORT. */
     STM_CONTENTION_WRITE_READ,
 
-    /* inevitable contention: the thread that waited is
-       STM_WAIT_OTHER_INEVITABLE (with a marker) and the thread that
-       it waited for is the next STM_TRANSACTION_COMMIT (with a marker
-       as well; both markers point to the place that made each
-       transaction inevitable). */
+    /* inevitable contention: all threads that try to become inevitable
+       have a STM_BECOME_INEVITABLE event with a position marker.  Then,
+       if it waits it gets a STM_WAIT_OTHER_INEVITABLE.  It is possible
+       that a thread gets STM_BECOME_INEVITABLE followed by
+       STM_TRANSACTION_ABORT if it fails to become inevitable. */
+    STM_BECOME_INEVITABLE,
 
     /* always one STM_WAIT_xxx followed later by STM_WAIT_DONE */
     STM_WAIT_FREE_SEGMENT,
diff --git a/c8/test/support.py b/c8/test/support.py
--- a/c8/test/support.py
+++ b/c8/test/support.py
@@ -135,6 +135,13 @@
        saying where the write was done.  Followed by STM_TRANSACTION_ABORT. */
     STM_CONTENTION_WRITE_READ,
 
+    /* inevitable contention: all threads that try to become inevitable
+       have a STM_BECOME_INEVITABLE event with a position marker.  Then,
+       if it waits it gets a STM_WAIT_OTHER_INEVITABLE.  It is possible
+       that a thread gets STM_BECOME_INEVITABLE followed by
+       STM_TRANSACTION_ABORT if it fails to become inevitable. */
+    STM_BECOME_INEVITABLE,
+
     /* always one STM_WAIT_xxx followed later by STM_WAIT_DONE */
     STM_WAIT_FREE_SEGMENT,
     STM_WAIT_SYNC_PAUSE,
diff --git a/c8/test/test_marker.py b/c8/test/test_marker.py
--- a/c8/test/test_marker.py
+++ b/c8/test/test_marker.py
@@ -19,16 +19,13 @@
         self.timing_event_keepalive = timing_event
         self.seen = seen
 
-    def check_recording(self, i1, o1, extra=None):
+    def check_recording(self, i1, o1, generating_thread_num=1):
         seen = self.seen
         tl, event, marker = seen[0]
-        assert tl == self.tls[1]
+        assert tl == self.tls[generating_thread_num]
         assert marker == (i1, o1)
-        if extra is None:
-            assert len(seen) == 1
-        else:
-            assert seen[1] == (self.tls[1], extra, None)
-            assert len(seen) == 2
+        assert len(seen) == 1
+        del self.seen[:]
 
     def test_marker_odd_simple(self):
         self.start_transaction()
@@ -119,25 +116,23 @@
         py.test.raises(Conflict, self.switch, 1)
         self.check_recording(19, ffi.NULL)
 
-    def test_commit_marker_for_inev(self):
-        self.recording(lib.STM_TRANSACTION_COMMIT)
+    def test_become_inevitable_marker(self):
+        self.recording(lib.STM_BECOME_INEVITABLE)
         #
         self.switch(1)
         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.commit_transaction()
         #
         self.check_recording(19, ffi.NULL)
 
     def test_abort_markers_cb_inevitable(self):
-        self.recording(lib.STM_WAIT_OTHER_INEVITABLE)
+        self.recording(lib.STM_BECOME_INEVITABLE)
         #
         self.start_transaction()
         self.become_inevitable()
+        self.check_recording(0, ffi.NULL, generating_thread_num=0)
         #
         self.switch(1)
         self.start_transaction()
@@ -147,9 +142,10 @@
         self.push_root(ffi.cast("object_t *", p))
         py.test.raises(Conflict, self.become_inevitable)
         #
-        py.test.skip("XXX only during tests does become_inevitable() abort"
-                     " and then it doesn't record anything")
-        self.check_recording(21, p)
+        # only during tests does become_inevitable() abort because
+        # another thread is already inevitable; but it should have
+        # recorded the marker first
+        self.check_recording(21, p, generating_thread_num=1)
 
     def test_read_write_contention(self):
         self.recording(lib.STM_CONTENTION_WRITE_READ)


More information about the pypy-commit mailing list