Author: Armin Rigo <[email protected]>
Branch:
Changeset: r30:d872b4ad04ef
Date: 2013-05-26 20:30 +0200
http://bitbucket.org/pypy/stmgc/changeset/d872b4ad04ef/
Log: Test and implementation of another "abort();//XXX".
diff --git a/c3/et.c b/c3/et.c
--- a/c3/et.c
+++ b/c3/et.c
@@ -513,7 +513,7 @@
{
if (d->active >= 0)
{
- assert(d->active == 1);
+ assert(d->active == 1); /* not 2, which means inevitable */
d->active = -reason;
}
assert(d->active < 0);
@@ -523,7 +523,11 @@
{
struct tx_descriptor *d = thread_descriptor;
if (d->active < 0)
- AbortTransaction(-d->active);
+ {
+ int reason = -d->active;
+ d->active = 1;
+ AbortTransaction(reason);
+ }
}
/************************************************************/
diff --git a/c3/nursery.c b/c3/nursery.c
--- a/c3/nursery.c
+++ b/c3/nursery.c
@@ -634,6 +634,7 @@
2. it is a stolen object
3. it is not visited because it has already been modified.
+ But this case cannot occur: the object is still protected
*/
if (obj->h_revision & 1) {
/* first case: untrack it. Note that this case can occur
@@ -643,17 +644,29 @@
/*mark*/
}
else if (obj->h_tid & GCFLAG_STOLEN) {
- /* second case: 'obj' was stolen. Just replace it in the
- list with its new copy, which should be identical
- (and public, so no more processing it needed). */
- assert(dclassify((gcptr)obj->h_revision) == K_PUBLIC);
- items[i] = (gcptr)obj->h_revision;
+ /* second case: 'obj' was stolen. We check to see if
+ the public version was already outdated. If not, we
+ replace 'obj' in the list with this public version,
+ which should be identical. */
+ gcptr P = (gcptr)obj->h_revision;
+ assert(dclassify(P) == K_PUBLIC);
+
+ if (P->h_revision & 1) { /* "is not a pointer" */
+ items[i] = P;
+ /*mark*/
+ }
+ else {
+ /* P has already been changed. Mark as abort. */
+ AbortTransactionAfterCollect(d, ABRT_COLLECT_MINOR);
+ /*mark*/
+ gcptrlist_clear(&d->list_of_read_objects);
+ break;
+ }
}
else {
- /* third case */
- abort();//XXX
- /* ABRT_COLLECT_MINOR ... check
- for stolen object */
+ /* third case: impossible */
+ assert(!"third case of fix_list_of_read_objects");
+ abort();
}
}
d->num_read_objects_known_old = d->list_of_read_objects.size;
diff --git a/c3/test/test_nursery.py b/c3/test/test_nursery.py
--- a/c3/test/test_nursery.py
+++ b/c3/test/test_nursery.py
@@ -392,6 +392,7 @@
def cb(c):
assert c == 0
p1 = lib.stm_read_barrier(pg)
+ assert lib.in_nursery(p1)
r.wait_while_in_parallel()
minor_collect()
perform_transaction(cb)
@@ -403,3 +404,28 @@
perform_transaction(cb)
r.leave_in_parallel()
run_parallel(f1, f2)
+
+def test_read_from_modified_stolen_object():
+ pg = palloc(HDR + WORD)
+ seen = []
+ def f1(r):
+ lib.setlong(pg, 0, 287221)
+ def cb(c):
+ if c == 0:
+ p1 = lib.stm_read_barrier(pg)
+ assert lib.in_nursery(p1)
+ r.wait_while_in_parallel()
+ seen.append("ok")
+ minor_collect()
+ raise AssertionError("we should not reach this!")
+ else:
+ assert seen == ["ok"]
+ perform_transaction(cb)
+ def f2(r):
+ def cb(c):
+ assert c == 0
+ r.enter_in_parallel()
+ lib.setlong(pg, 0, -66666) # steal object
+ perform_transaction(cb)
+ r.leave_in_parallel()
+ run_parallel(f1, f2, max_aborts=1)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit