Author: Armin Rigo <ar...@tunes.org>
Branch: 
Changeset: r236:531e5789c7dd
Date: 2013-06-22 15:57 +0200
http://bitbucket.org/pypy/stmgc/changeset/531e5789c7dd/

Log:    After a major GC, make sure the other threads abort if the major GC
        found that they should.

diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -59,16 +59,23 @@
 
 static pthread_mutex_t mutex_inevitable = PTHREAD_MUTEX_INITIALIZER;
 
-static void inev_mutex_acquire(void)
+static void inev_mutex_release(void)
+{
+  pthread_mutex_unlock(&mutex_inevitable);
+}
+
+static void inev_mutex_acquire(struct tx_descriptor *d)
 {   /* must save roots around this call */
   stm_stop_sharedlock();
   pthread_mutex_lock(&mutex_inevitable);
   stm_start_sharedlock();
-}
 
-static void inev_mutex_release(void)
-{
-  pthread_mutex_unlock(&mutex_inevitable);
+  if (d->active < 0)
+    {
+      inev_mutex_release();
+      AbortNowIfDelayed();
+      abort();   /* unreachable */
+    }
 }
 
 /************************************************************/
@@ -882,6 +889,7 @@
 {
   assert(d->active == 0);
   stm_start_sharedlock();
+  assert(d->active == 0);
 
   if (clock_gettime(CLOCK_MONOTONIC, &d->start_real_time) < 0) {
     d->start_real_time.tv_nsec = -1;
@@ -1225,7 +1233,7 @@
             {                    // there is another inevitable transaction
               CancelLocks(d);
               spinlock_release(d->public_descriptor->collection_lock);
-              inev_mutex_acquire();   // wait until released
+              inev_mutex_acquire(d);   // wait until released
               inev_mutex_release();
               spinlock_acquire(d->public_descriptor->collection_lock, 'C');
               if (d->public_descriptor->stolen_objects.size != 0)
@@ -1284,11 +1292,12 @@
   update_reads_size_limit(d);
 }
 
-static revision_t acquire_inev_mutex_and_mark_global_cur_time(void)
+static revision_t acquire_inev_mutex_and_mark_global_cur_time(
+                      struct tx_descriptor *d)
 {   /* must save roots around this call */
   revision_t cur_time;
 
-  inev_mutex_acquire();
+  inev_mutex_acquire(d);
   while (1)
     {
       cur_time = ACCESS_ONCE(global_cur_time);
@@ -1312,7 +1321,7 @@
   fprintf(stderr, "[%lx] inevitable: %s\n",
           (long)d->public_descriptor_index, why);
 
-  cur_time = acquire_inev_mutex_and_mark_global_cur_time();
+  cur_time = acquire_inev_mutex_and_mark_global_cur_time(d);
   if (d->start_time != cur_time)
     {
       d->start_time = cur_time;
@@ -1332,7 +1341,7 @@
   revision_t cur_time;
 
   init_transaction(d);
-  cur_time = acquire_inev_mutex_and_mark_global_cur_time();
+  cur_time = acquire_inev_mutex_and_mark_global_cur_time(d);
   d->start_time = cur_time;
   make_inevitable(d);
 }
diff --git a/c4/gcpage.c b/c4/gcpage.c
--- a/c4/gcpage.c
+++ b/c4/gcpage.c
@@ -378,8 +378,8 @@
         if (IS_POINTER(v)) {
             /* has a more recent revision.  Oups. */
             fprintf(stderr,
-                    "ABRT_COLLECT_MAJOR: %p was read but modified already\n",
-                    obj);
+                    "ABRT_COLLECT_MAJOR %p: %p was read but modified 
already\n",
+                    d, obj);
             AbortTransactionAfterCollect(d, ABRT_COLLECT_MAJOR);
             return;
         }
@@ -410,6 +410,8 @@
      */
     wlog_t *item;
 
+    fprintf(stderr, "fix public_to_private on thread %p\n", d);
+
     G2L_LOOP_FORWARD(d->public_to_private, item) {
 
         assert(item->addr->h_tid & GCFLAG_PUBLIC);
@@ -419,6 +421,7 @@
                (item->val->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
 
         item->addr->h_tid |= GCFLAG_PUBLIC_TO_PRIVATE;
+        fprintf(stderr, "\tpublic_to_private: %p\n", item->addr);
 
     } G2L_LOOP_END;
 
diff --git a/c4/stmsync.c b/c4/stmsync.c
--- a/c4/stmsync.c
+++ b/c4/stmsync.c
@@ -293,6 +293,8 @@
     /* another thread should be waiting in start_exclusivelock(),
        which takes priority here */
     stm_start_sharedlock();
+
+    AbortNowIfDelayed();   /* if another thread ran a major GC */
 }
 
 /************************************************************/
diff --git a/c4/test/support.py b/c4/test/support.py
--- a/c4/test/support.py
+++ b/c4/test/support.py
@@ -73,6 +73,7 @@
     void stm_start_sharedlock(void);
     void stm_stop_sharedlock(void);
     void AbortTransaction(int);
+    void AbortNowIfDelayed(void);
     gcptr stm_get_private_from_protected(long index);
     gcptr stm_get_read_obj(long index);
     void *STUB_THREAD(gcptr);
@@ -416,6 +417,7 @@
         lib.stm_stop_sharedlock()
         self.parallel_locks[1].acquire()
         lib.stm_start_sharedlock()
+        lib.AbortNowIfDelayed()
         print 'wait_while_in_parallel leave'
         # parallel_locks[0] is acquired, parallel_locks[1] is acquired
         self.parallel_locks[1].release()
@@ -500,9 +502,9 @@
     return p.h_tid & GCFLAG_STUB
 
 def check_not_free(p):
-    print >> sys.stderr, "[checking %r..." % p,
+    #print >> sys.stderr, "[checking %r..." % p,
     assert 42 < (p.h_tid & 0xFFFF) < 521
-    print >> sys.stderr, "ok]"
+    #print >> sys.stderr, "ok]"
 
 def check_nursery_free(p):
     #assert p.h_tid == p.h_revision == 0
diff --git a/c4/test/test_random.py b/c4/test/test_random.py
--- a/c4/test/test_random.py
+++ b/c4/test/test_random.py
@@ -5,7 +5,7 @@
 # a default seed that changes every day, but that can be easily recovered
 DEFAULT_SEED = int(time.strftime("%y%m%d", time.gmtime()))
 
-DO_MAJOR_COLLECTS = False
+DO_MAJOR_COLLECTS = True
 
 
 def setup_function(_):
@@ -452,6 +452,7 @@
         self.toggle = not threadid
         self.cond.notify()
         lib.stm_start_sharedlock()
+        lib.AbortNowIfDelayed()
 
     def wait1(self):
         self.wait(False)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to