[pypy-commit] stmgc default: Aborting, including aborting GCFLAG_PRIVATE_FROM_PROTECTED

arigo noreply at buildbot.pypy.org
Mon Jun 10 09:49:38 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r90:50f4a1c6ad65
Date: 2013-06-10 09:49 +0200
http://bitbucket.org/pypy/stmgc/changeset/50f4a1c6ad65/

Log:	Aborting, including aborting GCFLAG_PRIVATE_FROM_PROTECTED

diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -494,6 +494,10 @@
   struct timespec now;
   long long elapsed_time;
 
+  /* acquire the lock, but don't double-acquire it if already committing */
+  if (d->public_descriptor->collection_lock != 'C')
+    spinlock_acquire(d->public_descriptor->collection_lock, 'C');
+
   assert(d->active != 0);
   assert(!is_inevitable(d));
   assert(num < ABORT_REASONS);
@@ -566,11 +570,13 @@
       d->reads_size_limit_nonatomic = limit;
   }
 
+  AbortPrivateFromProtected(d);
   gcptrlist_clear(&d->list_of_read_objects);
-  abort();
-  gcptrlist_clear(&d->private_from_protected);  //XXX clean up
-  abort();
-  //stmgc_abort_transaction(d);
+  g2l_clear(&d->public_to_private);
+  gcptrlist_clear(&d->public_descriptor->stolen_objects);
+
+  /* release the lock */
+  spinlock_release(d->public_descriptor->collection_lock);
 
   fprintf(stderr,
           "\n"
@@ -848,6 +854,35 @@
   gcptrlist_clear(&d->private_from_protected);
 }
 
+void AbortPrivateFromProtected(struct tx_descriptor *d)
+{
+  long i, size = d->private_from_protected.size;
+  gcptr *items = d->private_from_protected.items;
+
+  for (i = 0; i < size; i++)
+    {
+      gcptr P = items[i];
+      assert(P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED);
+      assert(!(P->h_revision & 1));   // "is a pointer"
+
+      gcptr B = (gcptr)P->h_revision;
+      if (B->h_tid & GCFLAG_PUBLIC)
+        {
+          assert(!(B->h_tid & GCFLAG_BACKUP_COPY));
+          P->h_tid &= ~GCFLAG_PRIVATE_FROM_PROTECTED;
+          P->h_tid |= GCFLAG_PUBLIC;
+          /* P becomes a public outdated object */
+        }
+      else
+        {
+          assert(B->h_tid & GCFLAG_BACKUP_COPY);
+          memcpy(P, B, stmcb_size(P));
+          P->h_tid &= ~GCFLAG_BACKUP_COPY;
+        }
+    };
+  gcptrlist_clear(&d->private_from_protected);
+}
+
 void CommitTransaction(void)
 {   /* must save roots around this call */
   revision_t cur_time;
diff --git a/c4/test/test_et.py b/c4/test/test_et.py
--- a/c4/test/test_et.py
+++ b/c4/test/test_et.py
@@ -228,7 +228,7 @@
         r.set(3)
     run_parallel(f1, f2)
 
-def test_stealing_while_modifying():
+def test_stealing_while_modifying(aborting=False):
     p = palloc(HDR + WORD)
 
     def f1(r):
@@ -239,7 +239,15 @@
         pback_ = []
 
         def cb(c):
-            assert c == 0
+            if c != 0:
+                assert aborting
+                [pback] = pback_
+                assert classify(p) == "public"
+                assert classify(p1) == "public"
+                assert classify(pback) == "public"
+                assert lib.stm_read_barrier(p) == pback
+                assert lib.stm_read_barrier(p1) == pback
+                return
             assert classify(p) == "public"
             assert classify(p1) == "protected"
             assert classify(follow_revision(p)) == "stub"
@@ -261,16 +269,24 @@
             assert lib.stm_read_barrier(p1) == p1
             assert lib.stm_read_barrier(pback) == p1
             assert pback.h_revision & 1
+            if aborting:
+                abort_and_retry()
         perform_transaction(cb)
 
         lib.stm_commit_transaction()
         lib.stm_begin_inevitable_transaction()
         [pback] = pback_
-        assert classify(p1) == "protected"
-        assert classify(pback) == "public"
-        assert classify(follow_revision(pback)) == "stub"
-        assert follow_revision(pback).h_revision == (
-            int(ffi.cast("revision_t", p1)) | 2)
+        if aborting:
+            assert classify(p1) == "public"
+            assert classify(pback) == "public"
+            assert pback.h_revision & 1
+            assert p1.h_revision == int(ffi.cast("revision_t", pback))
+        else:
+            assert classify(p1) == "protected"
+            assert classify(pback) == "public"
+            assert classify(follow_revision(pback)) == "stub"
+            assert follow_revision(pback).h_revision == (
+                int(ffi.cast("revision_t", p1)) | 2)
 
     def f2(r):
         def cb(c):
@@ -286,3 +302,22 @@
         perform_transaction(cb)
 
     run_parallel(f1, f2)
+
+def test_abort_private_from_protected():
+    p = nalloc(HDR + WORD)
+    lib.setlong(p, 0, 897987)
+    lib.stm_commit_transaction()
+    lib.stm_begin_inevitable_transaction()
+    #
+    def cb(c):
+        assert classify(p) == "protected"
+        assert lib.getlong(p, 0) == 897987
+        if c == 0:
+            lib.setlong(p, 0, -38383)
+            assert lib.getlong(p, 0) == -38383
+            assert classify(p) == "private"
+            abort_and_retry()
+    perform_transaction(cb)
+
+def test_abort_stealing_while_modifying():
+    test_stealing_while_modifying(aborting=True)


More information about the pypy-commit mailing list