Author: Armin Rigo <ar...@tunes.org>
Branch: 
Changeset: r65:7526350df472
Date: 2013-06-05 15:57 +0200
http://bitbucket.org/pypy/stmgc/changeset/7526350df472/

Log:    in-progress

diff --git a/c3/et.c b/c3/et.c
--- a/c3/et.c
+++ b/c3/et.c
@@ -286,27 +286,33 @@
 #endif
 }
 
-static gcptr LocalizeProtected(struct tx_descriptor *d, gcptr R)
+static gcptr LocalizeProtected(struct tx_descriptor *d, gcptr P)
 {
-  assert(!(R->h_tid & GCFLAG_PUBLIC_TO_PRIVATE));
+  gcptr B;
 
-  /* duplicate, and save the original R->h_revision into an extra
-     word allocated just after L */
-  assert(R->h_revision & 1);
-  gcptr L = stmgc_duplicate(R, R->h_revision);
+  assert(P->h_revision != stm_private_rev_num);
+  assert(!(P->h_tid & GCFLAG_PUBLIC));
+  assert(!(P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE));
+  assert(!(P->h_tid & GCFLAG_BACKUP_COPY));
+  assert(!(P->h_tid & GCFLAG_STUB));
 
-  /* cross-thread memory barrier: make sure the local object is correct
-     and has h_revision == stm_local_revision, and the extra word is
-     written as well; when it is done, and only then, then we change
-     R->h_revision */
-  smp_wmb();
-
-  R->h_revision = (revision_t)L;
-
-  gcptrlist_insert(&d->protected_with_private_copy, R);
-  AddInReadSet(d, R);
-  /*mark*/
-  return L;
+  if (P->h_revision & 1)
+    {
+      /* does not have a backup yet */
+      B = stmgc_duplicate(P, 0);
+      B->h_tid |= GCFLAG_BACKUP_COPY;
+    }
+  else
+    {
+      size_t size = stmcb_size(P);
+      B = (gcptr)P->h_revision;
+      assert(B->h_tid & GCFLAG_BACKUP_COPY);
+      memcpy(B + 1, P + 1, size - sizeof(*B));
+    }
+  assert(B->h_tid & GCFLAG_BACKUP_COPY);
+  g2l_insert(&d->private_to_backup, P, B);
+  P->h_revision = stm_private_rev_num;
+  return P;
 }
 
 static gcptr LocalizePublic(struct tx_descriptor *d, gcptr R)
@@ -338,35 +344,25 @@
 
 gcptr stm_WriteBarrier(gcptr P)
 {
-  gcptr R, W;
+  gcptr W;
   struct tx_descriptor *d = thread_descriptor;
   assert(d->active >= 1);
 
-  /* must normalize the situation now, otherwise we risk that
-     LocalizePublic creates a new private version of a public
-     object that has got one, attached to the equivalent stolen
-     protected object */
-  if (gcptrlist_size(&d->stolen_objects) > 0)
-    stmgc_normalize_stolen_objects();
-
-  /* XXX optimize me based on common patterns */
-  R = HeadOfRevisionChainList(d, P);
-
-  switch (stmgc_classify(R)) {
-  case K_PRIVATE:   W = R;                       break;
-  case K_PROTECTED: W = LocalizeProtected(d, R); break;
-  case K_PUBLIC:    W = LocalizePublic(d, R);    break;
-  default: abort();
-  }
-
-  if (W->h_tid & GCFLAG_WRITE_BARRIER)
-    stmgc_write_barrier(W);
+  W = LocalizeProtected(d, P);
 
   fprintf(stderr, "write_barrier: %p -> %p\n", P, W);
 
   return W;
 }
 
+gcptr stm_get_backup_copy(gcptr P)
+{
+  struct tx_descriptor *d = thread_descriptor;
+  wlog_t *entry;
+  G2L_FIND(d->private_to_backup, P, entry, return NULL);
+  return entry->val;
+}
+
 /************************************************************/
 
 static revision_t GetGlobalCurTime(struct tx_descriptor *d)
