Author: Armin Rigo <[email protected]>
Branch:
Changeset: r333:e58e43f88445
Date: 2013-07-01 14:44 +0200
http://bitbucket.org/pypy/stmgc/changeset/e58e43f88445/
Log: in-progress
diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -764,20 +764,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) {
@@ -954,6 +958,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))
@@ -1032,6 +1037,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,
diff --git a/c4/et.h b/c4/et.h
--- a/c4/et.h
+++ b/c4/et.h
@@ -190,6 +190,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/c4/gcpage.c b/c4/gcpage.c
--- a/c4/gcpage.c
+++ b/c4/gcpage.c
@@ -346,6 +346,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);
@@ -356,15 +357,24 @@
/* the current transaction's private copies of public objects */
wlog_t *item;
+ struct G2L new_public_to_private;
+ memset(&new_public_to_private, 0, sizeof(new_public_to_private));
+
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 key = item->addr;
+ gcptr val = item->val;
+ visit(&key);
+ visit(&val);
+ g2l_insert(&new_public_to_private, key, val);
} G2L_LOOP_END;
+ g2l_delete_not_used_any_more(&d->public_to_private);
+ d->public_to_private = new_public_to_private;
+
/* make sure that the other lists are empty */
assert(gcptrlist_size(&d->public_with_young_copy) == 0);
assert(gcptrlist_size(&d->public_descriptor->stolen_objects) == 0);
@@ -587,6 +597,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));
}
}
diff --git a/c4/nursery.c b/c4/nursery.c
--- a/c4/nursery.c
+++ b/c4/nursery.c
@@ -536,6 +536,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);
@@ -562,6 +563,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
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit