[pypy-commit] stmgc default: Change again: don't pretend to have the identity of the stolen-from

arigo noreply at buildbot.pypy.org
Sun May 26 16:54:44 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r18:ab86b5cb7472
Date: 2013-05-26 16:12 +0200
http://bitbucket.org/pypy/stmgc/changeset/ab86b5cb7472/

Log:	Change again: don't pretend to have the identity of the stolen-from
	thread. This doesn't work correctly with the calls to
	stmgcpage_malloc().

diff --git a/c3/et.c b/c3/et.c
--- a/c3/et.c
+++ b/c3/et.c
@@ -301,6 +301,7 @@
 
  not_found:;
   gcptr L = stmgc_duplicate(R, 0);
+  assert(L->h_revision == stm_local_revision);
   g2l_insert(&d->public_to_private, R, L);
   gcptrlist_insert(&d->public_to_young, R);
   AddInReadSet(d, R);
@@ -746,11 +747,9 @@
   gcptrlist_clear(&d->list_of_read_objects);
 
   fprintf(stderr, "\n"
-          "***************************************************************\n"
-          "***************************************************************\n"
-          "*************************************   %ld\n"
-          "***************************************************************\n"
-          "***************************************************************\n",
+          "*************************************\n"
+          "**************************************  committed %ld\n"
+          "*************************************\n",
           (long)cur_time);
 
   revision_t localrev = stm_local_revision;
diff --git a/c3/gcpage.c b/c3/gcpage.c
--- a/c3/gcpage.c
+++ b/c3/gcpage.c
@@ -557,9 +557,9 @@
              */
             thread_descriptor = d;
             stm_local_revision = *d->local_revision_ref;
-            assert(stmgc_nursery_hiding(0));
+            assert(stmgc_nursery_hiding(d, 0));
             stmgc_minor_collect_no_abort();
-            assert(stmgc_nursery_hiding(1));
+            assert(stmgc_nursery_hiding(d, 1));
         }
     }
     thread_descriptor = saved;
diff --git a/c3/nursery.c b/c3/nursery.c
--- a/c3/nursery.c
+++ b/c3/nursery.c
@@ -179,6 +179,8 @@
 
 void stmgc_start_transaction(struct tx_descriptor *d)
 {
+    assert(!d->collection_lock);  /* with no protected objects so far, no
+                                     other thread can be stealing */
     assert(!gcptrlist_size(&d->protected_with_private_copy));
     assert(!g2l_any_entry(&d->public_to_private));
     assert(!gcptrlist_size(&d->private_old_pointing_to_young));
@@ -457,6 +459,7 @@
 
         /* then we record the dependency in the dictionary
            'public_to_private' */
+        assert(L->h_revision == stm_local_revision);
         g2l_insert(&d->public_to_private, R, L);
         /*mark*/
     }
@@ -657,11 +660,7 @@
 static void create_yo_stubs(gcptr *pobj)
 {
     gcptr obj = *pobj;
-    if (obj == NULL)
-        return;
-
-    struct tx_descriptor *d = thread_descriptor;
-    if (!stmgc_is_young_in(d, obj))
+    if (obj == NULL || (obj->h_tid & GCFLAG_OLD) != 0)
         return;
 
     /* xxx try to avoid duplicate stubs for the same object */
@@ -800,10 +799,9 @@
     gcptrlist_insert(&d->private_old_pointing_to_young, obj);
 }
 
-int stmgc_nursery_hiding(int hide)
+int stmgc_nursery_hiding(struct tx_descriptor *d, int hide)
 {
 #ifdef _GC_DEBUG
-    struct tx_descriptor *d = thread_descriptor;
     wlog_t *item;
     revision_t count;
 
@@ -855,16 +853,16 @@
 
 /************************************************************/
 
-static gcptr extract_from_foreign_nursery(gcptr R)
+static gcptr extract_from_foreign_nursery(struct tx_descriptor *source_d,
+                                          gcptr R)
 {
     /* "Stealing": this function follows a chain of protected objects in
-       the foreign nursery of the thread temporarily in
-       'thread_descriptor'.  It copies the last one outside the nursery,
-       and return it. */
+       the foreign nursery of the thread 'source_d'.  It copies the last
+       one outside the nursery, and return it. */
     gcptr R2, N;
     revision_t source_local_rev, v;
 
-    source_local_rev = stm_local_revision;
+    source_local_rev = *source_d->local_revision_ref;
     v = ACCESS_ONCE(R->h_revision);
 
     /* check that R is a protected object */
@@ -895,9 +893,9 @@
     }
 
     /* R is now the protected object to move outside, with revision v. */
-    N = create_old_object_copy(R  _REASON("stolen copy"));
+    N = create_old_object_copy(R  _REASON("**stolen copy"));
     N->h_revision = v;
-    gcptrlist_insert2(&thread_descriptor->stolen_objects, R, N);
+    gcptrlist_insert2(&source_d->stolen_objects, R, N);
 
     /* there might be references in N going to protected objects.  We
        must fix them with stubs. */
@@ -915,7 +913,6 @@
        for the other thread to do a minor collection, because it might
        be blocked in a system call or whatever. */
     struct tx_descriptor *my_d = thread_descriptor;
-    revision_t my_local_rev = stm_local_revision;
 
     /* repeat the checks in the caller, to avoid passing more than one
        argument here */
@@ -940,33 +937,30 @@
        retry.
     */
     if (P->h_revision == v) {
-        /* temporarily take the identity of source_d */
-        thread_descriptor = source_d;
-        stm_local_revision = *source_d->local_revision_ref;
-
+        /* careful here: all 'thread_descriptor' accesses will continue
+           to get the current thread (needed e.g. for stmgcpage_malloc())
+           which is different from 'source_d', the source thread out of
+           which we are stealing. */
         fprintf(stderr, "STEALING: %p->h_revision points to %p\n", P, R);
 
         /* debugging support: "activate" the foreign nursery */
-        assert(stmgc_nursery_hiding(0));
+        assert(stmgc_nursery_hiding(source_d, 0));
 
         /* copy the protected source object */
-        gcptr N = extract_from_foreign_nursery(R);
+        gcptr N = extract_from_foreign_nursery(source_d, R);
 
         /* make sure the copy N is visible to other threads before we
            change P->h_revision */
         smp_wmb();
 
         /* do the change to P->h_revision */
+        assert(bool_cas(&P->h_revision, ((revision_t)R) | 2, (revision_t)N));
         ACCESS_ONCE(P->h_revision) = (revision_t)N;
         fprintf(stderr, "STEALING: %p->h_revision changed from %p to %p\n",
                 P, R, N);
 
         /* debugging support: "deactivate" the foreign nursery again */
-        assert(stmgc_nursery_hiding(1));
-
-        /* restore my own identity */
-        stm_local_revision = my_local_rev;
-        thread_descriptor = my_d;
+        assert(stmgc_nursery_hiding(source_d, 1));
     }
     spinlock_release(source_d->collection_lock);
 }
@@ -980,6 +974,7 @@
     */
     long i, size = d->stolen_objects.size;
     gcptr *items = d->stolen_objects.items;
+    assert(d == thread_descriptor);
 
     for (i = 0; i < size; i += 2) {
         gcptr R = items[i];
@@ -1003,6 +998,7 @@
 
             /* we re-insert L as a private copy of the public object N */
             N->h_tid |= GCFLAG_PUBLIC_TO_PRIVATE;
+            assert(L->h_revision == stm_local_revision);
             g2l_insert(&d->public_to_private, N, L);
             gcptrlist_insert(&d->public_to_young, N);
         }
diff --git a/c3/nursery.h b/c3/nursery.h
--- a/c3/nursery.h
+++ b/c3/nursery.h
@@ -46,7 +46,7 @@
 enum protection_class_t stmgc_classify(gcptr);
 int stmgc_is_young_in(struct tx_descriptor *, gcptr);
 void stmgc_public_to_foreign_protected(gcptr);
-int stmgc_nursery_hiding(int);
+int stmgc_nursery_hiding(struct tx_descriptor *, int);
 void stmgc_normalize_stolen_objects(void);
 
 #ifdef _GC_DEBUG
diff --git a/c3/stmsync.c b/c3/stmsync.c
--- a/c3/stmsync.c
+++ b/c3/stmsync.c
@@ -236,12 +236,12 @@
 {
     int err = pthread_rwlock_rdlock(&rwlock_shared);
     assert(err == 0);
-    assert(stmgc_nursery_hiding(0));
+    assert(stmgc_nursery_hiding(thread_descriptor, 0));
 }
 
 void stm_stop_sharedlock(void)
 {
-    assert(stmgc_nursery_hiding(1));
+    assert(stmgc_nursery_hiding(thread_descriptor, 1));
     int err = pthread_rwlock_unlock(&rwlock_shared);
     assert(err == 0);
 }
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
@@ -272,9 +272,13 @@
         def cb(c):
             assert c == 0
             p4 = lib.stm_write_barrier(p1)
+            assert lib.in_nursery(p4)
+            assert p4 != p1 and p4 != pg
             assert lib.rawgetlong(p4, 0) == 9387987
+            print "changing p4=%r to contain -6666" % (p4,)
             lib.rawsetlong(p4, 0, -6666)
             r.wait_while_in_parallel()
+            assert seen == ["ok"]
         perform_transaction(cb)
     def f2(r):
         def cb(c):
@@ -284,6 +288,7 @@
             assert not lib.in_nursery(p2)
             assert lib.rawgetlong(p2, 0) == 9387987
         perform_transaction(cb)
+        seen.append("ok")
         r.leave_in_parallel()
     run_parallel(f1, f2)
     assert lib.getlong(pg, 0) == -6666


More information about the pypy-commit mailing list