[pypy-commit] stmgc default: Read the latest version of an object inside the aborting transaction.

arigo noreply at buildbot.pypy.org
Sat Jul 6 18:52:35 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r361:15dbb73844ab
Date: 2013-07-06 15:38 +0200
http://bitbucket.org/pypy/stmgc/changeset/15dbb73844ab/

Log:	Read the latest version of an object inside the aborting
	transaction.

diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -248,6 +248,36 @@
     }
 }
 
+gcptr stm_RepeatReadBarrier(gcptr P)
+{
+  /* Version of stm_DirectReadBarrier() that doesn't abort and assumes
+   * that 'P' was already an up-to-date result of a previous
+   * stm_DirectReadBarrier().  We only have to check if we did in the
+   * meantime a stm_write_barrier().
+   */
+  if (P->h_tid & GCFLAG_PUBLIC)
+    {
+      if (P->h_tid & GCFLAG_NURSERY_MOVED)
+        {
+          P = (gcptr)P->h_revision;
+          assert(P->h_tid & GCFLAG_PUBLIC);
+        }
+      if (P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE)
+        {
+          struct tx_descriptor *d = thread_descriptor;
+          wlog_t *item;
+          G2L_FIND(d->public_to_private, P, item, goto no_private_obj);
+
+          P = item->val;
+          assert(!(P->h_tid & GCFLAG_PUBLIC));
+        no_private_obj:
+          ;
+        }
+    }
+  assert(!(P->h_tid & GCFLAG_STUB));
+  return P;
+}
+
 static gcptr _match_public_to_private(gcptr P, gcptr pubobj, gcptr privobj,
                                       int from_stolen)
 {
diff --git a/c4/et.h b/c4/et.h
--- a/c4/et.h
+++ b/c4/et.h
@@ -181,6 +181,7 @@
 void SpinLoop(int);
 
 gcptr stm_DirectReadBarrier(gcptr);
+gcptr stm_RepeatReadBarrier(gcptr);
 gcptr stm_WriteBarrier(gcptr);
 gcptr _stm_nonrecord_barrier(gcptr);  /* debugging: read barrier, but
                                          not recording anything */
diff --git a/c4/extra.c b/c4/extra.c
--- a/c4/extra.c
+++ b/c4/extra.c
@@ -143,6 +143,7 @@
 void stm_abort_info_push(gcptr obj, long fieldoffsets[])
 {
     struct tx_descriptor *d = thread_descriptor;
+    obj = stm_read_barrier(obj);
     gcptrlist_insert2(&d->abortinfo, obj, (gcptr)fieldoffsets);
 }
 
@@ -188,7 +189,7 @@
     WRITE_BUF(buffer, res_size);
     WRITE('e');
     for (i=0; i<d->abortinfo.size; i+=2) {
-        char *object = (char *)d->abortinfo.items[i+0];
+        char *object = (char *)stm_RepeatReadBarrier(d->abortinfo.items[i+0]);
         long *fieldoffsets = (long*)d->abortinfo.items[i+1];
         long kind, offset;
         size_t rps_size;
diff --git a/c4/test/test_extra.py b/c4/test/test_extra.py
--- a/c4/test/test_extra.py
+++ b/c4/test/test_extra.py
@@ -87,3 +87,19 @@
             c = lib.stm_inspect_abort_info()
             assert c
             assert ffi.string(c).endswith("e0:e")
+
+def test_latest_version():
+    fo1 = ffi.new("long[]", [1, HDR, 0])
+    p = palloc(HDR + WORD)
+    lib.rawsetlong(p, 0, -9827892)
+    #
+    @perform_transaction
+    def run(retry_counter):
+        if retry_counter == 0:
+            lib.stm_abort_info_push(p, fo1)
+            lib.setlong(p, 0, 424242)
+            abort_and_retry()
+        else:
+            c = lib.stm_inspect_abort_info()
+            assert c
+            assert ffi.string(c).endswith("ei424242ee")


More information about the pypy-commit mailing list