Author: Remi Meier <[email protected]>
Branch: stmgc-c4
Changeset: r68265:578f115a3f4f
Date: 2013-11-21 16:06 +0100
http://bitbucket.org/pypy/pypy/changeset/578f115a3f4f/
Log: import stmgc with various fixes
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
@@ -739,9 +739,11 @@
W = LocalizePublic(d, R);
assert(is_private(W));
- if (W->h_tid & GCFLAG_OLD)
+ if (W->h_tid & GCFLAG_OLD) {
+ /* XXX: probably unnecessary as it is done in allocate_next_section
+ already */
gcptrlist_insert(&d->old_objects_to_trace, W);
- else
+ } else
gcptrlist_insert(&d->public_with_young_copy, R);
}
else
@@ -901,6 +903,21 @@
smp_spinloop();
}
+static void purge_private_objs_from_old_objects_to_trace()
+{
+ struct tx_descriptor *d = thread_descriptor;
+ int i, size = d->old_objects_to_trace.size;
+ gcptr *items = d->old_objects_to_trace.items;
+
+ for(i = 0; i < size; i++) {
+ if (items[i] && items[i]->h_revision == stm_private_rev_num) {
+ /* private objects from the same aborting transaction */
+ items[i] = NULL;
+ dprintf(("purge old private object %p\n", items[i]));
+ }
+ }
+}
+
void stm_abort_and_retry(void)
{
AbortTransaction(ABRT_MANUAL);
@@ -991,6 +1008,12 @@
stm_thread_local_obj = d->old_thread_local_obj;
d->old_thread_local_obj = NULL;
+ /* remove old private objects from old_objects_to_trace
+ because they never have to be traced (also because
+ weakrefs are kept alive even when their target is not
+ and stm_move_young_weakrefs doesn't handle that). */
+ purge_private_objs_from_old_objects_to_trace();
+
// notifies the CPU that we're potentially in a spin loop
SpinLoop(SPLP_ABORT);
@@ -1746,6 +1769,8 @@
/* there may be a thread holding the collection lock
because it steals a stub belonging to the thread
that previously owned this descriptor.
+ (not currently, as we do a start_exclusivelock()
+ before calling DescriptorInit)
*/
}
else {
@@ -1810,6 +1835,10 @@
gcptrlist_delete(&d->public_descriptor->stolen_objects);
gcptrlist_delete(&d->public_descriptor->stolen_young_stubs);
+ assert(d->young_weakrefs.size == 0);
+ assert(d->public_with_young_copy.size == 0);
+ assert(d->old_objects_to_trace.size == 0);
+
stmgcpage_done_tls();
i = d->public_descriptor_index;
assert(stm_descriptor_array[i] == d->public_descriptor);
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
@@ -141,7 +141,8 @@
#define SPLP_LOCKED_INFLIGHT 1
#define SPLP_LOCKED_VALIDATE 2
#define SPLP_LOCKED_COMMIT 3
-#define SPINLOOP_REASONS 4
+#define SPLP_LOCKED_COLLECT 4
+#define SPINLOOP_REASONS 5
/* this struct contains thread-local data that may be occasionally
* accessed by a foreign thread and that must stay around after the
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
@@ -56,6 +56,9 @@
|| *d->nursery_current_ref == d->nursery_end);
stm_free(d->nursery_base);
+ assert(d->public_with_young_copy.size == 0);
+ assert(d->old_objects_to_trace.size == 0);
+ assert(d->young_weakrefs.size == 0);
gcptrlist_delete(&d->old_objects_to_trace);
gcptrlist_delete(&d->public_with_young_copy);
gcptrlist_delete(&d->young_weakrefs);
@@ -279,7 +282,19 @@
static void trace_stub(struct tx_descriptor *d, gcptr S)
{
- revision_t w = ACCESS_ONCE(S->h_revision);
+ /* ignore stub if it is outdated, because then the transaction
+ will abort (or has been aborted long ago) */
+
+ revision_t w;
+
+ retry:
+ w = ACCESS_ONCE(S->h_revision);
+ if (!IS_POINTER(w) && w >= LOCKED) {
+ /* check again when unlocked */
+ SpinLoop(SPLP_LOCKED_COLLECT);
+ goto retry;
+ }
+
if ((w & 3) != 2) {
/* P has a ptr in h_revision, but this object is not a stub
with a protected pointer. It has likely been the case
@@ -333,6 +348,7 @@
*/
long i, size = d->public_with_young_copy.size;
gcptr *items = d->public_with_young_copy.items;
+ revision_t v;
for (i = 0; i < size; i++) {
gcptr P = items[i];
@@ -340,7 +356,7 @@
assert(P->h_tid & GCFLAG_OLD);
assert(P->h_tid & GCFLAG_PUBLIC_TO_PRIVATE);
- revision_t v = ACCESS_ONCE(P->h_revision);
+ v = ACCESS_ONCE(P->h_revision);
wlog_t *item;
G2L_FIND(d->public_to_private, P, item, goto not_in_public_to_private);
@@ -361,10 +377,19 @@
item->addr, item->val));
assert(_stm_is_private(item->val));
visit_if_young(&item->val);
+ assert(item->val->h_tid & GCFLAG_OLD);
continue;
not_in_public_to_private:
+ /* re-read because of possible spinloop */
+ v = ACCESS_ONCE(P->h_revision);
+
if (!IS_POINTER(v)) {
+ if (v >= LOCKED) {
+ /* check again when unlocked */
+ SpinLoop(SPLP_LOCKED_COLLECT);
+ goto not_in_public_to_private;
+ }
/* P is neither a key in public_to_private nor outdated.
It must come from an older transaction that aborted.
Nothing to do now.
@@ -384,7 +409,8 @@
{
while (gcptrlist_size(&d->old_objects_to_trace) > 0) {
gcptr obj = gcptrlist_pop(&d->old_objects_to_trace);
-
+ if (!obj)
+ continue;
assert(obj->h_tid & GCFLAG_OLD);
assert(!(obj->h_tid & GCFLAG_WRITE_BARRIER));
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 @@
-b89b61f0df98
+b820cff55e7a
diff --git a/rpython/translator/stm/src_stm/steal.c
b/rpython/translator/stm/src_stm/steal.c
--- a/rpython/translator/stm/src_stm/steal.c
+++ b/rpython/translator/stm/src_stm/steal.c
@@ -257,8 +257,11 @@
memset(&sd.all_stubs, 0, sizeof(sd.all_stubs));
steal_data = &sd;
stmgc_trace(L, &replace_ptr_to_protected_with_stub);
- if (L->h_tid & GCFLAG_WEAKREF)
+ if (L->h_tid & GCFLAG_WEAKREF) {
+ /* We have to trace the weakref manually because stmgc_trace
+ doesn't */
replace_ptr_to_protected_with_stub(WEAKREF_PTR(L, stmgc_size(L)));
+ }
g2l_delete_not_used_any_more(&sd.all_stubs);
/* If another thread (the foreign or a 3rd party) does a read
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
@@ -89,6 +89,7 @@
XXX: remove again when sure it is not needed
(interaction with stop_all_other_threads()) */
start_exclusivelock();
+ assert(stm_active == 0);
stmgcpage_acquire_global_lock();
#ifdef STM_BARRIER_COUNT
static int seen = 0;
@@ -117,6 +118,7 @@
if (token == 1) {
start_exclusivelock();
+ assert(stm_active == 0);
stmgcpage_acquire_global_lock();
done_shadowstack();
stmgc_done_nursery();
@@ -385,6 +387,14 @@
ACCESS_ONCE(sync_required) = -1;
stm_stop_sharedlock();
start_exclusivelock();
+ if (stm_active < 0) {
+ /* we have to give up and abort. Another thread did
+ a major collect and makes us abort now */
+ stop_exclusivelock();
+ stm_start_sharedlock();
+ assert(stm_active < 0);
+ AbortNowIfDelayed();
+ }
ACCESS_ONCE(sync_required) = 0;
assert(in_single_thread == NULL);
@@ -401,6 +411,10 @@
stop_exclusivelock();
stm_start_sharedlock();
+
+ /* another thread may commit, start a major collect, and
+ make us abort */
+ AbortNowIfDelayed();
}
void stm_possible_safe_point(void)
diff --git a/rpython/translator/stm/src_stm/weakref.c
b/rpython/translator/stm/src_stm/weakref.c
--- a/rpython/translator/stm/src_stm/weakref.c
+++ b/rpython/translator/stm/src_stm/weakref.c
@@ -40,10 +40,13 @@
if (stmgc_is_in_nursery(d, pointing_to)) {
if (pointing_to->h_tid & GCFLAG_MOVED) {
+ gcptr to = (gcptr)pointing_to->h_revision;
dprintf(("weakref ptr moved %p->%p\n",
- *WEAKREF_PTR(weakref, size),
- (gcptr)pointing_to->h_revision));
- *WEAKREF_PTR(weakref, size) = (gcptr)pointing_to->h_revision;
+ *WEAKREF_PTR(weakref, size), to));
+ *WEAKREF_PTR(weakref, size) = to;
+ assert(to->h_tid & GCFLAG_OLD);
+ assert(!(to->h_tid & GCFLAG_MOVED));
+ assert(!(pointing_to->h_tid & GCFLAG_OLD));
}
else {
assert(!IS_POINTER(pointing_to->h_revision));
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit