[pypy-commit] stmgc c8-marker: Generate the markers in case of inevitable transactions
arigo
noreply at buildbot.pypy.org
Mon Mar 9 10:04:51 CET 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: c8-marker
Changeset: r1702:5a56584dbe4b
Date: 2015-03-09 10:05 +0100
http://bitbucket.org/pypy/stmgc/changeset/5a56584dbe4b/
Log: Generate the markers in case of inevitable transactions
diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -5,6 +5,7 @@
/* *** MISC *** */
static void free_bk(struct stm_undo_s *undo)
{
+ assert(undo->type != TYPE_POSITION_MARKER);
free(undo->backup);
assert(undo->backup = (char*)-88);
increment_total_allocated(-SLICE_SIZE(undo->slice));
@@ -455,6 +456,17 @@
}
+static void wait_for_other_inevitable(struct stm_commit_log_entry_s *old)
+{
+ timing_wait_other_inevitable();
+
+ while (old->next == INEV_RUNNING && !safe_point_requested()) {
+ spin_loop();
+ usleep(10); /* XXXXXX */
+ }
+ timing_event(STM_SEGMENT->running_thread, STM_WAIT_DONE);
+}
+
static void reset_wb_executed_flags(void);
static void readd_wb_executed_flags(void);
static void check_all_write_barrier_flags(char *segbase, struct list_s *list);
@@ -506,13 +518,6 @@
if (__sync_bool_compare_and_swap(&old->next, NULL, new))
break; /* success! */
- } else if (old->next == INEV_RUNNING) {
- /* we failed because there is an INEV transaction running */
- /* XXXXXX for now just sleep (XXX with the lock acquired?
- isn't it a bad idea?). We should really ask to inev
- transaction to do the commit for us, and then we can
- continue running. */
- usleep(10);
}
if (is_commit) {
@@ -523,6 +528,16 @@
readd_wb_executed_flags();
}
+ if (old->next == INEV_RUNNING && !safe_point_requested()) {
+ /* we failed because there is an INEV transaction running */
+ /* XXXXXX for now just sleep. We should really ask to inev
+ transaction to do the commit for us, and then we can
+ continue running. */
+ dprintf(("_validate_and_attach(%p) failed, "
+ "waiting for inevitable\n", new));
+ wait_for_other_inevitable(old);
+ }
+
dprintf(("_validate_and_attach(%p) failed, enter safepoint\n", new));
/* check for requested safe point. otherwise an INEV transaction
@@ -1150,7 +1165,7 @@
/************************************************************/
-static void _finish_transaction(enum stm_event_e event)
+static void _finish_transaction(enum stm_event_e event, bool was_inev)
{
stm_thread_local_t *tl = STM_SEGMENT->running_thread;
@@ -1161,7 +1176,10 @@
list_clear(STM_PSEGMENT->objects_pointing_to_nursery);
list_clear(STM_PSEGMENT->old_objects_with_cards_set);
list_clear(STM_PSEGMENT->large_overflow_objects);
- timing_event(tl, event);
+ if (was_inev)
+ timing_commit_inev_position();
+ else
+ timing_event(tl, event);
release_thread_segment(tl);
/* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
@@ -1223,6 +1241,7 @@
push_large_overflow_objects_to_other_segments();
/* push before validate. otherwise they are reachable too early */
+
bool was_inev = STM_PSEGMENT->transaction_state == TS_INEVITABLE;
_validate_and_add_to_commit_log();
@@ -1264,7 +1283,7 @@
/* done */
stm_thread_local_t *tl = STM_SEGMENT->running_thread;
- _finish_transaction(STM_TRANSACTION_COMMIT);
+ _finish_transaction(STM_TRANSACTION_COMMIT, was_inev);
/* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
s_mutex_unlock();
@@ -1399,7 +1418,7 @@
: NURSERY_END;
}
- _finish_transaction(STM_TRANSACTION_ABORT);
+ _finish_transaction(STM_TRANSACTION_ABORT, false);
/* cannot access STM_SEGMENT or STM_PSEGMENT from here ! */
return tl;
@@ -1441,6 +1460,8 @@
_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,6 +141,9 @@
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
@@ -401,6 +401,9 @@
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
@@ -26,6 +26,8 @@
}
else {
/* no marker found */
+ out_marker->odd_number = 0;
+ out_marker->object = NULL;
return false;
}
}
@@ -87,6 +89,34 @@
STM_CONTENTION_WRITE_READ, &marker);
}
+static void _timing_record_inev_position(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);
+}
+
void (*stmcb_timing_event)(stm_thread_local_t *tl, /* the local thread */
enum stm_event_e event,
diff --git a/c8/stm/marker.h b/c8/stm/marker.h
--- a/c8/stm/marker.h
+++ b/c8/stm/marker.h
@@ -2,10 +2,21 @@
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);
+#define timing_enabled() (stmcb_timing_event != NULL)
+
#define timing_event(tl, event) \
- (stmcb_timing_event != NULL ? stmcb_timing_event(tl, event, NULL) : (void)0)
+ (timing_enabled() ? stmcb_timing_event(tl, event, NULL) : (void)0)
#define timing_record_write_position() \
- (stmcb_timing_event != NULL ? _timing_record_write_position() : (void)0)
+ (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)
diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c
--- a/c8/stm/nursery.c
+++ b/c8/stm/nursery.c
@@ -425,6 +425,13 @@
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/stm/sync.h b/c8/stm/sync.h
--- a/c8/stm/sync.h
+++ b/c8/stm/sync.h
@@ -33,3 +33,5 @@
static bool pause_signalled, globally_unique_transaction;
static void enter_safe_point_if_requested(void);
+
+#define safe_point_requested() (STM_SEGMENT->nursery_end != NURSERY_END)
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -354,6 +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). */
+
/* always one STM_WAIT_xxx followed later by STM_WAIT_DONE */
STM_WAIT_FREE_SEGMENT,
STM_WAIT_OTHER_INEVITABLE,
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
@@ -119,20 +119,25 @@
py.test.raises(Conflict, self.switch, 1)
self.check_recording(19, ffi.NULL)
- def test_double_abort_markers_cb_inevitable(self):
- self.recording(lib.STM_CONTENTION_INEVITABLE)
+ def test_commit_marker_for_inev(self):
+ self.recording(lib.STM_TRANSACTION_COMMIT)
+ #
+ 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.start_transaction()
- p = stm_allocate(16)
- stm_set_char(p, 'A')
- self.push_root(ffi.cast("object_t *", 19))
- self.push_root(ffi.cast("object_t *", p))
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))
- stm_minor_collect()
#
self.switch(1)
self.start_transaction()
@@ -142,7 +147,9 @@
self.push_root(ffi.cast("object_t *", p))
py.test.raises(Conflict, self.become_inevitable)
#
- self.check_recording(21, p, 19, p)
+ py.test.skip("XXX only during tests does become_inevitable() abort"
+ " and then it doesn't record anything")
+ self.check_recording(21, p)
def test_read_write_contention(self):
self.recording(lib.STM_CONTENTION_WRITE_READ)
@@ -167,63 +174,6 @@
py.test.raises(Conflict, self.switch, 1)
self.check_recording(19, ffi.NULL)
- def test_double_remote_markers_cb_write_write(self):
- self.recording(lib.STM_CONTENTION_WRITE_WRITE,
- lib.STM_ABORTING_OTHER_CONTENTION)
- p = stm_allocate_old(16)
- #
- 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))
- tl0 = self.get_stm_thread_local()
- #
- self.switch(1)
- self.start_transaction()
- self.become_inevitable()
- self.push_root(ffi.cast("object_t *", 21))
- self.push_root(ffi.cast("object_t *", ffi.NULL))
- stm_set_char(p, 'B') # aborts in #0
- self.pop_root()
- self.pop_root()
- self.push_root(ffi.cast("object_t *", 23))
- self.push_root(ffi.cast("object_t *", ffi.NULL))
- #
- py.test.raises(Conflict, self.switch, 0)
- #
- self.check_recording(21, ffi.NULL, 19, ffi.NULL,
- extra=lib.STM_ABORTING_OTHER_CONTENTION)
-
- def test_double_remote_markers_cb_write_read(self):
- self.recording(lib.STM_CONTENTION_WRITE_READ,
- lib.STM_ABORTING_OTHER_CONTENTION)
- p = stm_allocate_old(16)
- #
- self.start_transaction()
- assert stm_get_char(p) == '\x00' # read
- tl0 = self.get_stm_thread_local()
- #
- self.switch(1)
- self.start_transaction()
- self.become_inevitable()
- self.push_root(ffi.cast("object_t *", 21))
- self.push_root(ffi.cast("object_t *", ffi.NULL))
- stm_set_char(p, 'B') # write, will abort #0
- self.pop_root()
- self.pop_root()
- self.push_root(ffi.cast("object_t *", 23))
- self.push_root(ffi.cast("object_t *", ffi.NULL))
- self.commit_transaction()
- #
- py.test.raises(Conflict, self.switch, 0)
- #
- self.check_recording(21, ffi.NULL, 0, ffi.NULL,
- extra=lib.STM_ABORTING_OTHER_CONTENTION)
-
def test_all(self):
self.recording() # all events
self.start_transaction()
More information about the pypy-commit
mailing list