@@ -527,6 +523,7 @@
   }
 
   gcptrlist_clear(&d->list_of_read_objects);
+  g2l_clear(&d->private_to_backup);
   stmgc_abort_transaction(d);
 
   fprintf(stderr,
@@ -590,6 +587,7 @@
     d->start_real_time.tv_nsec = -1;
   }
   assert(d->list_of_read_objects.size == 0);
+  assert(!g2l_any_entry(&d->private_to_backup));
   stmgc_start_transaction(d);
 
   d->count_reads = 1;
@@ -775,6 +773,23 @@
     }
 }
 
+void TurnPrivateWithBackupToProtected(struct tx_descriptor *d,
+                                      revision_t cur_time)
+{
+  wlog_t *item;
+  G2L_LOOP_FORWARD(d->private_to_backup, item)
+    {
+      gcptr P = item->addr;
+      gcptr B = item->val;
+      assert(P->h_revision == stm_private_rev_num);
+      assert(B->h_tid & GCFLAG_BACKUP_COPY);
+      B->h_revision = cur_time;
+      P->h_revision = (revision_t)B;
+
+    } G2L_LOOP_END;
+  g2l_clear(&d->private_to_backup);
+}
+
 void CommitTransaction(void)
 {   /* must save roots around this call */
   revision_t cur_time;
@@ -828,6 +843,8 @@
           "*************************************\n",
           (long)cur_time);
 
+  TurnPrivateWithBackupToProtected(d, cur_time);
+
   revision_t localrev = stm_private_rev_num;
   UpdateProtectedChainHeads(d, cur_time, localrev);
   smp_wmb();
@@ -1057,6 +1074,7 @@
 
     thread_descriptor = NULL;
 
+    g2l_delete(&d->private_to_backup);
     gcptrlist_delete(&d->list_of_read_objects);
     gcptrlist_delete(&d->abortinfo);
     free(d->longest_abort_info);
diff --git a/c3/et.h b/c3/et.h
--- a/c3/et.h
+++ b/c3/et.h
@@ -116,6 +116,7 @@
   unsigned int num_spinloops[SPINLOOP_REASONS];
   struct GcPtrList list_of_read_objects;
   struct GcPtrList abortinfo;
+  struct G2L private_to_backup;
   char *longest_abort_info;
   long long longest_abort_info_time;
   struct FXCache recent_reads_cache;
@@ -175,6 +176,7 @@
 gcptr stm_RepeatReadBarrier(gcptr);
 gcptr stm_WriteBarrier(gcptr);
 gcptr _stm_nonrecord_barrier(gcptr, int *);
+gcptr stm_get_backup_copy(gcptr);
 
 int DescriptorInit(void);
 void DescriptorDone(void);
diff --git a/c3/nursery.c b/c3/nursery.c
--- a/c3/nursery.c
+++ b/c3/nursery.c
@@ -180,12 +180,14 @@
     memcpy(localobj, globalobj, size);
 
     assert(!(localobj->h_tid & GCFLAG_NURSERY_MOVED));
+#if 0
     localobj->h_tid &= ~(GCFLAG_VISITED           |
                          GCFLAG_PUBLIC_TO_PRIVATE |
                          GCFLAG_PREBUILT_ORIGINAL |
                          GCFLAG_WRITE_BARRIER     |
                          GCFLAG_OLD);
     localobj->h_revision = stm_private_rev_num;
+#endif
     return localobj;
 }
 
diff --git a/c3/test/support.py b/c3/test/support.py
--- a/c3/test/support.py
+++ b/c3/test/support.py
@@ -68,6 +68,7 @@
     void stm_start_sharedlock(void);
     void stm_stop_sharedlock(void);
     void AbortTransaction(int);
+    gcptr stm_get_backup_copy(gcptr);
 
     gcptr getptr(gcptr, long);
     void setptr(gcptr, long, gcptr);
@@ -90,12 +91,15 @@
     /* some constants normally private that are useful in the tests */
     #define WORD                     ...
     #define GC_PAGE_SIZE             ...
+    #define GCFLAG_OLD               ...
     #define GCFLAG_VISITED           ...
