[pypy-commit] stmgc default: Add another unit test (run by test/test_demo.py) for major GC tracking
arigo
noreply at buildbot.pypy.org
Tue Aug 12 18:43:29 CEST 2014
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r1308:38dbf997b57b
Date: 2014-08-12 18:43 +0200
http://bitbucket.org/pypy/stmgc/changeset/38dbf997b57b/
Log: Add another unit test (run by test/test_demo.py) for major GC
tracking the parts of the shadowstacks that have been moved away
diff --git a/c7/demo/test_shadowstack.c b/c7/demo/test_shadowstack.c
new file mode 100644
--- /dev/null
+++ b/c7/demo/test_shadowstack.c
@@ -0,0 +1,68 @@
+#include <stdlib.h>
+#include <assert.h>
+#include "stmgc.h"
+
+stm_thread_local_t stm_thread_local;
+
+typedef TLPREFIX struct node_s node_t;
+
+struct node_s {
+ struct object_s hdr;
+ long value;
+};
+
+ssize_t stmcb_size_rounded_up(struct object_s *ob)
+{
+ return sizeof(struct node_s);
+}
+void stmcb_trace(struct object_s *obj, void visit(object_t **))
+{
+}
+void stmcb_get_card_base_itemsize(struct object_s *obj,
+ uintptr_t offset_itemsize[2])
+{
+ abort();
+}
+void stmcb_trace_cards(struct object_s *obj, void visit(object_t **),
+ uintptr_t start, uintptr_t stop)
+{
+ abort();
+}
+void stmcb_commit_soon() {}
+
+
+int main(void)
+{
+ rewind_jmp_buf rjbuf;
+
+ stm_setup();
+ stm_register_thread_local(&stm_thread_local);
+ stm_rewind_jmp_enterframe(&stm_thread_local, &rjbuf);
+
+ stm_start_transaction(&stm_thread_local);
+ node_t *node = (node_t *)stm_allocate(sizeof(struct node_s));
+ node->value = 129821;
+ STM_PUSH_ROOT(stm_thread_local, node);
+ stm_commit_transaction();
+
+ /* now in a new transaction, pop the node off the shadowstack, but
+ then do a major collection. It should still be found by the
+ tracing logic. */
+ stm_start_transaction(&stm_thread_local);
+ STM_POP_ROOT(stm_thread_local, node);
+ assert(node->value == 129821);
+ STM_PUSH_ROOT(stm_thread_local, NULL);
+ stm_collect(9);
+
+ node_t *node2 = (node_t *)stm_allocate(sizeof(struct node_s));
+ assert(node2 != node);
+ assert(node->value == 129821);
+
+ STM_PUSH_ROOT(stm_thread_local, node2);
+ stm_collect(0);
+ STM_POP_ROOT(stm_thread_local, node2);
+ assert(node2 != node);
+ assert(node->value == 129821);
+
+ return 0;
+}
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -363,6 +363,16 @@
mark_trace(obj, segment_base);
}
+static void *mark_visit_objects_from_ss(void *_, const void *slice, size_t size)
+{
+ const struct stm_shadowentry_s *p, *end;
+ p = (const struct stm_shadowentry_s *)slice;
+ end = (const struct stm_shadowentry_s *)(slice + size);
+ for (; p < end; p++)
+ mark_visit_object(p->ss, stm_object_pages);
+ return NULL;
+}
+
static void mark_visit_from_roots(void)
{
if (testing_prebuilt_objs != NULL) {
@@ -386,6 +396,7 @@
mark_visit_object(current->ss, segment_base);
}
mark_visit_object(tl->thread_local_obj, segment_base);
+ stm_rewind_jmp_enum_shadowstack(tl, mark_visit_objects_from_ss);
tl = tl->next;
} while (tl != stm_all_thread_locals);
diff --git a/c7/stm/rewind_setjmp.c b/c7/stm/rewind_setjmp.c
--- a/c7/stm/rewind_setjmp.c
+++ b/c7/stm/rewind_setjmp.c
@@ -105,21 +105,28 @@
do_longjmp(rjthread, &_rewind_jmp_marker);
}
-char *rewind_jmp_restore_shadowstack(rewind_jmp_thread *rjthread)
+
+char *rewind_jmp_enum_shadowstack(rewind_jmp_thread *rjthread,
+ void *callback(void *, const void *, size_t))
{
struct _rewind_jmp_moved_s *p = rjthread->moved_off;
char *sstarget = rjthread->moved_off_ssbase;
while (p) {
char *ssend = sstarget + p->shadowstack_size;
- memcpy(sstarget, ((char *)p) + RJM_HEADER + p->stack_size,
- p->shadowstack_size);
+ callback(sstarget, ((char *)p) + RJM_HEADER + p->stack_size,
+ p->shadowstack_size);
sstarget = ssend;
p = p->next;
}
return sstarget;
}
+char *rewind_jmp_restore_shadowstack(rewind_jmp_thread *rjthread)
+{
+ return rewind_jmp_enum_shadowstack(rjthread, memcpy);
+}
+
__attribute__((noinline))
void _rewind_jmp_copy_stack_slice(rewind_jmp_thread *rjthread)
{
diff --git a/c7/stm/rewind_setjmp.h b/c7/stm/rewind_setjmp.h
--- a/c7/stm/rewind_setjmp.h
+++ b/c7/stm/rewind_setjmp.h
@@ -1,6 +1,8 @@
#ifndef _REWIND_SETJMP_H_
#define _REWIND_SETJMP_H_
+#include <stddef.h>
+
/************************************************************
: : ^^^^^
@@ -75,6 +77,8 @@
long rewind_jmp_setjmp(rewind_jmp_thread *rjthread, void *ss);
void rewind_jmp_longjmp(rewind_jmp_thread *rjthread) __attribute__((noreturn));
char *rewind_jmp_restore_shadowstack(rewind_jmp_thread *rjthread);
+char *rewind_jmp_enum_shadowstack(rewind_jmp_thread *rjthread,
+ void *callback(void *, const void *, size_t));
#define rewind_jmp_forget(rjthread) do { \
if ((rjthread)->moved_off) _rewind_jmp_free_stack_slices(rjthread); \
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -343,6 +343,8 @@
(tl)->shadowstack = (struct stm_shadowentry_s *) \
rewind_jmp_restore_shadowstack(&(tl)->rjthread); \
} while (0)
+#define stm_rewind_jmp_enum_shadowstack(tl, callback) \
+ rewind_jmp_enum_shadowstack(&(tl)->rjthread, callback)
/* Starting and ending transactions. stm_read(), stm_write() and
stm_allocate() should only be called from within a transaction.
diff --git a/c7/test/test_demo.py b/c7/test/test_demo.py
--- a/c7/test/test_demo.py
+++ b/c7/test/test_demo.py
@@ -13,6 +13,8 @@
self._do("make -C ../demo %s" % target)
self._do("../demo/%s 2> /dev/null" % target)
+ def test_shadowstack(self): self.make_and_run("debug-test_shadowstack")
+
def test_demo2_debug(self): self.make_and_run("debug-demo2")
def test_demo2_build(self): self.make_and_run("build-demo2")
def test_demo2_release(self): self.make_and_run("release-demo2")
More information about the pypy-commit
mailing list