Author: Armin Rigo <[email protected]>
Branch:
Changeset: r471:b57de4359eea
Date: 2013-08-03 10:02 +0200
http://bitbucket.org/pypy/stmgc/changeset/b57de4359eea/
Log: Implement the repeat read barrier (actually mostly just expose it to
the user, with a fast-path logic).
diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -276,28 +276,45 @@
/* 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().
+ * meantime a stm_write_barrier(). Should only be called if we
+ * have the flag PUBLIC_TO_PRIVATE or on MOVED objects. This version
+ * should never abort (it is used in stm_decode_abort_info()).
*/
- if (P->h_tid & GCFLAG_PUBLIC)
+ assert(P->h_tid & GCFLAG_PUBLIC);
+ assert(!(P->h_tid & GCFLAG_STUB));
+
+ if (P->h_tid & GCFLAG_MOVED)
{
- if (P->h_tid & GCFLAG_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);
+ dprintf(("repeat_read_barrier: %p -> %p moved\n", P,
+ (gcptr)P->h_revision));
+ P = (gcptr)P->h_revision;
+ assert(P->h_tid & GCFLAG_PUBLIC);
+ assert(!(P->h_tid & GCFLAG_STUB));
+ assert(!(P->h_tid & GCFLAG_MOVED));
+ if (!(P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE))
+ return P;
+ }
+ assert(P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE);
- P = item->val;
- assert(!(P->h_tid & GCFLAG_PUBLIC));
- no_private_obj:
- ;
- }
- }
+ struct tx_descriptor *d = thread_descriptor;
+ wlog_t *item;
+ G2L_FIND(d->public_to_private, P, item, goto no_private_obj);
+
+ /* We have a key in 'public_to_private'. The value is the
+ corresponding private object. */
+ dprintf(("repeat_read_barrier: %p -> %p public_to_private\n", P, item->val));
+ P = item->val;
+ assert(!(P->h_tid & GCFLAG_PUBLIC));
assert(!(P->h_tid & GCFLAG_STUB));
+ assert(is_private(P));
+ return P;
+
+ no_private_obj:
+ /* Key not found. It should not be waiting in 'stolen_objects',
+ because this case from steal.c applies to objects to were originally
+ backup objects. 'P' cannot be a backup object if it was obtained
+ earlier as a result of stm_read_barrier().
+ */
return P;
}
diff --git a/c4/et.h b/c4/et.h
--- a/c4/et.h
+++ b/c4/et.h
@@ -69,9 +69,9 @@
static const revision_t GCFLAG_VISITED = STM_FIRST_GCFLAG << 1;
static const revision_t GCFLAG_PUBLIC = STM_FIRST_GCFLAG << 2;
static const revision_t GCFLAG_PREBUILT_ORIGINAL = STM_FIRST_GCFLAG << 3;
-static const revision_t GCFLAG_PUBLIC_TO_PRIVATE = STM_FIRST_GCFLAG << 4;
+// in stmgc.h: GCFLAG_PUBLIC_TO_PRIVATE = STM_FIRST_GCFLAG << 4;
// in stmgc.h: GCFLAG_WRITE_BARRIER = STM_FIRST_GCFLAG << 5;
-static const revision_t GCFLAG_MOVED = STM_FIRST_GCFLAG << 6;
+// 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;
static const revision_t GCFLAG_PRIVATE_FROM_PROTECTED = STM_FIRST_GCFLAG << 9;
diff --git a/c4/extra.c b/c4/extra.c
--- a/c4/extra.c
+++ b/c4/extra.c
@@ -204,7 +204,7 @@
WRITE_BUF(buffer, res_size);
WRITE('e');
for (i=0; i<d->abortinfo.size; i+=2) {
- char *object = (char *)stm_RepeatReadBarrier(d->abortinfo.items[i+0]);
+ char *object = (char*)stm_repeat_read_barrier(d->abortinfo.items[i+0]);
long *fieldoffsets = (long*)d->abortinfo.items[i+1];
long kind, offset;
size_t rps_size;
diff --git a/c4/stmgc.h b/c4/stmgc.h
--- a/c4/stmgc.h
+++ b/c4/stmgc.h
@@ -58,7 +58,7 @@
int stm_enter_callback_call(void);
void stm_leave_callback_call(int);
-/* read/write barriers (the most general versions only for now).
+/* read/write barriers.
- the read barrier must be applied before reading from an object.
the result is valid as long as we're in the same transaction,
@@ -68,10 +68,18 @@
the result is valid for a shorter period of time: we have to
do stm_write_barrier() again if we ended the transaction, or
if we did a potential collection (e.g. stm_allocate()).
+
+ - as an optimization, stm_repeat_read_barrier() can be used
+ instead of stm_read_barrier() if the object was already
+ obtained by a stm_read_barrier() in the same transaction.
+ The only thing that may have occurred is that a
+ stm_write_barrier() on the same object could have made it
+ invalid.
*/
#if 0 // (optimized version below)
gcptr stm_read_barrier(gcptr);
gcptr stm_write_barrier(gcptr);
+gcptr stm_repeat_read_barrier(gcptr);
#endif
/* start a new transaction, calls callback(), and when it returns
@@ -158,7 +166,9 @@
extern __thread revision_t stm_private_rev_num;
gcptr stm_DirectReadBarrier(gcptr);
gcptr stm_WriteBarrier(gcptr);
+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;
extern __thread char *stm_read_barrier_cache;
#define FX_MASK 65535
#define FXCACHE_AT(obj) \
@@ -178,5 +188,10 @@
stm_WriteBarrier(obj) \
: (obj))
+#define stm_repeat_read_barrier(obj) \
+ (UNLIKELY((obj)->h_tid & (GCFLAG_PUBLIC_TO_PRIVATE | GCFLAG_MOVED)) ? \
+ stm_RepeatReadBarrier(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
@@ -57,6 +57,7 @@
int stm_in_transaction(void);
gcptr stm_read_barrier(gcptr);
gcptr stm_write_barrier(gcptr);
+ gcptr stm_repeat_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
@@ -713,3 +713,19 @@
assert x == 1
lib.stm_leave_callback_call(x)
lib.stm_initialize_tests(0)
+
+def test_repeat_read_barrier():
+ p = nalloc(HDR + WORD)
+ assert lib.stm_repeat_read_barrier(p) == p
+ lib.stm_commit_transaction()
+ lib.stm_begin_inevitable_transaction()
+ assert lib.stm_repeat_read_barrier(p) == p
+ #
+ p = palloc(HDR + WORD)
+ assert classify(p) == "public"
+ assert lib.stm_read_barrier(p) == p
+ q = lib.stm_write_barrier(p)
+ assert classify(q) == "private"
+ assert q != p
+ assert lib.stm_repeat_read_barrier(q) == q
+ assert lib.stm_repeat_read_barrier(p) == q
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit