[pypy-commit] pypy stmgc-c4: import stmgc/bf56c12295c8

arigo noreply at buildbot.pypy.org
Mon Jul 1 15:14:01 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c4
Changeset: r65135:12aa03d05cb3
Date: 2013-07-01 15:12 +0200
http://bitbucket.org/pypy/pypy/changeset/12aa03d05cb3/

Log:	import stmgc/bf56c12295c8

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
@@ -765,20 +765,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) {
@@ -907,6 +911,8 @@
 long stm_atomic(long delta)
 {
   struct tx_descriptor *d = thread_descriptor;
+  if (delta) // no atomic-checks
+    dprintf(("stm_atomic(%lu)\n", delta));
   d->atomic += delta;
   assert(d->atomic >= 0);
   update_reads_size_limit(d);
@@ -953,6 +959,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))
@@ -1031,6 +1038,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,
@@ -1505,7 +1552,6 @@
       revision_t i;
       struct tx_descriptor *d = stm_malloc(sizeof(struct tx_descriptor));
       memset(d, 0, sizeof(struct tx_descriptor));
-      stmgcpage_acquire_global_lock();
 
       struct tx_public_descriptor *pd;
       i = descriptor_array_free_list;
@@ -1555,7 +1601,6 @@
                (long)d->public_descriptor_index, (long)pthread_self()));
 
       stmgcpage_init_tls();
-      stmgcpage_release_global_lock();
       return 1;
     }
   else
@@ -1568,7 +1613,6 @@
     struct tx_descriptor *d = thread_descriptor;
     assert(d != NULL);
     assert(d->active == 0);
-    stmgcpage_acquire_global_lock();
 
     /* our nursery is empty at this point.  The list 'stolen_objects'
        should have been emptied at the previous minor collection and
@@ -1586,7 +1630,6 @@
     if (d->tx_prev != NULL) d->tx_prev->tx_next = d->tx_next;
     if (d->tx_next != NULL) d->tx_next->tx_prev = d->tx_prev;
     if (d == stm_tx_head) stm_tx_head = d->tx_next;
-    stmgcpage_release_global_lock();
 
     thread_descriptor = NULL;
 
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
@@ -191,6 +191,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/rpython/translator/stm/src_stm/gcpage.c b/rpython/translator/stm/src_stm/gcpage.c
--- a/rpython/translator/stm/src_stm/gcpage.c
+++ b/rpython/translator/stm/src_stm/gcpage.c
@@ -220,17 +220,14 @@
         return;
 
  restart:
-    if (obj->h_tid & GCFLAG_VISITED) {
-        dprintf(("[already visited: %p]\n", obj));
-        assert(obj == *pobj);
-        assert((obj->h_revision & 3) ||   /* either odd, or stub */
-               (obj->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
-        return;    /* already seen */
-    }
-
     if (obj->h_revision & 1) {
         assert(!(obj->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
-        obj->h_tid &= ~GCFLAG_PUBLIC_TO_PRIVATE;  /* see also fix_outdated() */
+        assert(!(obj->h_tid & GCFLAG_STUB));
+        if (!(obj->h_tid & GCFLAG_VISITED)) {
+            obj->h_tid &= ~GCFLAG_PUBLIC_TO_PRIVATE;  /* see fix_outdated() */
+            obj->h_tid |= GCFLAG_VISITED;
+            gcptrlist_insert(&objects_to_trace, obj);
+        }
     }
     else if (obj->h_tid & GCFLAG_PUBLIC) {
         /* h_revision is a ptr: we have a more recent version */
@@ -267,27 +264,48 @@
         *pobj = obj;
         goto restart;
     }
+    else if (obj->h_tid & GCFLAG_VISITED) {
+        dprintf(("[already visited: %p]\n", obj));
+        assert(obj == *pobj);
+        assert((obj->h_revision & 3) ||   /* either odd, or stub */
+               (obj->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
+        return;    /* already seen */
+    }
     else {
         assert(obj->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED);
         gcptr B = (gcptr)obj->h_revision;
-        gcptrlist_insert(&objects_to_trace, B);
+        assert(B->h_tid & (GCFLAG_PUBLIC | GCFLAG_BACKUP_COPY));
 
-        if (!(B->h_tid & GCFLAG_PUBLIC)) {
-            /* a regular private_from_protected object with a backup copy B */
-            assert(B->h_tid & GCFLAG_BACKUP_COPY);
-            assert(B->h_revision & 1);
-            B->h_tid |= GCFLAG_VISITED;
-        }
-        else {
-            /* a private_from_protected with a stolen backup copy B */
+        obj->h_tid |= GCFLAG_VISITED;
+        B->h_tid |= GCFLAG_VISITED;
+        assert(!(obj->h_tid & GCFLAG_STUB));
+        assert(!(B->h_tid & GCFLAG_STUB));
+        gcptrlist_insert2(&objects_to_trace, obj, B);
+
+        if (IS_POINTER(B->h_revision)) {
+            assert(B->h_tid & GCFLAG_PUBLIC);
             assert(!(B->h_tid & GCFLAG_BACKUP_COPY));
-            gcptr obj1 = B;
-            visit(&obj1);     /* xxx recursion? */
-            obj->h_revision = (revision_t)obj1;
+            assert(!(B->h_revision & 2));
+
+            pobj = (gcptr *)&B->h_revision;
+            obj = *pobj;
+            goto restart;
         }
     }
-    obj->h_tid |= GCFLAG_VISITED;
-    gcptrlist_insert(&objects_to_trace, obj);
+}
+
+static void visit_keep(gcptr obj)
+{
+    if (!(obj->h_tid & GCFLAG_VISITED)) {
+        obj->h_tid &= ~GCFLAG_PUBLIC_TO_PRIVATE;  /* see fix_outdated() */
+        obj->h_tid |= GCFLAG_VISITED;
+        gcptrlist_insert(&objects_to_trace, obj);
+
+        if (IS_POINTER(obj->h_revision)) {
+            assert(!(obj->h_revision & 2));
+            visit((gcptr *)&obj->h_revision);
+        }
+    }
 }
 
 static void visit_all_objects(void)
@@ -313,7 +331,6 @@
     for (; pobj != pend; pobj++) {
         obj = *pobj;
         assert(obj->h_tid & GCFLAG_PREBUILT_ORIGINAL);
-        obj->h_tid &= ~GCFLAG_VISITED;
         assert(IS_POINTER(obj->h_revision));
         visit((gcptr *)&obj->h_revision);
     }
@@ -343,6 +360,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);
@@ -354,12 +372,22 @@
         /* the current transaction's private copies of public objects */
         wlog_t *item;
         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 R = item->addr;
+            gcptr L = item->val;
+            visit_keep(R);
+            if (L != NULL) {
+                revision_t v = L->h_revision;
+                visit_keep(L);
+                /* a bit of custom logic here: if L->h_revision used to
+                   point exactly to R, as set by stealing, then we must
+                   keep this property, even though visit_keep(L) might
+                   decide it would be better to make it point to a more
+                   recent copy. */
+                if (v == (revision_t)R)
+                    L->h_revision = v;   /* restore */
+            }
         } G2L_LOOP_END;
 
         /* make sure that the other lists are empty */
@@ -584,6 +612,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));
     }
 }
 
@@ -626,6 +655,7 @@
         if (d != saved) {
             /* Hack: temporarily pretend that we "are" the other thread...
              */
+            assert(d->shadowstack_end_ref && *d->shadowstack_end_ref);
             thread_descriptor = d;
             stm_private_rev_num = *d->private_revision_ref;
             stm_read_barrier_cache = *d->read_barrier_cache_ref;
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
@@ -92,7 +92,7 @@
     assert(tid == (tid & STM_USER_TID_MASK));
     gcptr P = allocate_nursery(size, tid);
     P->h_revision = stm_private_rev_num;
-    P->h_original = 0;
+    assert(P->h_original == 0);  /* null-initialized already */
     return P;
 }
 
@@ -199,8 +199,6 @@
         return (revision_t)p;
     }
     
-
-    
     spinlock_acquire(d->public_descriptor->collection_lock, 'I');
     /* old objects must have an h_original xOR be
        the original itself. 
@@ -222,7 +220,6 @@
         gcptr O = stmgc_duplicate_old(p);
         p->h_original = (revision_t)O;
         p->h_tid |= GCFLAG_HAS_ID;
-        O->h_tid |= GCFLAG_PUBLIC;
         
         if (p->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED) {
             gcptr B = (gcptr)p->h_revision;
@@ -540,6 +537,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);
@@ -566,6 +564,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
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 @@
-59eb9a85c3d1
+bf56c12295c8
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
@@ -80,12 +80,14 @@
 
 void stm_initialize(void)
 {
+    stmgcpage_acquire_global_lock();
     int r = DescriptorInit();
     if (r != 1)
         stm_fatalerror("stm_initialize: DescriptorInit failure\n");
     stmgc_init_nursery();
     init_shadowstack();
     //stmgcpage_init_tls();
+    stmgcpage_release_global_lock();
     BeginInevitableTransaction();
 }
 
@@ -93,10 +95,12 @@
 {
     stmgc_minor_collect();   /* force everything out of the nursery */
     CommitTransaction();
+    stmgcpage_acquire_global_lock();
     //stmgcpage_done_tls();
     done_shadowstack();
     stmgc_done_nursery();
     DescriptorDone();
+    stmgcpage_release_global_lock();
 }
 
 /************************************************************/


More information about the pypy-commit mailing list