[pypy-commit] stmgc marker: in-progress: clean-up
arigo
noreply at buildbot.pypy.org
Mon Apr 28 17:53:24 CEST 2014
Author: Armin Rigo <arigo at tunes.org>
Branch: marker
Changeset: r1188:fe38fc7a7c18
Date: 2014-04-28 17:53 +0200
http://bitbucket.org/pypy/stmgc/changeset/fe38fc7a7c18/
Log: in-progress: clean-up
diff --git a/c7/stm/contention.c b/c7/stm/contention.c
--- a/c7/stm/contention.c
+++ b/c7/stm/contention.c
@@ -187,12 +187,7 @@
dprintf(("abort in contention\n"));
STM_SEGMENT->nursery_end = abort_category;
- if (kind == WRITE_WRITE_CONTENTION)
- 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);
+ marker_contention_abort_self(abort_category, other_segment_num, obj);
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
@@ -635,8 +635,9 @@
(int)pseg->transaction_state);
}
- /* look up and preserve the marker information as a string */
- marker_fetch_expand(pseg);
+ /* if we don't have marker information already, look up and preserve
+ the marker information from the shadowstack as a string */
+ marker_default_for_abort(pseg);
/* throw away the content of the nursery */
long bytes_in_nursery = throw_away_nursery(pseg);
diff --git a/c7/stm/marker.c b/c7/stm/marker.c
--- a/c7/stm/marker.c
+++ b/c7/stm/marker.c
@@ -13,25 +13,40 @@
static void marker_fetch(stm_thread_local_t *tl, uintptr_t marker[2])
{
+ /* fetch the current marker from the tl's shadow stack,
+ and return it in 'marker[2]'. */
struct stm_shadowentry_s *current = tl->shadowstack - 1;
struct stm_shadowentry_s *base = tl->shadowstack_base;
- /* stop walking just before shadowstack_base, which contains
- STM_STACK_MARKER_OLD which shouldn't be expanded */
- while (--current > base) {
- if (((uintptr_t)current->ss) & 1) {
- /* found the odd marker */
- marker[0] = (uintptr_t)current[0].ss;
- marker[1] = (uintptr_t)current[1].ss;
- return;
- }
+
+ /* The shadowstack_base contains STM_STACK_MARKER_OLD, which is
+ a convenient stopper for the loop below but which shouldn't
+ be returned. */
+ assert(base->ss == (object_t *)STM_STACK_MARKER_OLD);
+
+ while (!(((uintptr_t)current->ss) & 1)) {
+ current--;
+ assert(current >= base);
}
- marker[0] = 0;
- marker[1] = 0;
+ if (current != base) {
+ /* found the odd marker */
+ marker[0] = (uintptr_t)current[0].ss;
+ marker[1] = (uintptr_t)current[1].ss;
+ }
+ else {
+ /* no marker found */
+ marker[0] = 0;
+ marker[1] = 0;
+ }
}
static void marker_expand(uintptr_t marker[2], char *segment_base,
char *outmarker)
{
+ /* Expand the marker given by 'marker[2]' into a full string. This
+ works assuming that the marker was produced inside the segment
+ given by 'segment_base'. If that's from a different thread, you
+ must first acquire the corresponding 'marker_lock'. */
+ assert(_has_mutex());
outmarker[0] = 0;
if (marker[0] == 0)
return; /* no marker entry found */
@@ -41,7 +56,7 @@
}
}
-static void marker_fetch_expand(struct stm_priv_segment_info_s *pseg)
+static void marker_default_for_abort(struct stm_priv_segment_info_s *pseg)
{
if (pseg->marker_self[0] != 0)
return; /* already collected an entry */
@@ -58,8 +73,10 @@
static char _result[_STM_MARKER_LEN];
uintptr_t marker[2];
_result[0] = 0;
+ s_mutex_lock();
marker_fetch(STM_SEGMENT->running_thread, marker);
marker_expand(marker, STM_SEGMENT->segment_base, _result);
+ s_mutex_unlock();
return _result;
}
@@ -91,8 +108,6 @@
static void marker_fetch_obj_write(uint8_t in_segment_num, object_t *obj,
uintptr_t marker[2])
{
- char *segment_base = get_segment_base(in_segment_num);
- acquire_marker_lock(segment_base);
assert(_has_mutex());
/* here, we acquired the other thread's marker_lock, which means that:
@@ -112,50 +127,58 @@
assert(list_count(mlstm) == 2 * list_count(mlst));
marker[0] = list_item(mlstm, i * 2 + 0);
marker[1] = list_item(mlstm, i * 2 + 1);
- goto done;
+ return;
}
}
marker[0] = 0;
marker[1] = 0;
- done:
- release_marker_lock(segment_base);
}
-static void marker_lookup_other_thread_write_write(uint8_t other_segment_num,
- object_t *obj)
+static void marker_contention_abort_self(int category,
+ uint8_t other_segment_num,
+ object_t *obj)
{
- uintptr_t marker[2];
- marker_fetch_obj_write(other_segment_num, obj, marker);
+ uintptr_t self_marker[2];
+ uintptr_t other_marker[2];
+ struct stm_priv_segment_info_s *my_pseg, *other_pseg;
- struct stm_priv_segment_info_s *my_pseg, *other_pseg;
+ my_pseg = get_priv_segment(STM_SEGMENT->segment_num);
other_pseg = get_priv_segment(other_segment_num);
- my_pseg = get_priv_segment(STM_SEGMENT->segment_num);
- my_pseg->marker_other[0] = 0;
- marker_expand(marker, other_pseg->pub.segment_base, my_pseg->marker_other);
-}
-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);
-}
+ char *my_segment_base = STM_SEGMENT->segment_base;
+ char *other_segment_base = get_segment_base(other_segment_num);
-static void marker_lookup_same_thread_write_read(object_t *obj)
-{
- uintptr_t marker[2];
- marker_fetch_obj_write(STM_SEGMENT->segment_num, obj, marker);
+ /* I'm aborting. Collect the location for myself. It's usually
+ the current location, except in a write-read abort, in which
+ case it's the older location of the write. */
+ if (category == STM_TIME_RUN_ABORTED_WRITE_READ)
+ marker_fetch_obj_write(my_pseg->pub.segment_num, obj, self_marker);
+ else
+ marker_fetch(my_pseg->pub.running_thread, self_marker);
- struct stm_priv_segment_info_s *my_pseg;
- my_pseg = get_priv_segment(STM_SEGMENT->segment_num);
- my_pseg->marker_self[0] = 0;
- my_pseg->marker_other[0] = 0;
- marker_expand(marker, STM_SEGMENT->segment_base, my_pseg->marker_self);
+ marker_expand(self_marker, my_segment_base, my_pseg->marker_self);
+
+ /* For some categories, we can also collect the relevant information
+ for the other segment. */
+ acquire_marker_lock(other_segment_base);
+
+ switch (category) {
+ case STM_TIME_RUN_ABORTED_WRITE_WRITE:
+ marker_fetch_obj_write(other_segment_num, obj, other_marker);
+ break;
+ case STM_TIME_RUN_ABORTED_INEVITABLE:
+ other_marker[0] = other_pseg->marker_inev[0];
+ other_marker[1] = other_pseg->marker_inev[1];
+ break;
+ default:
+ other_marker[0] = 0;
+ other_marker[1] = 0;
+ break;
+ }
+
+ marker_expand(other_marker, other_segment_base, my_pseg->marker_other);
+
+ release_marker_lock(other_segment_base);
}
static void marker_fetch_inev(void)
diff --git a/c7/stm/marker.h b/c7/stm/marker.h
--- a/c7/stm/marker.h
+++ b/c7/stm/marker.h
@@ -1,15 +1,13 @@
static void marker_fetch(stm_thread_local_t *tl, uintptr_t marker[2]);
+static void marker_fetch_inev(void);
static void marker_expand(uintptr_t marker[2], char *segment_base,
char *outmarker);
-static void marker_fetch_expand(struct stm_priv_segment_info_s *pseg);
+static void marker_default_for_abort(struct stm_priv_segment_info_s *pseg);
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 marker_fetch_obj_write(uint8_t in_segment_num, object_t *obj,
- uintptr_t marker[2]);
-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);
+
+static void marker_contention_abort_self(int category,
+ uint8_t other_segment_num,
+ object_t *obj);
More information about the pypy-commit
mailing list