Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r333:e58e43f88445
Date: 2013-07-01 14:44 +0200
http://bitbucket.org/pypy/stmgc/changeset/e58e43f88445/

Log:    in-progress

diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -764,20 +764,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) {
@@ -954,6 +958,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))
@@ -1032,6 +1037,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,
diff --git a/c4/et.h b/c4/et.h
--- a/c4/et.h
+++ b/c4/et.h
@@ -190,6 +190,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/c4/gcpage.c b/c4/gcpage.c
--- a/c4/gcpage.c
+++ b/c4/gcpage.c
@@ -346,6 +346,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);
@@ -356,15 +357,24 @@
 
         /* the current transaction's private copies of public objects */
         wlog_t *item;
+        struct G2L new_public_to_private;
+        memset(&new_public_to_private, 0, sizeof(new_public_to_private));
+
         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 key = item->addr;
+            gcptr val = item->val;
+            visit(&key);
+            visit(&val);
+            g2l_insert(&new_public_to_private, key, val);
 
         } G2L_LOOP_END;
 
+        g2l_delete_not_used_any_more(&d->public_to_private);
+        d->public_to_private = new_public_to_private;
+
         /* make sure that the other lists are empty */
         assert(gcptrlist_size(&d->public_with_young_copy) == 0);
         assert(gcptrlist_size(&d->public_descriptor->stolen_objects) == 0);
@@ -587,6 +597,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));
     }
 }
 
diff --git a/c4/nursery.c b/c4/nursery.c
--- a/c4/nursery.c
+++ b/c4/nursery.c
@@ -536,6 +536,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);
@@ -562,6 +563,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
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to