[pypy-commit] stmgc default: Read barrier on public objects
arigo
noreply at buildbot.pypy.org
Wed Jun 5 18:23:08 CEST 2013
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r72:b9dfe1e2b66e
Date: 2013-06-05 18:22 +0200
http://bitbucket.org/pypy/stmgc/changeset/b9dfe1e2b66e/
Log: Read barrier on public objects
diff --git a/c3/et.c b/c3/et.c
--- a/c3/et.c
+++ b/c3/et.c
@@ -65,78 +65,6 @@
/************************************************************/
-static gcptr HeadOfRevisionChainList(struct tx_descriptor *d, gcptr G)
-{
- abort();
-#if 0
- gcptr R = G;
- revision_t v;
-
- retry:
- v = ACCESS_ONCE(R->h_revision);
- if (!(v & 1)) // "is a pointer", i.e.
- { // "has a more recent revision"
- if (v & 2)
- {
- old_to_young:
- v &= ~2;
- if (UNLIKELY(!stmgc_is_young_in(d, (gcptr)v)))
- {
- stmgc_public_to_foreign_protected(R);
- goto retry;
- }
- R = (gcptr)v;
- goto retry;
- }
-
- gcptr R_prev = R;
- R = (gcptr)v;
-
- retry_threelevels:
- v = ACCESS_ONCE(R->h_revision);
- if (!(v & 1)) // "is a pointer", i.e.
- { // "has a more recent revision"
- if (v & 2)
- goto old_to_young;
-
- /* we update R_prev->h_revision as a shortcut */
- /* XXX check if this really gives a worse performance than only
- doing this write occasionally based on a counter in d */
- gcptr R_next = (gcptr)v;
- if (R_next->h_revision == stm_local_revision)
- {
- /* must not update an older h_revision to go directly to
- the private copy at the end of a chain of protected
- objects! */
- return R_next;
- }
- if (R_prev->h_tid & GCFLAG_STOLEN)
- {
- /* must not update the h_revision of a stolen object! */
- R_prev = R;
- R = R_next;
- goto retry_threelevels;
- }
- R_prev->h_revision = v;
- R = R_next;
- goto retry;
- }
- }
-
- if (UNLIKELY(v > d->start_time)) // object too recent?
- {
- if (v >= LOCKED)
- {
- SpinLoop(SPLP_LOCKED_INFLIGHT);
- goto retry; // spinloop until it is no longer LOCKED
- }
- ValidateNow(d); // try to move start_time forward
- goto retry; // restart searching from R
- }
- return R;
-#endif
-}
-
#if 0
static inline gcptr AddInReadSet(struct tx_descriptor *d, gcptr R)
{
@@ -163,12 +91,57 @@
if (P->h_tid & GCFLAG_PUBLIC)
{
- abort();
- /*...*/
+ /* follow the chained list of h_revision's as long as they are
+ regular pointers */
+ revision_t v;
+
+ retry:
+ v = ACCESS_ONCE(P->h_revision);
+ if (!(v & 1)) // "is a pointer", i.e.
+ { // "has a more recent revision"
+ if (v & 2)
+ {
+ old_to_young:
+ abort();
+ }
+ assert(P->h_tid & GCFLAG_PUBLIC);
+
+ gcptr P_prev = P;
+ P = (gcptr)v;
+
+ /* if we land on a P in read_barrier_cache: just return it */
+ if (FXCACHE_AT(P) == P)
+ return P;
+
+ v = ACCESS_ONCE(P->h_revision);
+ if (!(v & 1)) // "is a pointer", i.e.
+ { // "has a more recent revision"
+ if (v & 2)
+ goto old_to_young;
+ assert(P->h_tid & GCFLAG_PUBLIC);
+
+ /* we update P_prev->h_revision as a shortcut */
+ /* XXX check if this really gives a worse performance than only
+ doing this write occasionally based on a counter in d */
+ P_prev->h_revision = v;
+ P = (gcptr)v;
+ goto retry;
+ }
+ }
+
+ if (UNLIKELY(v > d->start_time)) // object too recent?
+ {
+ if (v >= LOCKED)
+ {
+ SpinLoop(SPLP_LOCKED_INFLIGHT);
+ goto retry; // spinloop until it is no longer LOCKED
+ }
+ ValidateNow(d); // try to move start_time forward
+ goto retry; // restart searching from P
+ }
}
-
+ fxcache_add(&d->recent_reads_cache, P);
gcptrlist_insert(&d->list_of_read_objects, P);
- fxcache_add(&d->recent_reads_cache, P);
return P;
}
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
@@ -156,3 +156,25 @@
assert list_of_read_objects() == []
assert lib.stm_read_barrier(p) == p # record as a read object
assert list_of_read_objects() == [p]
+
+def test_read_barrier_public():
+ p = palloc(HDR)
+ assert lib.stm_read_barrier(p) == p
+ assert list_of_read_objects() == [p]
+
+def test_read_barrier_public_outdated():
+ p1 = palloc(HDR)
+ p2 = palloc(HDR)
+ p1.h_revision = ffi.cast("revision_t", p2)
+ assert lib.stm_read_barrier(p1) == p2
+ assert list_of_read_objects() == [p2]
+
+def test_read_barrier_public_shortcut():
+ p1 = palloc(HDR)
+ p2 = palloc(HDR)
+ p3 = palloc(HDR)
+ p1.h_revision = ffi.cast("revision_t", p2)
+ p2.h_revision = ffi.cast("revision_t", p3)
+ assert lib.stm_read_barrier(p1) == p3
+ assert list_of_read_objects() == [p3]
+ assert p1.h_revision == int(ffi.cast("revision_t", p3)) # shortcutted
More information about the pypy-commit
mailing list