+    #define GCFLAG_PUBLIC            ...
+    #define GCFLAG_PREBUILT_ORIGINAL ...
+    #define GCFLAG_BACKUP_COPY       ...
     #define GCFLAG_PUBLIC_TO_PRIVATE ...
-    #define GCFLAG_PREBUILT_ORIGINAL ...
     #define GCFLAG_WRITE_BARRIER     ...
     #define GCFLAG_NURSERY_MOVED     ...
-    #define GCFLAG_OLD               ...
+    #define GCFLAG_STOLEN            ...
     #define GCFLAG_STUB              ...
     #define ABRT_MANUAL              ...
     typedef struct { ...; } page_header_t;
@@ -509,3 +513,17 @@
 
 def abort_and_retry():
     lib.AbortTransaction(lib.ABRT_MANUAL)
+
+def classify(p):
+    private = p.h_revision == lib.get_private_rev_num()
+    public  = (p.h_tid & GCFLAG_PUBLIC) != 0
+    backup  = (p.h_tid & GCFLAG_BACKUP_COPY) != 0
+    assert private + public + backup <= 1
+    if private:
+        return "private"
+    if public:
+        return "public"
+    if backup:
+        return "backup"
+    else:
+        return "protected"
diff --git a/c3/test/test_et.py b/c3/test/test_et.py
--- a/c3/test/test_et.py
+++ b/c3/test/test_et.py
@@ -7,6 +7,8 @@
     lib.stm_initialize_tests(getattr(f, 'max_aborts', 0))
 
 def teardown_function(_):
+    lib.stm_commit_transaction()
+    lib.stm_begin_inevitable_transaction()
     lib.stm_finalize()
 
 
@@ -16,12 +18,14 @@
     assert r < 0 and r % 2 == 1
     assert p.h_revision == r
     assert p.h_tid == lib.gettid(p) | 0    # no GC flags
+    assert classify(p) == "private"
 
 def test_write_barrier_private():
     p = nalloc(HDR)
     assert lib.stm_write_barrier(p) == p
     assert p.h_revision == lib.get_private_rev_num()
     assert p.h_tid == lib.gettid(p) | 0    # no GC flags
+    assert classify(p) == "private"
 
 def test_protected_no_backup():
     p = nalloc(HDR)
@@ -34,6 +38,7 @@
     assert r != r2
     assert p.h_revision == r
     assert p.h_tid == lib.gettid(p) | 0    # no GC flags
+    assert classify(p) == "protected"
 
 def test_private_with_backup():
     p = nalloc(HDR)
@@ -41,9 +46,11 @@
     lib.stm_begin_inevitable_transaction()
     r2 = lib.get_private_rev_num()
     assert p.h_revision != r2
+    assert classify(p) == "protected"
     p2 = lib.stm_write_barrier(p)
     assert p2 == p       # does not move
     assert p.h_revision == r2
+    assert classify(p) == "private"
 
 def test_get_backup_copy():
     p = nalloc(HDR + WORD)
@@ -59,6 +66,21 @@
     assert pback.h_tid == p.h_tid | GCFLAG_BACKUP_COPY
     assert lib.rawgetlong(pback, 0) == 78927812
     assert lib.rawgetlong(p, 0) == 927122
+    assert classify(p) == "private"
+    assert classify(pback) == "backup"
 
 def test_protected_with_backup():
-    xxx
+    p = nalloc(HDR + WORD)
+    lib.setlong(p, 0, 78927812)
+    lib.stm_commit_transaction()
+    lib.stm_begin_inevitable_transaction()
+    lib.setlong(p, 0, 927122)
+    pback = lib.stm_get_backup_copy(p)
+    assert pback != p
+    assert p.h_revision == lib.get_private_rev_num()
+    lib.stm_commit_transaction()
+    lib.stm_begin_inevitable_transaction()
+    assert lib.stm_get_backup_copy(p) == ffi.NULL
+    assert classify(p) == "protected"
+    assert classify(pback) == "backup"
+    assert ffi.cast("revision_t *", p.h_revision) == pback
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to