Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r88:38cc005153e5
Date: 2013-06-09 22:23 +0200
http://bitbucket.org/pypy/stmgc/changeset/38cc005153e5/

Log:    progress

diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -30,6 +30,11 @@
 {
   return thread_descriptor;
 }
+static int is_private(gcptr P)
+{
+  return (P->h_revision == stm_private_rev_num) ||
+    (P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED);
+}
 
 /************************************************************/
 
@@ -119,6 +124,7 @@
       if (P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE)
         {
           wlog_t *item;
+        retry_public_to_private:;
           G2L_FIND(d->public_to_private, P, item, goto no_private_obj);
 
           P = item->val;
@@ -126,8 +132,14 @@
           assert(P->h_revision == stm_private_rev_num);
           fprintf(stderr, "read_barrier: %p -> %p public_to_private\n", G, P);
           return P;
+
+        no_private_obj:
+          if (d->public_descriptor->stolen_objects.size > 0)
+            {
+              stm_normalize_stolen_objects(d);
+              goto retry_public_to_private;
+            }
         }
-    no_private_obj:
 
       if (UNLIKELY(v > d->start_time))   // object too recent?
         {
@@ -188,7 +200,7 @@
   else
     {
       /* stealing */
-      fprintf(stderr, "read_barrier: %p -> stealing %p...", G, P);
+      fprintf(stderr, "read_barrier: %p -> stealing %p...\n  ", G, P);
       stm_steal_stub(P);
       goto retry;
     }
@@ -378,8 +390,7 @@
 
   R = stm_read_barrier(P);
 
-  if (R->h_revision == stm_private_rev_num ||
-      (R->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED))
+  if (is_private(R))
     return R;
 
   if (R->h_tid & GCFLAG_PUBLIC)
@@ -419,11 +430,14 @@
 static _Bool ValidateDuringTransaction(struct tx_descriptor *d,
                                        _Bool during_commit)
 {
-  abort();
-#if 0
   long i, size = d->list_of_read_objects.size;
   gcptr *items = d->list_of_read_objects.items;
 
+  if (size == 0)
+    return 1;
+  abort();
+
+#if 0
   for (i=0; i<size; i++)
     {
       gcptr R = items[i];
@@ -636,6 +650,7 @@
   assert(d->list_of_read_objects.size == 0);
   assert(d->private_from_protected.size == 0);
   assert(!g2l_any_entry(&d->public_to_private));
+  assert(d->public_descriptor->stolen_objects.size == 0);
 
   d->count_reads = 1;
   fxcache_clear(&d->recent_reads_cache);
@@ -668,7 +683,7 @@
       gcptr R = item->addr;
       revision_t v;
     retry:
-      assert(R->h_tid & GCFLAG_OLD);
+      assert(R->h_tid & GCFLAG_PUBLIC);
       v = ACCESS_ONCE(R->h_revision);
       if (!(v & 1))            // "is a pointer", i.e.
         {                      //   "has a more recent revision"
@@ -861,6 +876,9 @@
   struct tx_descriptor *d = thread_descriptor;
   assert(d->active >= 1);
 
+  if (d->public_descriptor->stolen_objects.size != 0)
+    stm_normalize_stolen_objects(d);
+
   spinlock_acquire(d->public_descriptor->collection_lock, 'C');  /*committing*/
   AcquireLocks(d);
 
@@ -918,7 +936,7 @@
   assert(newrev & 1);
   ACCESS_ONCE(stm_private_rev_num) = newrev;
   fprintf(stderr, "%p: stm_local_revision = %ld\n", d, (long)newrev);
-  assert(d->public_descriptor->private_revision_ref = &stm_private_rev_num);
+  assert(d->private_revision_ref = &stm_private_rev_num);
 
   UpdateChainHeads(d, cur_time, localrev);
 
@@ -1136,8 +1154,9 @@
       assert(d->my_lock & 1);
       assert(d->my_lock >= LOCKED);
       stm_private_rev_num = -1;
-      pd->private_revision_ref = &stm_private_rev_num;
+      d->private_revision_ref = &stm_private_rev_num;
       d->max_aborts = -1;
+      pd->descriptor = d;
       thread_descriptor = d;
 
       fprintf(stderr, "[%lx] pthread %lx starting\n",
@@ -1152,15 +1171,12 @@
 
 void DescriptorDone(void)
 {
-    static revision_t no_private_revision = 8;
     revision_t i;
     struct tx_descriptor *d = thread_descriptor;
     assert(d != NULL);
     assert(d->active == 0);
-
-    spinlock_acquire(d->public_descriptor->collection_lock, 'D');  /*done*/
-    d->public_descriptor->private_revision_ref = &no_private_revision;
-    spinlock_release(d->public_descriptor->collection_lock);
+    assert(d->public_descriptor->stolen_objects.size == 0);
+    gcptrlist_delete(&d->public_descriptor->stolen_objects);
 
     spinlock_acquire(descriptor_array_lock, 1);
     i = d->public_descriptor_index;
diff --git a/c4/et.h b/c4/et.h
--- a/c4/et.h
+++ b/c4/et.h
@@ -105,9 +105,10 @@
  * thread shuts down.  It is reused the next time a thread starts. */
 struct tx_public_descriptor {
   revision_t collection_lock;
+  struct tx_descriptor *descriptor;
   struct stub_block_s *stub_blocks;
   gcptr stub_free_list;
-  revision_t *private_revision_ref;
+  struct GcPtrList stolen_objects;
   revision_t free_list_next;
   /* xxx gcpage data here */
 };
@@ -140,6 +141,7 @@
   struct G2L public_to_private;
   char *longest_abort_info;
   long long longest_abort_info_time;
+  revision_t *private_revision_ref;
   struct FXCache recent_reads_cache;
 };
 
diff --git a/c4/steal.c b/c4/steal.c
--- a/c4/steal.c
+++ b/c4/steal.c
@@ -56,8 +56,16 @@
     gcptr L = (gcptr)(v - 2);
 
     if (L->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED) {
-        L = (gcptr)L->h_revision;     /* the backup copy */
-        L->h_tid &= ~GCFLAG_BACKUP_COPY;
+        gcptr B = (gcptr)L->h_revision;     /* the backup copy */
+        B->h_tid &= ~GCFLAG_BACKUP_COPY;
+        L->h_revision = *foreign_pd->descriptor->private_revision_ref;
+
+        /* add {B: L} in 'public_to_private', but lazily, because we don't
+           want to walk over the feet of the foreign thread */
+        B->h_tid |= GCFLAG_PUBLIC_TO_PRIVATE;
+        gcptrlist_insert2(&foreign_pd->stolen_objects, B, L);
+
+        L = B;
     }
 
     /* change L from protected to public */
@@ -72,3 +80,20 @@
  done:
     spinlock_release(foreign_pd->collection_lock);
 }
+
+void stm_normalize_stolen_objects(struct tx_descriptor *d)
+{
+    spinlock_acquire(d->public_descriptor->collection_lock, 'N');
+
+    long i, size = d->public_descriptor->stolen_objects.size;
+    gcptr *items = d->public_descriptor->stolen_objects.items;
+
+    for (i = 0; i < size; i += 2) {
+        gcptr B = items[i];
+        gcptr L = items[i + 1];
+        g2l_insert(&d->public_to_private, B, L);
+    }
+    gcptrlist_clear(&d->public_descriptor->stolen_objects);
+
+    spinlock_release(d->public_descriptor->collection_lock);
+}
diff --git a/c4/steal.h b/c4/steal.h
--- a/c4/steal.h
+++ b/c4/steal.h
@@ -10,7 +10,7 @@
 gcptr stm_stub_malloc(struct tx_public_descriptor *);
 void stm_steal_stub(gcptr);
 gcptr stm_get_stolen_obj(long index);   /* debugging */
-void stm_normalize_stolen_objects(struct tx_public_descriptor *);
+void stm_normalize_stolen_objects(struct tx_descriptor *);
 
 
 #endif
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
@@ -229,7 +229,6 @@
     run_parallel(f1, f2)
 
 def test_stealing_while_modifying():
-    py.test.skip("in-progress")
     p = palloc(HDR + WORD)
 
     def f1(r):
@@ -258,6 +257,7 @@
             assert pback.h_tid & GCFLAG_PUBLIC_TO_PRIVATE
             assert lib.stm_read_barrier(p) == p1
             assert lib.stm_read_barrier(p1) == p1
+            assert lib.stm_read_barrier(pback) == p1
             assert pback.h_revision & 1
         perform_transaction(cb)
 
@@ -273,6 +273,8 @@
         def cb(c):
             assert c == 0
             r.enter_in_parallel()
+            lib.stm_commit_transaction()
+            lib.stm_begin_inevitable_transaction()
             p2 = lib.stm_read_barrier(p)    # steals
             assert lib.rawgetlong(p2, 0) == 2782172
             assert p2 == lib.stm_read_barrier(p)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to