Author: Armin Rigo <[email protected]>
Branch: stm-gc-2
Changeset: r63118:ef7cc6c7f545
Date: 2013-04-07 17:44 +0200
http://bitbucket.org/pypy/pypy/changeset/ef7cc6c7f545/

Log:    The minimal interface that should be enough to synchronize all
        threads at the start of a major GC

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
@@ -393,6 +393,8 @@
   size_t size;
   struct timespec now;
   long long elapsed_time;
+  int err;
+
   assert(d->active);
   assert(!is_inevitable(d));
   assert(num < ABORT_REASONS);
@@ -476,7 +478,8 @@
   SpinLoop(0);
   // jump back to the setjmp_buf (this call does not return)
   d->active = 0;
-  pthread_rwlock_unlock(&rwlock_in_transaction);
+  err = pthread_rwlock_unlock(&rwlock_in_transaction);
+  assert(err == 0);
   longjmp(*d->setjmp_buf, 1);
 }
 
@@ -491,8 +494,11 @@
 
 static void init_transaction(struct tx_descriptor *d)
 {
+  int err;
   assert(d->active == 0);
-  pthread_rwlock_rdlock(&rwlock_in_transaction);
+  err = pthread_rwlock_rdlock(&rwlock_in_transaction);
+  assert(err == 0);
+
   if (clock_gettime(CLOCK_MONOTONIC, &d->start_real_time) < 0) {
     d->start_real_time.tv_nsec = -1;
   }
@@ -643,6 +649,7 @@
 {
   revision_t cur_time;
   struct tx_descriptor *d = thread_descriptor;
+  int err;
   assert(d->active != 0);
 
   FindRootsForLocalCollect(d);
@@ -689,7 +696,8 @@
   gcptrlist_clear(&d->gcroots);
   d->num_commits++;
   d->active = 0;
-  pthread_rwlock_unlock(&rwlock_in_transaction);
+  err = pthread_rwlock_unlock(&rwlock_in_transaction);
+  assert(err == 0);
 }
 
 /************************************************************/
diff --git a/rpython/translator/stm/src_stm/rpyintf.c 
b/rpython/translator/stm/src_stm/rpyintf.c
--- a/rpython/translator/stm/src_stm/rpyintf.c
+++ b/rpython/translator/stm/src_stm/rpyintf.c
@@ -63,6 +63,9 @@
 }
 
 static unsigned long stm_regular_length_limit = ULONG_MAX;
+static volatile int break_please = 0;
+
+static void reached_safe_point(void);
 
 void stm_add_atomic(long delta)
 {
@@ -106,6 +109,9 @@
     assert(d->reads_size_limit_nonatomic == 0);
 #endif
 
+  if (break_please)
+    reached_safe_point();
+
   return d->count_reads > d->reads_size_limit;
 }
 
@@ -173,6 +179,9 @@
       if (!d->atomic)
         BeginTransaction(&_jmpbuf);
 
+      if (break_please)
+        reached_safe_point();
+
       /* invoke the callback in the new transaction */
       result = callback(arg, counter);
 
@@ -192,6 +201,53 @@
   PYPY_DEBUG_STOP("stm-perform-transaction");
 }
 
+static struct tx_descriptor *in_single_thread = NULL;  /* for debugging */
+
+void stm_start_single_thread(void)
+{
+  /* Called by the GC, just after a minor collection, when we need to do
+     a major collection.  When it returns, it acquired the "write lock"
+     which prevents any other thread from running a transaction. */
+  int err;
+  break_please = 1;
+  err = pthread_rwlock_unlock(&rwlock_in_transaction);
+  assert(err == 0);
+  err = pthread_rwlock_wrlock(&rwlock_in_transaction);
+  assert(err == 0);
+  break_please = 0;
+
+  assert(in_single_thread == NULL);
+  in_single_thread = thread_descriptor;
+  assert(in_single_thread != NULL);
+}
+
+void stm_stop_single_thread(void)
+{
+  int err;
+
+  assert(in_single_thread == thread_descriptor);
+  in_single_thread = NULL;
+
+  err = pthread_rwlock_unlock(&rwlock_in_transaction);
+  assert(err == 0);
+  err = pthread_rwlock_rdlock(&rwlock_in_transaction);
+  assert(err == 0);
+}
+
+static void reached_safe_point(void)
+{
+  int err;
+  struct tx_descriptor *d = thread_descriptor;
+  assert(in_single_thread != d);
+  if (d->active)
+    {
+      err = pthread_rwlock_unlock(&rwlock_in_transaction);
+      assert(err == 0);
+      err = pthread_rwlock_rdlock(&rwlock_in_transaction);
+      assert(err == 0);
+    }
+}
+
 void stm_abort_and_retry(void)
 {
   AbortTransaction(4);    /* manual abort */
diff --git a/rpython/translator/stm/test/test_stmgcintf.c 
b/rpython/translator/stm/test/test_stmgcintf.c
--- a/rpython/translator/stm/test/test_stmgcintf.c
+++ b/rpython/translator/stm/test/test_stmgcintf.c
@@ -344,6 +344,22 @@
 
 /************************************************************/
 
+void single_thread_1(void)
+{
+    stm_start_single_thread();
+    stm_stop_single_thread();
+    stm_start_single_thread();
+    stm_stop_single_thread();
+    /* check that the assert() included in these functions don't trigger */
+}
+
+void test_single_thread(void)
+{
+    run_in_transaction(single_thread_1, '.');
+}
+
+/************************************************************/
+
 
 #define XTEST(name)  if (!strcmp(argv[1], #name)) { test_##name(); return 0; }
 
@@ -361,6 +377,7 @@
     XTEST(duplicator);
     XTEST(try_inevitable);
     XTEST(should_break_transaction);
+    XTEST(single_thread);
     printf("bad test name\n");
     return 1;
 }
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to