Author: Armin Rigo <[email protected]>
Branch:
Changeset: r119:e26c4be262b8
Date: 2013-06-13 22:49 +0200
http://bitbucket.org/pypy/stmgc/changeset/e26c4be262b8/
Log: Start copying from c3 portions of code and tests.
diff --git a/c4/et.h b/c4/et.h
--- a/c4/et.h
+++ b/c4/et.h
@@ -105,7 +105,6 @@
* thread shuts down. It is reused the next time a thread starts. */
struct tx_public_descriptor {
revision_t collection_lock;
- NURSERY_FIELDS_DECL
struct tx_descriptor *descriptor;
struct stub_block_s *stub_blocks;
gcptr stub_free_list;
@@ -125,6 +124,8 @@
gcptr *shadowstack;
gcptr **shadowstack_end_ref;
+ NURSERY_FIELDS_DECL
+
long atomic; /* 0 = not atomic, > 0 atomic */
unsigned long count_reads;
unsigned long reads_size_limit; /* see should_break_tr. */
diff --git a/c4/nursery.c b/c4/nursery.c
new file mode 100644
--- /dev/null
+++ b/c4/nursery.c
@@ -0,0 +1,161 @@
+#include "stmimpl.h"
+
+
+static int is_in_nursery(struct tx_descriptor *d, gcptr obj)
+{
+ return (d->nursery_base <= (char*)obj && ((char*)obj) < d->nursery_end);
+}
+
+/************************************************************/
+
+void stm_init_nursery(void)
+{
+ struct tx_descriptor *d = thread_descriptor;
+
+ assert(d->nursery_base == NULL);
+ d->nursery_base = stm_malloc(GC_NURSERY);
+ memset(d->nursery_base, 0, GC_NURSERY);
+ d->nursery_end = d->nursery_base + GC_NURSERY;
+ d->nursery_current = d->nursery_base;
+}
+
+static char *collect_and_allocate_size(size_t size); /* forward */
+
+gcptr stm_allocate(size_t size, unsigned long tid)
+{
+ /* XXX inline the fast path */
+ struct tx_descriptor *d = thread_descriptor;
+ char *cur = d->nursery_current;
+ char *end = cur + size;
+ d->nursery_current = end;
+ if (end > d->nursery_end) {
+ cur = collect_and_allocate_size(size);
+ }
+ gcptr P = (gcptr)cur;
+ assert(tid == (tid & STM_USER_TID_MASK));
+ P->h_tid = tid;
+ P->h_revision = stm_private_rev_num;
+ return P;
+}
+
+/************************************************************/
+
+static void visit_if_young(gcptr *root)
+{
+ gcptr obj = *root;
+ gcptr fresh_old_copy;
+ struct tx_descriptor *d = thread_descriptor;
+
+ if (!is_in_nursery(d, obj)) {
+ /* not a nursery object */
+ }
+ else {
+ /* a nursery object */
+ fresh_old_copy = stmgc_duplicate(obj);
+ fresh_old_copy->h_tid |= GCFLAG_OLD;
+ obj->h_tid |= GCFLAG_NURSERY_MOVED;
+ obj->h_revision = (revision_t)fresh_old_copy;
+ *root = fresh_old_copy;
+ }
+}
+
+static void mark_young_roots(gcptr *root, gcptr *end)
+{
+ /* XXX use a way to avoid walking all roots again and again */
+ for (; root != end; root++) {
+ visit_if_young(root);
+ }
+}
+
+static void setup_minor_collect(struct tx_descriptor *d)
+{
+ spinlock_acquire(d->public_descriptor->collection_lock, 'M'); /*minor*/
+ assert(gcptrlist_size(&d->old_objects_to_trace) == 0);
+
+ if (d->public_descriptor->stolen_objects.size != 0)
+ stm_normalize_stolen_objects(d);
+}
+
+static void teardown_minor_collect(struct tx_descriptor *d)
+{
+ assert(gcptrlist_size(&d->old_objects_to_trace) == 0);
+ assert(gcptrlist_size(&d->public_descriptor->stolen_objects) == 0);
+
+ spinlock_release(d->public_descriptor->collection_lock);
+}
+
+static void minor_collect(struct tx_descriptor *d)
+{
+ fprintf(stderr, "minor collection [%p to %p]\n",
+ d->nursery_base, d->nursery_end);
+
+ /* acquire the "collection lock" first */
+ setup_minor_collect(d);
+
+ mark_young_roots(d->shadowstack, *d->shadowstack_end_ref);
+
+#if 0
+ mark_private_from_protected(d);
+
+ mark_public_to_young(d);
+
+ mark_private_old_pointing_to_young(d);
+
+ visit_all_outside_objects(d);
+ fix_list_of_read_objects(d);
+
+ /* now all surviving nursery objects have been moved out, and all
+ surviving young-but-outside-the-nursery objects have been flagged
+ with GCFLAG_OLD */
+ finish_public_to_young(d);
+
+ if (g2l_any_entry(&d->young_objects_outside_nursery))
+ free_unvisited_young_objects_outside_nursery(d);
+#endif
+
+ teardown_minor_collect(d);
+
+ /* clear the nursery */
+ memset(d->nursery_base, 0, GC_NURSERY);
+ d->nursery_current = d->nursery_base;
+
+ assert(!stmgc_minor_collect_anything_to_do(d));
+}
+
+void stmgc_minor_collect(void)
+{
+ struct tx_descriptor *d = thread_descriptor;
+ assert(d->active >= 1);
+ minor_collect(d);
+ AbortNowIfDelayed();
+}
+
+int stmgc_minor_collect_anything_to_do(struct tx_descriptor *d)
+{
+ if (d->nursery_current == d->nursery_base /*&&
+ !g2l_any_entry(&d->young_objects_outside_nursery)*/ ) {
+ /* there is no young object */
+ //assert(gcptrlist_size(&d->private_old_pointing_to_young) == 0);
+ //assert(gcptrlist_size(&d->public_to_young) == 0);
+ return 0;
+ }
+ else {
+ /* there are young objects */
+ return 1;
+ }
+}
+
+static char *collect_and_allocate_size(size_t allocate_size)
+{
+ stmgc_minor_collect();
+ //stmgcpage_possibly_major_collect(0);
+
+ struct tx_descriptor *d = thread_descriptor;
+ assert(d->nursery_current == d->nursery_base);
+
+ //_debug_roots(d->shadowstack, *d->shadowstack_end_ref);
+
+ d->nursery_current = d->nursery_base + allocate_size;
+ assert(d->nursery_current <= d->nursery_end); /* XXX object too big */
+ return d->nursery_base;
+}
diff --git a/c4/nursery.h b/c4/nursery.h
new file mode 100644
--- /dev/null
+++ b/c4/nursery.h
@@ -0,0 +1,21 @@
+#ifndef _SRCSTM_NURSERY_H
+#define _SRCSTM_NURSERY_H
+
+#ifndef GC_NURSERY
+#define GC_NURSERY 4194304 /* 4 MB */
+#endif
+
+
+#define NURSERY_FIELDS_DECL \
+ char *nursery_current; \
+ char *nursery_end; \
+ char *nursery_base; \
+ struct GcPtrList old_objects_to_trace;
+
+struct tx_descriptor; /* from et.h */
+
+void stm_init_nursery(void);
+void stmgc_minor_collect(void);
+int stmgc_minor_collect_anything_to_do(struct tx_descriptor *);
+
+#endif
diff --git a/c4/test/test_nursery.py b/c4/test/test_nursery.py
new file mode 100644
--- /dev/null
+++ b/c4/test/test_nursery.py
@@ -0,0 +1,33 @@
+import py
+from support import *
+
+
+def setup_function(f):
+ lib.stm_clear_between_tests()
+ lib.stm_initialize_tests(getattr(f, 'max_aborts', 0))
+
+def teardown_function(_):
+ lib.stm_finalize()
+
+
+def test_nursery_alloc():
+ for i in range(20):
+ p = nalloc(HDR)
+ check_not_free(p)
+
+def test_stm_roots():
+ p1 = nalloc(HDR)
+ p2 = nalloc(HDR)
+ p3 = nalloc(HDR)
+ seen = set()
+ for i in range(20):
+ lib.stm_push_root(p1)
+ lib.stm_push_root(p3)
+ p = nalloc(HDR)
+ check_not_free(p)
+ seen.add(p)
+ p3 = lib.stm_pop_root()
+ p1 = lib.stm_pop_root()
+ check_not_free(p1)
+ check_not_free(p3)
+ assert p2 in seen # the pointer location was reused
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit