[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