Author: Armin Rigo <[email protected]>
Branch:
Changeset: r472:b7b44751111b
Date: 2013-08-03 14:11 +0200
http://bitbucket.org/pypy/stmgc/changeset/b7b44751111b/
Log: stm_immut_read_barrier()
diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -318,6 +318,41 @@
return P;
}
+gcptr stm_ImmutReadBarrier(gcptr P)
+{
+ assert(P->h_tid & GCFLAG_STUB);
+ assert(P->h_tid & GCFLAG_PUBLIC);
+
+ revision_t v = ACCESS_ONCE(P->h_revision);
+ assert(IS_POINTER(v)); /* "is a pointer", "has a more recent revision" */
+
+ if (!(v & 2))
+ {
+ P = (gcptr)v;
+ }
+ else
+ {
+ /* follow a stub reference */
+ struct tx_descriptor *d = thread_descriptor;
+ struct tx_public_descriptor *foreign_pd = STUB_THREAD(P);
+ if (foreign_pd == d->public_descriptor)
+ {
+ /* Same thread: dereference the pointer directly. */
+ dprintf(("immut_read_barrier: %p -> %p via stub\n ", P,
+ (gcptr)(v - 2)));
+ P = (gcptr)(v - 2);
+ }
+ else
+ {
+ /* stealing: needed because accessing v - 2 from this thread
+ is forbidden (the target might disappear under our feet) */
+ dprintf(("immut_read_barrier: %p -> stealing...\n ", P));
+ stm_steal_stub(P);
+ }
+ }
+ return stm_immut_read_barrier(P); /* retry */
+}
+
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
@@ -73,7 +73,7 @@
// in stmgc.h: GCFLAG_WRITE_BARRIER = STM_FIRST_GCFLAG << 5;
// in stmgc.h: GCFLAG_MOVED = STM_FIRST_GCFLAG << 6;
static const revision_t GCFLAG_BACKUP_COPY /*debug*/ = STM_FIRST_GCFLAG << 7;
-static const revision_t GCFLAG_STUB /*debug*/ = STM_FIRST_GCFLAG << 8;
+// in stmgc.h: GCFLAG_STUB = STM_FIRST_GCFLAG << 8;
static const revision_t GCFLAG_PRIVATE_FROM_PROTECTED = STM_FIRST_GCFLAG << 9;
static const revision_t GCFLAG_HAS_ID = STM_FIRST_GCFLAG << 10;
static const revision_t GCFLAG_IMMUTABLE = STM_FIRST_GCFLAG << 11;
@@ -195,8 +195,9 @@
void SpinLoop(int);
gcptr stm_DirectReadBarrier(gcptr);
+gcptr stm_WriteBarrier(gcptr);
gcptr stm_RepeatReadBarrier(gcptr);
-gcptr stm_WriteBarrier(gcptr);
+gcptr stm_ImmutReadBarrier(gcptr);
gcptr _stm_nonrecord_barrier(gcptr); /* debugging: read barrier, but
not recording anything */
int _stm_is_private(gcptr); /* debugging */
diff --git a/c4/stmgc.h b/c4/stmgc.h
--- a/c4/stmgc.h
+++ b/c4/stmgc.h
@@ -75,11 +75,16 @@
The only thing that may have occurred is that a
stm_write_barrier() on the same object could have made it
invalid.
+
+ - a different optimization is to read immutable fields: in order
+ to do that, use stm_immut_read_barrier(), which only activates
+ on stubs.
*/
#if 0 // (optimized version below)
gcptr stm_read_barrier(gcptr);
gcptr stm_write_barrier(gcptr);
gcptr stm_repeat_read_barrier(gcptr);
+gcptr stm_immut_read_barrier(gcptr);
#endif
/* start a new transaction, calls callback(), and when it returns
@@ -169,6 +174,7 @@
static const revision_t GCFLAG_PUBLIC_TO_PRIVATE = STM_FIRST_GCFLAG << 4;
static const revision_t GCFLAG_WRITE_BARRIER = STM_FIRST_GCFLAG << 5;
static const revision_t GCFLAG_MOVED = STM_FIRST_GCFLAG << 6;
+static const revision_t GCFLAG_STUB = STM_FIRST_GCFLAG << 8;
extern __thread char *stm_read_barrier_cache;
#define FX_MASK 65535
#define FXCACHE_AT(obj) \
@@ -193,5 +199,10 @@
stm_RepeatReadBarrier(obj) \
: (obj))
+#define stm_immut_read_barrier(obj) \
+ (UNLIKELY((obj)->h_tid & GCFLAG_STUB) ? \
+ stm_ImmutReadBarrier(obj) \
+ : (obj))
+
#endif
diff --git a/c4/test/support.py b/c4/test/support.py
--- a/c4/test/support.py
+++ b/c4/test/support.py
@@ -58,6 +58,7 @@
gcptr stm_read_barrier(gcptr);
gcptr stm_write_barrier(gcptr);
gcptr stm_repeat_read_barrier(gcptr);
+ gcptr stm_immut_read_barrier(gcptr);
void stm_perform_transaction(gcptr arg, int (*callback)(gcptr, int));
void stm_commit_transaction(void);
void stm_begin_inevitable_transaction(void);
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
@@ -729,3 +729,19 @@
assert q != p
assert lib.stm_repeat_read_barrier(q) == q
assert lib.stm_repeat_read_barrier(p) == q
+
+def test_immut_read_barrier():
+ p = palloc(HDR + WORD)
+ p2 = lib.stm_write_barrier(p)
+ lib.stm_commit_transaction()
+ lib.stm_begin_inevitable_transaction()
+ assert classify(p) == "public"
+ assert classify(p2) == "protected"
+ pstub = ffi.cast("gcptr", p.h_revision)
+ assert classify(pstub) == "stub"
+ assert lib.stm_immut_read_barrier(p) == p
+ assert lib.stm_immut_read_barrier(pstub) == p2
+ assert lib.stm_immut_read_barrier(p2) == p2
+ assert lib.stm_read_barrier(p2) == p2
+ assert lib.stm_read_barrier(pstub) == p2
+ assert lib.stm_read_barrier(p) == p2
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit