Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r16:8cfb3a9e834d
Date: 2013-05-26 15:01 +0200
http://bitbucket.org/pypy/stmgc/changeset/8cfb3a9e834d/

Log:    Fix stmgc_nursery_hiding(): use a real refcount and locking policy
        now, which avoids races when stealing.

diff --git a/c3/nursery.c b/c3/nursery.c
--- a/c3/nursery.c
+++ b/c3/nursery.c
@@ -217,10 +217,6 @@
 
 void stmgc_abort_transaction(struct tx_descriptor *d)
 {
-    /* cancel the change to the h_revision done in LocalizeProtected() */
-    long i, size = d->protected_with_private_copy.size;
-    gcptr *items = d->protected_with_private_copy.items;
-
     /* Note that the thrown-away private objects are kept around.  It
        may possibly be a small optimization to reuse the part of the
        nursery that contains them.  To be on the safe "future-proof"
@@ -231,6 +227,10 @@
     if (d->collection_lock != 'C')
         spinlock_acquire(d->collection_lock);
 
+    /* cancel the change to the h_revision done in LocalizeProtected() */
+    long i, size = d->protected_with_private_copy.size;
+    gcptr *items = d->protected_with_private_copy.items;
+
     for (i = 0; i < size; i++) {
         gcptr R = items[i];
         assert(dclassify(R) == K_PROTECTED);
@@ -805,30 +805,51 @@
 {
 #ifdef _GC_DEBUG
     struct tx_descriptor *d = thread_descriptor;
+    wlog_t *item;
+    revision_t count;
+
+    /* 'd->debug_nursery_access' works like a refcount: when it is 0,
+       no-one should be accessing young objects of 'd'.  We ensure that
+       it is the case using mprotect. */
+    while (1) {
+        count = ACCESS_ONCE(d->debug_nursery_access);
+        if (count == (revision_t)-1) {
+            spinloop();
+            continue;
+        }
+        if (bool_cas(&d->debug_nursery_access, count, (revision_t)-1))
+            break;
+    }
+
     if (hide) {
-        stm_dbgmem_not_used(d->nursery, GC_NURSERY, 1);
+        /* decrement the "refcount" */
+        assert(count > 0);
+        count--;
+        if (count == 0) {
+            stm_dbgmem_not_used(d->nursery, GC_NURSERY, 1);
+
+            G2L_LOOP_FORWARD(d->young_objects_outside_nursery, item) {
+                gcptr obj = item->addr;
+                size_t size = stmcb_size(obj);
+                stm_dbgmem_not_used(obj, size, 0);
+            } G2L_LOOP_END;
+        }
     }
     else {
-        stm_dbgmem_used_again(d->nursery,
-                              d->nursery_current - d->nursery, 1);
+        if (count == 0) {
+            stm_dbgmem_used_again(d->nursery,
+                                  d->nursery_current - d->nursery, 1);
+            G2L_LOOP_FORWARD(d->young_objects_outside_nursery, item) {
+                gcptr obj = item->addr;
+                stm_dbgmem_used_again(obj, sizeof(*obj), 0);
+                size_t size = stmcb_size(obj);
+                stm_dbgmem_used_again(obj, size, 0);
+            } G2L_LOOP_END;
+        }
+        count++;
     }
-
-    wlog_t *item;
-
-    G2L_LOOP_FORWARD(d->young_objects_outside_nursery, item) {
-
-        gcptr obj = item->addr;
-        if (hide) {
-            size_t size = stmcb_size(obj);
-            stm_dbgmem_not_used(obj, size, 0);
-        }
-        else {
-            stm_dbgmem_used_again(obj, sizeof(gcptr *), 0);
-            size_t size = stmcb_size(obj);
-            stm_dbgmem_used_again(obj, size, 0);
-        }
-
-    } G2L_LOOP_END;
+    smp_wmb();
+    ACCESS_ONCE(d->debug_nursery_access) = count;
 #endif
     return 1;
 }
@@ -924,9 +945,10 @@
         thread_descriptor = source_d;
         stm_local_revision = *source_d->local_revision_ref;
 
+        fprintf(stderr, "STEALING: %p->h_revision points to %p\n", P, R);
+
         /* debugging support: "activate" the foreign nursery */
-        int was_active = stm_dbgmem_is_active(source_d->nursery, 0);
-        if (!was_active) assert(stmgc_nursery_hiding(0));
+        assert(stmgc_nursery_hiding(0));
 
         /* copy the protected source object */
         gcptr N = extract_from_foreign_nursery(R);
@@ -941,7 +963,7 @@
                 P, R, N);
 
         /* debugging support: "deactivate" the foreign nursery again */
-        if (!was_active) assert(stmgc_nursery_hiding(1));
+        assert(stmgc_nursery_hiding(1));
 
         /* restore my own identity */
         stm_local_revision = my_local_rev;
diff --git a/c3/nursery.h b/c3/nursery.h
--- a/c3/nursery.h
+++ b/c3/nursery.h
@@ -14,7 +14,7 @@
     gcptr **shadowstack_end_ref;                        \
     gcptr *thread_local_obj_ref;                        \
                                                         \
-    revision_t collection_lock;                         \
+    revision_t collection_lock, debug_nursery_access;   \
     struct G2L young_objects_outside_nursery;           \
     struct GcPtrList old_objects_to_trace;              \
     long num_read_objects_known_old;                    \
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to