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

Reply via email to