[pypy-commit] pypy stmgc-c4: import stmgc/bf56c12295c8
arigo
noreply at buildbot.pypy.org
Mon Jul 1 15:14:01 CEST 2013
Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c4
Changeset: r65135:12aa03d05cb3
Date: 2013-07-01 15:12 +0200
http://bitbucket.org/pypy/pypy/changeset/12aa03d05cb3/
Log: import stmgc/bf56c12295c8
diff --git a/rpython/translator/stm/src_stm/et.c b/rpython/translator/stm/src_stm/et.c
--- a/rpython/translator/stm/src_stm/et.c
+++ b/rpython/translator/stm/src_stm/et.c
@@ -765,20 +765,24 @@
long long elapsed_time;
/* acquire the lock, but don't double-acquire it if already committing */
- if (d->public_descriptor->collection_lock != 'C') {
- spinlock_acquire(d->public_descriptor->collection_lock, 'C');
- if (d->public_descriptor->stolen_objects.size != 0)
- stm_normalize_stolen_objects(d);
- }
-
+ if (d->public_descriptor->collection_lock != 'C')
+ {
+ spinlock_acquire(d->public_descriptor->collection_lock, 'C');
+ if (d->public_descriptor->stolen_objects.size != 0)
+ stm_normalize_stolen_objects(d);
+ assert(!stm_has_got_any_lock(d));
+ }
+ else
+ {
+ CancelLocks(d);
+ assert(!stm_has_got_any_lock(d));
+ }
assert(d->active != 0);
assert(!is_inevitable(d));
assert(num < ABORT_REASONS);
d->num_aborts[num]++;
- CancelLocks(d);
-
/* compute the elapsed time */
if (d->start_real_time.tv_nsec != -1 &&
clock_gettime(CLOCK_MONOTONIC, &now) >= 0) {
@@ -907,6 +911,8 @@
long stm_atomic(long delta)
{
struct tx_descriptor *d = thread_descriptor;
+ if (delta) // no atomic-checks
+ dprintf(("stm_atomic(%lu)\n", delta));
d->atomic += delta;
assert(d->atomic >= 0);
update_reads_size_limit(d);
@@ -953,6 +959,7 @@
revision_t my_lock = d->my_lock;
wlog_t *item;
+ assert(!stm_has_got_any_lock(d));
assert(d->public_descriptor->stolen_objects.size == 0);
if (!g2l_any_entry(&d->public_to_private))
@@ -1031,6 +1038,46 @@
} G2L_LOOP_END;
}
+_Bool stm_has_got_any_lock(struct tx_descriptor *d)
+{
+ wlog_t *item;
+ int found_locked, found_unlocked;
+
+ if (!g2l_any_entry(&d->public_to_private))
+ return 0;
+
+ found_locked = 0;
+ found_unlocked = 0;
+
+ G2L_LOOP_FORWARD(d->public_to_private, item)
+ {
+ gcptr R = item->addr;
+ gcptr L = item->val;
+ if (L == NULL)
+ continue;
+
+ revision_t expected, v = L->h_revision;
+
+ if (L->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED)
+ expected = (revision_t)R;
+ else
+ expected = *d->private_revision_ref;
+
+ if (v == expected)
+ {
+ assert(R->h_revision != d->my_lock);
+ found_unlocked = 1;
+ continue;
+ }
+
+ found_locked = 1;
+ assert(found_unlocked == 0); /* an unlocked followed by a locked: no */
+
+ } G2L_LOOP_END;
+
+ return found_locked;
+}
+
static pthread_mutex_t mutex_prebuilt_gcroots = PTHREAD_MUTEX_INITIALIZER;
static void UpdateChainHeads(struct tx_descriptor *d, revision_t cur_time,
@@ -1505,7 +1552,6 @@
revision_t i;
struct tx_descriptor *d = stm_malloc(sizeof(struct tx_descriptor));
memset(d, 0, sizeof(struct tx_descriptor));
- stmgcpage_acquire_global_lock();
struct tx_public_descriptor *pd;
i = descriptor_array_free_list;
@@ -1555,7 +1601,6 @@
(long)d->public_descriptor_index, (long)pthread_self()));
stmgcpage_init_tls();
- stmgcpage_release_global_lock();
return 1;
}
else
@@ -1568,7 +1613,6 @@
struct tx_descriptor *d = thread_descriptor;
assert(d != NULL);
assert(d->active == 0);
- stmgcpage_acquire_global_lock();
/* our nursery is empty at this point. The list 'stolen_objects'
should have been emptied at the previous minor collection and
@@ -1586,7 +1630,6 @@
if (d->tx_prev != NULL) d->tx_prev->tx_next = d->tx_next;
if (d->tx_next != NULL) d->tx_next->tx_prev = d->tx_prev;
if (d == stm_tx_head) stm_tx_head = d->tx_next;
- stmgcpage_release_global_lock();
thread_descriptor = NULL;
diff --git a/rpython/translator/stm/src_stm/et.h b/rpython/translator/stm/src_stm/et.h
--- a/rpython/translator/stm/src_stm/et.h
+++ b/rpython/translator/stm/src_stm/et.h
@@ -191,6 +191,7 @@
gcptr stm_get_read_obj(long); /* debugging */
void stm_clear_read_cache(void); /* debugging */
void _stm_test_forget_previous_state(void); /* debugging */
+_Bool stm_has_got_any_lock(struct tx_descriptor *);
struct tx_public_descriptor *stm_get_free_public_descriptor(revision_t *);
int DescriptorInit(void);
diff --git a/rpython/translator/stm/src_stm/gcpage.c b/rpython/translator/stm/src_stm/gcpage.c
--- a/rpython/translator/stm/src_stm/gcpage.c
+++ b/rpython/translator/stm/src_stm/gcpage.c
@@ -220,17 +220,14 @@
return;
restart:
- if (obj->h_tid & GCFLAG_VISITED) {
- dprintf(("[already visited: %p]\n", obj));
- assert(obj == *pobj);
- assert((obj->h_revision & 3) || /* either odd, or stub */
- (obj->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
- return; /* already seen */
- }
-
if (obj->h_revision & 1) {
assert(!(obj->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
- obj->h_tid &= ~GCFLAG_PUBLIC_TO_PRIVATE; /* see also fix_outdated() */
+ assert(!(obj->h_tid & GCFLAG_STUB));
+ if (!(obj->h_tid & GCFLAG_VISITED)) {
+ obj->h_tid &= ~GCFLAG_PUBLIC_TO_PRIVATE; /* see fix_outdated() */
+ obj->h_tid |= GCFLAG_VISITED;
+ gcptrlist_insert(&objects_to_trace, obj);
+ }
}
else if (obj->h_tid & GCFLAG_PUBLIC) {
/* h_revision is a ptr: we have a more recent version */
@@ -267,27 +264,48 @@
*pobj = obj;
goto restart;
}
+ else if (obj->h_tid & GCFLAG_VISITED) {
+ dprintf(("[already visited: %p]\n", obj));
+ assert(obj == *pobj);
+ assert((obj->h_revision & 3) || /* either odd, or stub */
+ (obj->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
+ return; /* already seen */
+ }
else {
assert(obj->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED);
gcptr B = (gcptr)obj->h_revision;
- gcptrlist_insert(&objects_to_trace, B);
+ assert(B->h_tid & (GCFLAG_PUBLIC | GCFLAG_BACKUP_COPY));
- if (!(B->h_tid & GCFLAG_PUBLIC)) {
- /* a regular private_from_protected object with a backup copy B */
- assert(B->h_tid & GCFLAG_BACKUP_COPY);
- assert(B->h_revision & 1);
- B->h_tid |= GCFLAG_VISITED;
- }
- else {
- /* a private_from_protected with a stolen backup copy B */
+ obj->h_tid |= GCFLAG_VISITED;
+ B->h_tid |= GCFLAG_VISITED;
+ assert(!(obj->h_tid & GCFLAG_STUB));
+ assert(!(B->h_tid & GCFLAG_STUB));
+ gcptrlist_insert2(&objects_to_trace, obj, B);
+
+ if (IS_POINTER(B->h_revision)) {
+ assert(B->h_tid & GCFLAG_PUBLIC);
assert(!(B->h_tid & GCFLAG_BACKUP_COPY));
- gcptr obj1 = B;
- visit(&obj1); /* xxx recursion? */
- obj->h_revision = (revision_t)obj1;
+ assert(!(B->h_revision & 2));
+
+ pobj = (gcptr *)&B->h_revision;
+ obj = *pobj;
+ goto restart;
}
}
- obj->h_tid |= GCFLAG_VISITED;
- gcptrlist_insert(&objects_to_trace, obj);
+}
+
+static void visit_keep(gcptr obj)
+{
+ if (!(obj->h_tid & GCFLAG_VISITED)) {
+ obj->h_tid &= ~GCFLAG_PUBLIC_TO_PRIVATE; /* see fix_outdated() */
+ obj->h_tid |= GCFLAG_VISITED;
+ gcptrlist_insert(&objects_to_trace, obj);
+
+ if (IS_POINTER(obj->h_revision)) {
+ assert(!(obj->h_revision & 2));
+ visit((gcptr *)&obj->h_revision);
+ }
+ }
}
static void visit_all_objects(void)
@@ -313,7 +331,6 @@
for (; pobj != pend; pobj++) {
obj = *pobj;
assert(obj->h_tid & GCFLAG_PREBUILT_ORIGINAL);
- obj->h_tid &= ~GCFLAG_VISITED;
assert(IS_POINTER(obj->h_revision));
visit((gcptr *)&obj->h_revision);
}
@@ -343,6 +360,7 @@
{
struct tx_descriptor *d;
for (d = stm_tx_head; d; d = d->tx_next) {
+ assert(!stm_has_got_any_lock(d));
/* the roots pushed on the shadowstack */
mark_roots(d->shadowstack, *d->shadowstack_end_ref);
@@ -354,12 +372,22 @@
/* the current transaction's private copies of public objects */
wlog_t *item;
G2L_LOOP_FORWARD(d->public_to_private, item) {
-
/* note that 'item->addr' is also in the read set, so if it was
outdated, it will be found at that time */
- visit(&item->addr);
- visit(&item->val);
-
+ gcptr R = item->addr;
+ gcptr L = item->val;
+ visit_keep(R);
+ if (L != NULL) {
+ revision_t v = L->h_revision;
+ visit_keep(L);
+ /* a bit of custom logic here: if L->h_revision used to
+ point exactly to R, as set by stealing, then we must
+ keep this property, even though visit_keep(L) might
+ decide it would be better to make it point to a more
+ recent copy. */
+ if (v == (revision_t)R)
+ L->h_revision = v; /* restore */
+ }
} G2L_LOOP_END;
/* make sure that the other lists are empty */
@@ -584,6 +612,7 @@
struct tx_descriptor *d;
for (d = stm_tx_head; d; d = d->tx_next) {
free_unused_local_pages(d->public_descriptor);
+ assert(!stm_has_got_any_lock(d));
}
}
@@ -626,6 +655,7 @@
if (d != saved) {
/* Hack: temporarily pretend that we "are" the other thread...
*/
+ assert(d->shadowstack_end_ref && *d->shadowstack_end_ref);
thread_descriptor = d;
stm_private_rev_num = *d->private_revision_ref;
stm_read_barrier_cache = *d->read_barrier_cache_ref;
diff --git a/rpython/translator/stm/src_stm/nursery.c b/rpython/translator/stm/src_stm/nursery.c
--- a/rpython/translator/stm/src_stm/nursery.c
+++ b/rpython/translator/stm/src_stm/nursery.c
@@ -92,7 +92,7 @@
assert(tid == (tid & STM_USER_TID_MASK));
gcptr P = allocate_nursery(size, tid);
P->h_revision = stm_private_rev_num;
- P->h_original = 0;
+ assert(P->h_original == 0); /* null-initialized already */
return P;
}
@@ -199,8 +199,6 @@
return (revision_t)p;
}
-
-
spinlock_acquire(d->public_descriptor->collection_lock, 'I');
/* old objects must have an h_original xOR be
the original itself.
@@ -222,7 +220,6 @@
gcptr O = stmgc_duplicate_old(p);
p->h_original = (revision_t)O;
p->h_tid |= GCFLAG_HAS_ID;
- O->h_tid |= GCFLAG_PUBLIC;
if (p->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED) {
gcptr B = (gcptr)p->h_revision;
@@ -540,6 +537,7 @@
{
dprintf(("minor collection [%p to %p]\n",
d->nursery_base, d->nursery_end));
+ assert(!stm_has_got_any_lock(d));
/* acquire the "collection lock" first */
setup_minor_collect(d);
@@ -566,6 +564,7 @@
with GCFLAG_OLD
*/
teardown_minor_collect(d);
+ assert(!stm_has_got_any_lock(d));
/* When doing minor collections with the nursery "mostly empty",
as occurs when other threads force major collections but this
diff --git a/rpython/translator/stm/src_stm/revision b/rpython/translator/stm/src_stm/revision
--- a/rpython/translator/stm/src_stm/revision
+++ b/rpython/translator/stm/src_stm/revision
@@ -1,1 +1,1 @@
-59eb9a85c3d1
+bf56c12295c8
diff --git a/rpython/translator/stm/src_stm/stmsync.c b/rpython/translator/stm/src_stm/stmsync.c
--- a/rpython/translator/stm/src_stm/stmsync.c
+++ b/rpython/translator/stm/src_stm/stmsync.c
@@ -80,12 +80,14 @@
void stm_initialize(void)
{
+ stmgcpage_acquire_global_lock();
int r = DescriptorInit();
if (r != 1)
stm_fatalerror("stm_initialize: DescriptorInit failure\n");
stmgc_init_nursery();
init_shadowstack();
//stmgcpage_init_tls();
+ stmgcpage_release_global_lock();
BeginInevitableTransaction();
}
@@ -93,10 +95,12 @@
{
stmgc_minor_collect(); /* force everything out of the nursery */
CommitTransaction();
+ stmgcpage_acquire_global_lock();
//stmgcpage_done_tls();
done_shadowstack();
stmgc_done_nursery();
DescriptorDone();
+ stmgcpage_release_global_lock();
}
/************************************************************/
More information about the pypy-commit
mailing list