Author: Armin Rigo <ar...@tunes.org> Branch: marker Changeset: r1161:e24c66f0b2b4 Date: 2014-04-18 11:11 +0200 http://bitbucket.org/pypy/stmgc/changeset/e24c66f0b2b4/
Log: Get started diff --git a/c7/stm/core.c b/c7/stm/core.c --- a/c7/stm/core.c +++ b/c7/stm/core.c @@ -630,6 +630,7 @@ value before the transaction start */ stm_thread_local_t *tl = pseg->pub.running_thread; assert(tl->shadowstack >= pseg->shadowstack_at_start_of_transaction); + pseg->shadowstack_at_abort = tl->shadowstack; tl->shadowstack = pseg->shadowstack_at_start_of_transaction; tl->thread_local_obj = pseg->threadlocal_at_start_of_transaction; tl->last_abort__bytes_in_nursery = bytes_in_nursery; diff --git a/c7/stm/core.h b/c7/stm/core.h --- a/c7/stm/core.h +++ b/c7/stm/core.h @@ -152,6 +152,7 @@ 'thread_local_obj' field. */ struct stm_shadowentry_s *shadowstack_at_start_of_transaction; object_t *threadlocal_at_start_of_transaction; + struct stm_shadowentry_s *shadowstack_at_abort; /* For debugging */ #ifndef NDEBUG diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c --- a/c7/stm/gcpage.c +++ b/c7/stm/gcpage.c @@ -379,7 +379,7 @@ struct stm_shadowentry_s *current = tl->shadowstack; struct stm_shadowentry_s *base = tl->shadowstack_base; while (current-- != base) { - if (((uintptr_t)current->ss) > STM_STACK_MARKER_OLD) + if ((((uintptr_t)current->ss) & 3) == 0) mark_visit_object(current->ss, segment_base); } mark_visit_object(tl->thread_local_obj, segment_base); diff --git a/c7/stm/marker.c b/c7/stm/marker.c new file mode 100644 --- /dev/null +++ b/c7/stm/marker.c @@ -0,0 +1,32 @@ +#ifndef _STM_CORE_H_ +# error "must be compiled via stmgc.c" +#endif + + +void (*stmcb_expand_marker)(uintptr_t odd_number, + object_t *following_object, + char *outputbuf, size_t outputbufsize); + + +void marker_fetch(stm_thread_local_t *tl, + enum stm_time_e attribute_to, double time) +{ + tl->longest_marker_state = attribute_to; + tl->longest_marker_time = time; + + if (stmcb_expand_marker != NULL) { + struct stm_shadowentry_s *current = tl->shadowstack - 1; + struct stm_shadowentry_s *base = tl->shadowstack_base; + while (--current >= base) { + uintptr_t x = (uintptr_t)current->ss; + if (x & 1) { + /* the stack entry is an odd number */ + tl->longest_marker_self[0] = 0; + stmcb_expand_marker(x, current[1].ss, + tl->longest_marker_self, + sizeof(tl->longest_marker_self)); + break; + } + } + } +} diff --git a/c7/stm/marker.h b/c7/stm/marker.h new file mode 100644 --- /dev/null +++ b/c7/stm/marker.h @@ -0,0 +1,3 @@ + +void marker_fetch(stm_thread_local_t *tl, + enum stm_time_e attribute_to, double time); diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c --- a/c7/stm/nursery.c +++ b/c7/stm/nursery.c @@ -160,28 +160,26 @@ --current; OPT_ASSERT(current >= base); - switch ((uintptr_t)current->ss) { + uintptr_t x = (uintptr_t)current->ss; - case 0: /* NULL */ - continue; - - case STM_STACK_MARKER_NEW: + if ((x & 3) == 0) { + /* the stack entry is a regular pointer (possibly NULL) */ + minor_trace_if_young(¤t->ss); + } + else if (x == STM_STACK_MARKER_NEW) { /* the marker was not already seen: mark it as seen, but continue looking more deeply in the shadowstack */ current->ss = (object_t *)STM_STACK_MARKER_OLD; - continue; - - case STM_STACK_MARKER_OLD: + } + else if (x == STM_STACK_MARKER_OLD) { /* the marker was already seen: we can stop the root stack tracing at this point */ - goto interrupt; - - default: - /* the stack entry is a regular pointer */ - minor_trace_if_young(¤t->ss); + break; + } + else { + /* it is an odd-valued marker, ignore */ } } - interrupt: minor_trace_if_young(&tl->thread_local_obj); } diff --git a/c7/stm/timing.c b/c7/stm/timing.c --- a/c7/stm/timing.c +++ b/c7/stm/timing.c @@ -35,8 +35,18 @@ { stm_thread_local_t *tl = STM_SEGMENT->running_thread; TIMING_CHANGE(tl, STM_TIME_OUTSIDE_TRANSACTION); - add_timing(tl, attribute_to, tl->timing[STM_TIME_RUN_CURRENT]); + double time_this_transaction = tl->timing[STM_TIME_RUN_CURRENT]; + add_timing(tl, attribute_to, time_this_transaction); tl->timing[STM_TIME_RUN_CURRENT] = 0.0f; + + if (attribute_to != STM_TIME_RUN_COMMITTED && + time_this_transaction > tl->longest_marker_time) { + assert(tl->shadowstack == + STM_PSEGMENT->shadowstack_at_start_of_transaction); + tl->shadowstack = STM_PSEGMENT->shadowstack_at_abort; + marker_fetch(tl, attribute_to, time_this_transaction); + tl->shadowstack = STM_PSEGMENT->shadowstack_at_start_of_transaction; + } } static const char *timer_names[] = { diff --git a/c7/stmgc.c b/c7/stmgc.c --- a/c7/stmgc.c +++ b/c7/stmgc.c @@ -14,6 +14,7 @@ #include "stm/fprintcolor.h" #include "stm/weakref.h" #include "stm/timing.h" +#include "stm/marker.h" #include "stm/misc.c" #include "stm/list.c" @@ -33,3 +34,4 @@ #include "stm/fprintcolor.c" #include "stm/weakref.c" #include "stm/timing.c" +#include "stm/marker.c" diff --git a/c7/stmgc.h b/c7/stmgc.h --- a/c7/stmgc.h +++ b/c7/stmgc.h @@ -90,6 +90,11 @@ float timing[_STM_TIME_N]; double _timing_cur_start; enum stm_time_e _timing_cur_state; + /* the marker with the longest associated time so far */ + enum stm_time_e longest_marker_state; + double longest_marker_time; + char longest_marker_self[80]; + char longest_marker_other[80]; /* the next fields are handled internally by the library */ int associated_segment_num; struct stm_thread_local_s *prev, *next; @@ -264,8 +269,8 @@ #define STM_PUSH_ROOT(tl, p) ((tl).shadowstack++->ss = (object_t *)(p)) #define STM_POP_ROOT(tl, p) ((p) = (typeof(p))((--(tl).shadowstack)->ss)) #define STM_POP_ROOT_RET(tl) ((--(tl).shadowstack)->ss) -#define STM_STACK_MARKER_NEW 1 -#define STM_STACK_MARKER_OLD 2 +#define STM_STACK_MARKER_NEW 2 +#define STM_STACK_MARKER_OLD 6 /* Every thread needs to have a corresponding stm_thread_local_t @@ -368,6 +373,14 @@ void stm_flush_timing(stm_thread_local_t *tl, int verbose); +/* The markers pushed in the shadowstack are an odd number followed by a + regular pointer. When needed, this library invokes this callback to + turn this pair into a human-readable explanation. */ +extern void (*stmcb_expand_marker)(uintptr_t odd_number, + object_t *following_object, + char *outputbuf, size_t outputbufsize); + + /* ==================== END ==================== */ #endif diff --git a/c7/test/support.py b/c7/test/support.py --- a/c7/test/support.py +++ b/c7/test/support.py @@ -28,6 +28,10 @@ int associated_segment_num; uint32_t events[]; float timing[]; + int longest_marker_state; + double longest_marker_time; + char longest_marker_self[]; + char longest_marker_other[]; ...; } stm_thread_local_t; @@ -118,6 +122,9 @@ #define STM_TIME_SYNC_PAUSE ... void stm_flush_timing(stm_thread_local_t *, int); + +void (*stmcb_expand_marker)(uintptr_t odd_number, object_t *following_object, + char *outputbuf, size_t outputbufsize); """) @@ -435,6 +442,7 @@ self.current_thread = 0 def teardown_method(self, meth): + lib.stmcb_expand_marker = ffi.NULL tl = self.tls[self.current_thread] if lib._stm_in_transaction(tl) and lib.stm_is_inevitable(): self.commit_transaction() # must succeed! diff --git a/c7/test/test_marker.py b/c7/test/test_marker.py new file mode 100644 --- /dev/null +++ b/c7/test/test_marker.py @@ -0,0 +1,82 @@ +from support import * +import py, time + +class TestMarker(BaseTest): + + def test_marker_odd_simple(self): + self.start_transaction() + self.push_root(ffi.cast("object_t *", 29)) + stm_minor_collect() + stm_major_collect() + # assert did not crash + x = self.pop_root() + assert int(ffi.cast("uintptr_t", x)) == 29 + + def test_abort_marker_no_shadowstack(self): + tl = self.get_stm_thread_local() + assert tl.longest_marker_state == lib.STM_TIME_OUTSIDE_TRANSACTION + assert tl.longest_marker_time == 0.0 + # + self.start_transaction() + start = time.time() + while abs(time.time() - start) <= 0.1: + pass + self.abort_transaction() + # + tl = self.get_stm_thread_local() + assert tl.longest_marker_state == lib.STM_TIME_RUN_ABORTED_OTHER + assert 0.099 <= tl.longest_marker_time <= 0.9 + assert tl.longest_marker_self[0] == '\x00' + assert tl.longest_marker_other[0] == '\x00' + + def test_abort_marker_shadowstack(self): + self.start_transaction() + p = stm_allocate(16) + self.push_root(ffi.cast("object_t *", 29)) + self.push_root(p) + start = time.time() + while abs(time.time() - start) <= 0.1: + pass + self.abort_transaction() + # + tl = self.get_stm_thread_local() + assert tl.longest_marker_state == lib.STM_TIME_RUN_ABORTED_OTHER + assert 0.099 <= tl.longest_marker_time <= 0.9 + assert tl.longest_marker_self[0] == '\x00' + assert tl.longest_marker_other[0] == '\x00' + + def test_abort_marker_no_shadowstack_cb(self): + @ffi.callback("void(uintptr_t, object_t *, char *, size_t)") + def expand_marker(number, ptr, outbuf, outbufsize): + seen.append(1) + lib.stmcb_expand_marker = expand_marker + seen = [] + # + self.start_transaction() + self.abort_transaction() + # + tl = self.get_stm_thread_local() + assert tl.longest_marker_self[0] == '\x00' + assert not seen + + def test_abort_marker_shadowstack_cb(self): + @ffi.callback("void(uintptr_t, object_t *, char *, size_t)") + def expand_marker(number, ptr, outbuf, outbufsize): + s = '%d %r\x00' % (number, ptr) + assert len(s) <= outbufsize + outbuf[0:len(s)] = s + lib.stmcb_expand_marker = expand_marker + # + self.start_transaction() + p = stm_allocate(16) + self.push_root(ffi.cast("object_t *", 29)) + self.push_root(p) + start = time.time() + while abs(time.time() - start) <= 0.1: + pass + self.abort_transaction() + # + tl = self.get_stm_thread_local() + assert tl.longest_marker_state == lib.STM_TIME_RUN_ABORTED_OTHER + assert 0.099 <= tl.longest_marker_time <= 0.9 + assert ffi.string(tl.longest_marker_self) == '29 %r' % (p,) diff --git a/c7/test/test_nursery.py b/c7/test/test_nursery.py --- a/c7/test/test_nursery.py +++ b/c7/test/test_nursery.py @@ -1,7 +1,7 @@ from support import * import py -class TestBasic(BaseTest): +class TestNursery(BaseTest): def test_nursery_full(self): lib._stm_set_nursery_free_count(2048) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit