Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r125:61b9c5a13a48
Date: 2013-06-14 16:54 +0200
http://bitbucket.org/pypy/stmgc/changeset/61b9c5a13a48/

Log:    Next test

diff --git a/c4/nursery.c b/c4/nursery.c
--- a/c4/nursery.c
+++ b/c4/nursery.c
@@ -119,16 +119,75 @@
 
 static void mark_public_to_young(struct tx_descriptor *d)
 {
+    /* "public_to_young" contains ptrs to the public copies used as
+       key of "public_to_private", but only the ones that were added
+       since the last minor collection.  Once the transaction commit,
+       they stay in "public_to_young", and so they become public
+       objects whose h_revision is a public stub, which itself points
+       (originally) to a protected young object.
+
+       Be careful and accept more or less any object in the list, which
+       can show up because of aborted transactions.
+    */
     long i, size = d->public_to_young.size;
     gcptr *items = d->public_to_young.items;
 
     for (i = 0; i < size; i++) {
         gcptr P = items[i];
+        assert(P->h_tid & GCFLAG_PUBLIC);
+
+        revision_t v = ACCESS_ONCE(P->h_revision);
         wlog_t *item;
+        G2L_FIND(d->public_to_private, P, item, goto not_in_public_to_private);
 
-        G2L_FIND(d->public_to_private, P, item, continue);
+        if (!(v & 1)) {   // "is a pointer"
+            /* P is both a key in public_to_private and an outdated copy.
+               We are in a case where we know the transaction will not
+               be able to commit successfully.
+            */
+            abort();
+            AbortTransactionAfterCollect(d, ABRT_COLLECT_MINOR);
+            //...
+        }
+
         visit_if_young(&item->val);
+        continue;
+
+    not_in_public_to_private:
+        if (v & 1) {   // "is not a pointer"
+            /* P is neither a key in public_to_private nor outdated.
+               It must come from an older transaction that aborted.
+               Nothing to do now.
+            */
+            continue;
+        }
+
+        gcptr S = (gcptr)v;
+        revision_t w = ACCESS_ONCE(S->h_revision);
+        if ((w & 3) != 2) {
+            /* P has a ptr in h_revision, but this object is not a stub
+               with a protected pointer.  It has likely been the case
+               in the past, but someone made even more changes.
+               Nothing to do now.
+            */
+            continue;
+        }
+
+        if (STUB_THREAD(S) != d->public_descriptor) {
+            /* Bah, it's indeed a stub but for another thread.  Nothing
+               to do now.
+            */
+            continue;
+        }
+
+        /* It's a stub for us.  It cannot be un-stubbed under our
+           feet because we hold our own collection_lock.
+        */
+        gcptr L = (gcptr)(w - 2);
+        visit_if_young(&L);
+        S->h_revision = ((revision_t)L) | 2;
     }
+
     gcptrlist_clear(&d->public_to_young);
 }
 
diff --git a/c4/test/test_nursery.py b/c4/test/test_nursery.py
--- a/c4/test/test_nursery.py
+++ b/c4/test/test_nursery.py
@@ -92,3 +92,35 @@
     assert p2b != p2
     check_not_free(p2b)
     assert lib.getlong(p2b, 0) == 8972981
+
+def test_outer2inner_after_transaction_end():
+    p1 = palloc(HDR + WORD)
+    lib.rawsetlong(p1, 0, 420063)
+    p2 = lib.stm_write_barrier(p1)
+    lib.rawsetlong(p2, 0, -91467)
+    assert lib.in_nursery(p2)
+    lib.stm_push_root(p1)
+    print "committing..."
+    transaction_break()
+    print "done"
+
+    # first check that the situation is still the same in the next transaction
+    p1b = lib.stm_pop_root()
+    assert p1b == p1
+    assert classify(p1b) == "public"
+    p2b = lib.stm_read_barrier(p1b)
+    assert lib.in_nursery(p2b)
+    assert p2b == p2
+    assert classify(p2) == "protected"
+    check_not_free(p2b)
+    lib.stm_push_root(p1b)
+    print 'ok'
+
+    # then do a minor collection
+    minor_collect()
+    p1b = lib.stm_pop_root()
+    assert p1b == p1
+    # check that the link p1 -> p2 was kept alive by moving p2 outside
+    p2b = lib.stm_read_barrier(p1b)
+    assert not lib.in_nursery(p2b)
+    check_not_free(p2b)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to