Author: Armin Rigo <[email protected]>
Branch:
Changeset: r88:38cc005153e5
Date: 2013-06-09 22:23 +0200
http://bitbucket.org/pypy/stmgc/changeset/38cc005153e5/
Log: progress
diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -30,6 +30,11 @@
{
return thread_descriptor;
}
+static int is_private(gcptr P)
+{
+ return (P->h_revision == stm_private_rev_num) ||
+ (P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED);
+}
/************************************************************/
@@ -119,6 +124,7 @@
if (P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE)
{
wlog_t *item;
+ retry_public_to_private:;
G2L_FIND(d->public_to_private, P, item, goto no_private_obj);
P = item->val;
@@ -126,8 +132,14 @@
assert(P->h_revision == stm_private_rev_num);
fprintf(stderr, "read_barrier: %p -> %p public_to_private\n", G, P);
return P;
+
+ no_private_obj:
+ if (d->public_descriptor->stolen_objects.size > 0)
+ {
+ stm_normalize_stolen_objects(d);
+ goto retry_public_to_private;
+ }
}
- no_private_obj:
if (UNLIKELY(v > d->start_time)) // object too recent?
{
@@ -188,7 +200,7 @@
else
{
/* stealing */
- fprintf(stderr, "read_barrier: %p -> stealing %p...", G, P);
+ fprintf(stderr, "read_barrier: %p -> stealing %p...\n ", G, P);
stm_steal_stub(P);
goto retry;
}
@@ -378,8 +390,7 @@
R = stm_read_barrier(P);
- if (R->h_revision == stm_private_rev_num ||
- (R->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED))
+ if (is_private(R))
return R;
if (R->h_tid & GCFLAG_PUBLIC)
@@ -419,11 +430,14 @@
static _Bool ValidateDuringTransaction(struct tx_descriptor *d,
_Bool during_commit)
{
- abort();
-#if 0
long i, size = d->list_of_read_objects.size;
gcptr *items = d->list_of_read_objects.items;
+ if (size == 0)
+ return 1;
+ abort();
+
+#if 0
for (i=0; i<size; i++)
{
gcptr R = items[i];
@@ -636,6 +650,7 @@
assert(d->list_of_read_objects.size == 0);
assert(d->private_from_protected.size == 0);
assert(!g2l_any_entry(&d->public_to_private));
+ assert(d->public_descriptor->stolen_objects.size == 0);
d->count_reads = 1;
fxcache_clear(&d->recent_reads_cache);
@@ -668,7 +683,7 @@
gcptr R = item->addr;
revision_t v;
retry:
- assert(R->h_tid & GCFLAG_OLD);
+ assert(R->h_tid & GCFLAG_PUBLIC);
v = ACCESS_ONCE(R->h_revision);
if (!(v & 1)) // "is a pointer", i.e.
{ // "has a more recent revision"
@@ -861,6 +876,9 @@
struct tx_descriptor *d = thread_descriptor;
assert(d->active >= 1);
+ if (d->public_descriptor->stolen_objects.size != 0)
+ stm_normalize_stolen_objects(d);
+
spinlock_acquire(d->public_descriptor->collection_lock, 'C'); /*committing*/
AcquireLocks(d);
@@ -918,7 +936,7 @@
assert(newrev & 1);
ACCESS_ONCE(stm_private_rev_num) = newrev;
fprintf(stderr, "%p: stm_local_revision = %ld\n", d, (long)newrev);
- assert(d->public_descriptor->private_revision_ref = &stm_private_rev_num);
+ assert(d->private_revision_ref = &stm_private_rev_num);
UpdateChainHeads(d, cur_time, localrev);
@@ -1136,8 +1154,9 @@
assert(d->my_lock & 1);
assert(d->my_lock >= LOCKED);
stm_private_rev_num = -1;
- pd->private_revision_ref = &stm_private_rev_num;
+ d->private_revision_ref = &stm_private_rev_num;
d->max_aborts = -1;
+ pd->descriptor = d;
thread_descriptor = d;
fprintf(stderr, "[%lx] pthread %lx starting\n",
@@ -1152,15 +1171,12 @@
void DescriptorDone(void)
{
- static revision_t no_private_revision = 8;
revision_t i;
struct tx_descriptor *d = thread_descriptor;
assert(d != NULL);
assert(d->active == 0);
-
- spinlock_acquire(d->public_descriptor->collection_lock, 'D'); /*done*/
- d->public_descriptor->private_revision_ref = &no_private_revision;
- spinlock_release(d->public_descriptor->collection_lock);
+ assert(d->public_descriptor->stolen_objects.size == 0);
+ gcptrlist_delete(&d->public_descriptor->stolen_objects);
spinlock_acquire(descriptor_array_lock, 1);
i = d->public_descriptor_index;
diff --git a/c4/et.h b/c4/et.h
--- a/c4/et.h
+++ b/c4/et.h
@@ -105,9 +105,10 @@
* thread shuts down. It is reused the next time a thread starts. */
struct tx_public_descriptor {
revision_t collection_lock;
+ struct tx_descriptor *descriptor;
struct stub_block_s *stub_blocks;
gcptr stub_free_list;
- revision_t *private_revision_ref;
+ struct GcPtrList stolen_objects;
revision_t free_list_next;
/* xxx gcpage data here */
};
@@ -140,6 +141,7 @@
struct G2L public_to_private;
char *longest_abort_info;
long long longest_abort_info_time;
+ revision_t *private_revision_ref;
struct FXCache recent_reads_cache;
};
diff --git a/c4/steal.c b/c4/steal.c
--- a/c4/steal.c
+++ b/c4/steal.c
@@ -56,8 +56,16 @@
gcptr L = (gcptr)(v - 2);
if (L->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED) {
- L = (gcptr)L->h_revision; /* the backup copy */
- L->h_tid &= ~GCFLAG_BACKUP_COPY;
+ gcptr B = (gcptr)L->h_revision; /* the backup copy */
+ B->h_tid &= ~GCFLAG_BACKUP_COPY;
+ L->h_revision = *foreign_pd->descriptor->private_revision_ref;
+
+ /* add {B: L} in 'public_to_private', but lazily, because we don't
+ want to walk over the feet of the foreign thread */
+ B->h_tid |= GCFLAG_PUBLIC_TO_PRIVATE;
+ gcptrlist_insert2(&foreign_pd->stolen_objects, B, L);
+
+ L = B;
}
/* change L from protected to public */
@@ -72,3 +80,20 @@
done:
spinlock_release(foreign_pd->collection_lock);
}
+
+void stm_normalize_stolen_objects(struct tx_descriptor *d)
+{
+ spinlock_acquire(d->public_descriptor->collection_lock, 'N');
+
+ long i, size = d->public_descriptor->stolen_objects.size;
+ gcptr *items = d->public_descriptor->stolen_objects.items;
+
+ for (i = 0; i < size; i += 2) {
+ gcptr B = items[i];
+ gcptr L = items[i + 1];
+ g2l_insert(&d->public_to_private, B, L);
+ }
+ gcptrlist_clear(&d->public_descriptor->stolen_objects);
+
+ spinlock_release(d->public_descriptor->collection_lock);
+}
diff --git a/c4/steal.h b/c4/steal.h
--- a/c4/steal.h
+++ b/c4/steal.h
@@ -10,7 +10,7 @@
gcptr stm_stub_malloc(struct tx_public_descriptor *);
void stm_steal_stub(gcptr);
gcptr stm_get_stolen_obj(long index); /* debugging */
-void stm_normalize_stolen_objects(struct tx_public_descriptor *);
+void stm_normalize_stolen_objects(struct tx_descriptor *);
#endif
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
@@ -229,7 +229,6 @@
run_parallel(f1, f2)
def test_stealing_while_modifying():
- py.test.skip("in-progress")
p = palloc(HDR + WORD)
def f1(r):
@@ -258,6 +257,7 @@
assert pback.h_tid & GCFLAG_PUBLIC_TO_PRIVATE
assert lib.stm_read_barrier(p) == p1
assert lib.stm_read_barrier(p1) == p1
+ assert lib.stm_read_barrier(pback) == p1
assert pback.h_revision & 1
perform_transaction(cb)
@@ -273,6 +273,8 @@
def cb(c):
assert c == 0
r.enter_in_parallel()
+ lib.stm_commit_transaction()
+ lib.stm_begin_inevitable_transaction()
p2 = lib.stm_read_barrier(p) # steals
assert lib.rawgetlong(p2, 0) == 2782172
assert p2 == lib.stm_read_barrier(p)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit