[pypy-commit] stmgc marker: Get started
arigo
noreply at buildbot.pypy.org
Fri Apr 18 11:11:57 CEST 2014
Author: Armin Rigo <arigo at 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)
More information about the pypy-commit
mailing list