Author: Armin Rigo <ar...@tunes.org>
Branch: stm-gc
Changeset: r52355:a8cf7f197ec1
Date: 2012-02-10 16:10 +0100
http://bitbucket.org/pypy/pypy/changeset/a8cf7f197ec1/

Log:    Replace in_main_thread() with in_transaction().

diff --git a/pypy/rpython/memory/gc/stmgc.py b/pypy/rpython/memory/gc/stmgc.py
--- a/pypy/rpython/memory/gc/stmgc.py
+++ b/pypy/rpython/memory/gc/stmgc.py
@@ -297,7 +297,7 @@
         #
         @dont_inline
         def _stm_write_barrier_global(obj):
-            if stm_operations.in_main_thread():
+            if not stm_operations.in_transaction():
                 return obj
             # we need to find of make a local copy
             hdr = self.header(obj)
diff --git a/pypy/rpython/memory/gc/test/test_stmgc.py 
b/pypy/rpython/memory/gc/test/test_stmgc.py
--- a/pypy/rpython/memory/gc/test/test_stmgc.py
+++ b/pypy/rpython/memory/gc/test/test_stmgc.py
@@ -26,8 +26,8 @@
     def setup_size_getter(self, getsize_fn):
         self._getsize_fn = getsize_fn
 
-    def in_main_thread(self):
-        return self.threadnum == 0
+    def in_transaction(self):
+        return self.threadnum != 0
 
     def set_tls(self, tls, in_main_thread):
         assert lltype.typeOf(tls) == llmemory.Address
@@ -149,6 +149,7 @@
         self.gc.stm_operations.threadnum = threadnum
         if threadnum not in self.gc.stm_operations._tls_dict:
             self.gc.setup_thread(False)
+            self.gc.start_transaction()
     def gcsize(self, S):
         return (llmemory.raw_malloc_usage(llmemory.sizeof(self.gc.HDR)) +
                 llmemory.raw_malloc_usage(llmemory.sizeof(S)))
diff --git a/pypy/translator/stm/src_stm/et.c b/pypy/translator/stm/src_stm/et.c
--- a/pypy/translator/stm/src_stm/et.c
+++ b/pypy/translator/stm/src_stm/et.c
@@ -81,6 +81,7 @@
    if there is an inevitable transaction running */
 static volatile unsigned long global_timestamp = 2;
 static __thread struct tx_descriptor *thread_descriptor = NULL;
+static __thread struct tx_descriptor *active_thread_descriptor = NULL;
 static long (*rpython_get_size)(void*);
 
 /************************************************************/
@@ -114,7 +115,7 @@
 {
   unsigned int c;
   int i;
-  struct tx_descriptor *d = thread_descriptor;
+  struct tx_descriptor *d = active_thread_descriptor;
   d->num_spinloops[num]++;
 
   //printf("tx_spinloop(%d)\n", num);
@@ -132,11 +133,6 @@
 #endif
 }
 
-static _Bool is_main_thread(struct tx_descriptor *d)
-{
-  return d->my_lock_word == 0;
-}
-
 static _Bool is_inevitable(struct tx_descriptor *d)
 {
   return d->setjmp_buf == NULL;
@@ -268,7 +264,7 @@
 /*** increase the abort count and restart the transaction */
 static void tx_abort(int reason)
 {
-  struct tx_descriptor *d = thread_descriptor;
+  struct tx_descriptor *d = active_thread_descriptor;
   assert(!is_inevitable(d));
   d->num_aborts[reason]++;
 #ifdef RPY_STM_DEBUG_PRINT
@@ -459,12 +455,16 @@
 #define STM_READ_WORD(SIZE, TYPE)                                       \
 TYPE stm_read_int##SIZE(void* addr, long offset)                        \
 {                                                                       \
-  struct tx_descriptor *d = thread_descriptor;                          \
+  struct tx_descriptor *d = active_thread_descriptor;                   \
   volatile orec_t *o = get_orec(addr);                                  \
   owner_version_t ovt;                                                  \
                                                                         \
   assert(sizeof(TYPE) == SIZE);                                         \
                                                                         \
+  /* XXX try to remove this check from the main path */                 \
+  if (d == NULL)                                                        \
+    return *(TYPE *)(((char *)addr) + offset);                          \
+                                                                        \
   if ((o->tid & GCFLAG_WAS_COPIED) != 0)                                \
     {                                                                   \
       /* Look up in the thread-local dictionary. */                     \
@@ -477,10 +477,6 @@
     not_found:;                                                         \
     }                                                                   \
                                                                         \
-  /* XXX try to remove this check from the main path */                 \
-  if (is_main_thread(d))                                                \
-    return *(TYPE *)(((char *)addr) + offset);                          \
-                                                                        \
   STM_DO_READ(TYPE tmp = *(TYPE *)(((char *)addr) + offset));           \
   return tmp;                                                           \
 }
@@ -492,11 +488,11 @@
 
 void stm_copy_transactional_to_raw(void *src, void *dst, long size)
 {
-  struct tx_descriptor *d = thread_descriptor;
+  struct tx_descriptor *d = active_thread_descriptor;
   volatile orec_t *o = get_orec(src);
   owner_version_t ovt;
 
-  assert(!is_main_thread(d));
+  assert(d != NULL);
 
   /* don't copy the header */
   src = ((char *)src) + sizeof(orec_t);
@@ -507,9 +503,10 @@
 }
 
 
-static struct tx_descriptor *descriptor_init(_Bool is_main_thread)
+static struct tx_descriptor *descriptor_init()
 {
   assert(thread_descriptor == NULL);
+  assert(active_thread_descriptor == NULL);
   if (1)  /* for hg diff */
     {
       struct tx_descriptor *d = malloc(sizeof(struct tx_descriptor));
@@ -519,21 +516,15 @@
       PYPY_DEBUG_START("stm-init");
 #endif
 
-      if (is_main_thread)
-        {
-          d->my_lock_word = 0;
-        }
-      else
-        {
-          /* initialize 'my_lock_word' to be a unique negative number */
-          d->my_lock_word = (owner_version_t)d;
-          if (!IS_LOCKED(d->my_lock_word))
-            d->my_lock_word = ~d->my_lock_word;
-          assert(IS_LOCKED(d->my_lock_word));
-        }
+      /* initialize 'my_lock_word' to be a unique negative number */
+      d->my_lock_word = (owner_version_t)d;
+      if (!IS_LOCKED(d->my_lock_word))
+        d->my_lock_word = ~d->my_lock_word;
+      assert(IS_LOCKED(d->my_lock_word));
       /*d->spinloop_counter = (unsigned int)(d->my_lock_word | 1);*/
 
       thread_descriptor = d;
+      /* active_thread_descriptor stays NULL */
 
 #ifdef RPY_STM_DEBUG_PRINT
       if (PYPY_HAVE_DEBUG_PRINTS) fprintf(PYPY_DEBUG_FILE, "thread %lx 
starting\n",
@@ -548,6 +539,7 @@
 {
   struct tx_descriptor *d = thread_descriptor;
   assert(d != NULL);
+  assert(active_thread_descriptor == NULL);
 
   thread_descriptor = NULL;
 
@@ -593,12 +585,13 @@
   assert(d != NULL);
   d->setjmp_buf = buf;
   d->start_time = (/*d->last_known_global_timestamp*/ global_timestamp) & ~1;
+  active_thread_descriptor = d;
 }
 
 static long commit_transaction(void)
 {
-  struct tx_descriptor *d = thread_descriptor;
-  assert(!is_main_thread(d));
+  struct tx_descriptor *d = active_thread_descriptor;
+  assert(d != NULL);
 
   // if I don't have writes, I'm committed
   if (!redolog_any_entry(&d->redolog))
@@ -612,6 +605,7 @@
         }
       d->num_commits++;
       common_cleanup(d);
+      active_thread_descriptor = NULL;
       return d->start_time;
     }
 
@@ -657,6 +651,7 @@
 
   // reset all lists
   common_cleanup(d);
+  active_thread_descriptor = NULL;
   return d->end_time;
 }
 
@@ -666,6 +661,7 @@
   jmp_buf _jmpbuf;
   volatile long v_counter = 0;
   long counter;
+  assert(active_thread_descriptor == NULL);
   setjmp(_jmpbuf);
   begin_transaction(&_jmpbuf);
   counter = v_counter;
@@ -681,8 +677,8 @@
      global_timestamp and global_timestamp cannot be incremented
      by another thread.  We set the lowest bit in global_timestamp
      to 1. */
-  struct tx_descriptor *d = thread_descriptor;
-  if (d == NULL || is_main_thread(d))
+  struct tx_descriptor *d = active_thread_descriptor;
+  if (d == NULL)
     return;
 
 #ifdef RPY_STM_DEBUG_PRINT
@@ -742,7 +738,10 @@
 {
   struct tx_descriptor *d = thread_descriptor;
   if (d == NULL)
+    return -1;
+  if (active_thread_descriptor == NULL)
     return 0;
+  assert(d == active_thread_descriptor);
   if (!is_inevitable(d))
     return 1;
   else
@@ -756,9 +755,10 @@
 }
 
 
-void stm_set_tls(void *newtls, long is_main_thread)
+void stm_set_tls(void *newtls, long in_main_thread)
 {
-  struct tx_descriptor *d = descriptor_init(is_main_thread);
+  /* 'in_main_thread' is ignored so far */
+  struct tx_descriptor *d = descriptor_init();
   d->rpython_tls_object = newtls;
 }
 
@@ -785,7 +785,8 @@
 
 void stm_tldict_add(void *key, void *value)
 {
-  struct tx_descriptor *d = thread_descriptor;
+  struct tx_descriptor *d = active_thread_descriptor;
+  assert(d != NULL);
   redolog_insert(&d->redolog, key, value);
 }
 
@@ -806,10 +807,25 @@
   rpython_get_size = getsize_fn;
 }
 
-long stm_in_main_thread(void)
+long stm_in_transaction(void)
 {
-  struct tx_descriptor *d = thread_descriptor;
-  return is_main_thread(d);
+  struct tx_descriptor *d = active_thread_descriptor;
+  return d != NULL;
+}
+
+void _stm_activate_transaction(long activate)
+{
+  assert(thread_descriptor != NULL);
+  if (activate)
+    {
+      assert(active_thread_descriptor == NULL);
+      active_thread_descriptor = thread_descriptor;
+    }
+  else
+    {
+      assert(active_thread_descriptor != NULL);
+      active_thread_descriptor = NULL;
+    }
 }
 
 #endif  /* PYPY_NOT_MAIN_FILE */
diff --git a/pypy/translator/stm/src_stm/et.h b/pypy/translator/stm/src_stm/et.h
--- a/pypy/translator/stm/src_stm/et.h
+++ b/pypy/translator/stm/src_stm/et.h
@@ -46,6 +46,8 @@
                                      2: in an inevitable transaction */
 long stm_thread_id(void);  /* returns a unique thread id,
                               or 0 if descriptor_init() was not called */
+long stm_in_transaction(void);
+void _stm_activate_transaction(long);
 
 
 /************************************************************/
diff --git a/pypy/translator/stm/stmgcintf.py b/pypy/translator/stm/stmgcintf.py
--- a/pypy/translator/stm/stmgcintf.py
+++ b/pypy/translator/stm/stmgcintf.py
@@ -15,7 +15,9 @@
     setup_size_getter = smexternal('stm_setup_size_getter', [GETSIZE],
                                    lltype.Void)
 
-    in_main_thread = smexternal('stm_in_main_thread', [], lltype.Signed)
+    in_transaction = smexternal('stm_in_transaction', [], lltype.Signed)
+    _activate_transaction = smexternal('_stm_activate_transaction',
+                                       [lltype.Signed], lltype.Void)
 
     set_tls = smexternal('stm_set_tls', [llmemory.Address, lltype.Signed],
                          lltype.Void)
diff --git a/pypy/translator/stm/test/targetdemo.py 
b/pypy/translator/stm/test/targetdemo.py
--- a/pypy/translator/stm/test/targetdemo.py
+++ b/pypy/translator/stm/test/targetdemo.py
@@ -14,6 +14,7 @@
     LENGTH      = 5000
     USE_MEMORY  = False
     anchor      = Node(-1)
+    lock        = ll_thread.allocate_ll_lock()
 glob = Global()
 
 class Arg:
diff --git a/pypy/translator/stm/test/test_stmgcintf.py 
b/pypy/translator/stm/test/test_stmgcintf.py
--- a/pypy/translator/stm/test/test_stmgcintf.py
+++ b/pypy/translator/stm/test/test_stmgcintf.py
@@ -30,16 +30,23 @@
 
 
 class TestStmGcIntf:
+    _in_transaction = False
 
     def setup_method(self, meth):
         TLS = getattr(meth, 'TLS', DEFAULT_TLS)
         s = lltype.malloc(TLS, flavor='raw', immortal=True)
         self.tls = s
         a = llmemory.cast_ptr_to_adr(s)
-        in_main_thread = getattr(meth, 'in_main_thread', True)
+        in_transaction = getattr(meth, 'in_transaction', False)
+        in_main_thread = getattr(meth, 'in_main_thread', not in_transaction)
         stm_operations.set_tls(a, int(in_main_thread))
+        if in_transaction:
+            stm_operations._activate_transaction(1)
+            self._in_transaction = True
 
     def teardown_method(self, meth):
+        if self._in_transaction:
+            stm_operations._activate_transaction(0)
         stm_operations.del_tls()
 
     def test_set_get_del(self):
@@ -60,6 +67,7 @@
         stm_operations.tldict_add(a3, a4)
         assert stm_operations.tldict_lookup(a3) == a4
         assert stm_operations.tldict_lookup(a1) == a2
+    test_tldict.in_transaction = True
 
     def test_tldict_large(self):
         content = {}
@@ -74,7 +82,7 @@
                 a2 = rffi.cast(llmemory.Address, random.randrange(2000, 9999))
                 stm_operations.tldict_add(a1, a2)
                 content[key] = a2
-        return content
+    test_tldict_large.in_transaction = True
 
     def get_callback(self):
         def callback(tls, key, value):
@@ -101,6 +109,7 @@
         stm_operations.tldict_enum(p_callback)
         assert (seen == [(a1, a2), (a3, a4)] or
                 seen == [(a3, a4), (a1, a2)])
+    test_enum_tldict_nonempty.in_transaction = True
 
     def stm_read_case(self, flags, copied=False):
         # doesn't test STM behavior, but just that it appears to work
@@ -136,7 +145,7 @@
         assert res == 42042
         res = self.stm_read_case(stmgc.GCFLAG_WAS_COPIED, copied=True)
         assert res == 84084
-    test_stm_read_word_transactional_thread.in_main_thread = False
+    test_stm_read_word_transactional_thread.in_transaction = True
 
     def test_stm_read_int1(self):
         S2 = lltype.Struct('S2', ('hdr', stmgc.StmGC.HDR),
@@ -186,11 +195,16 @@
         #
         lltype.free(s2, flavor='raw')
         lltype.free(s1, flavor='raw')
-    test_stm_copy_transactional_to_raw.in_main_thread = False
+    test_stm_copy_transactional_to_raw.in_transaction = True
 
-    def test_in_main_thread(self):
-        assert stm_operations.in_main_thread()
+    def test_in_transaction(self):
+        assert stm_operations.in_transaction()
+    test_in_transaction.in_transaction = True
 
-    def test_not_in_main_thread(self):
-        assert not stm_operations.in_main_thread()
-    test_not_in_main_thread.in_main_thread = False
+    def test_not_in_transaction(self):
+        assert not stm_operations.in_transaction()
+    test_not_in_transaction.in_main_thread = False
+
+    def test_not_in_transaction_main(self):
+        assert not stm_operations.in_transaction()
+    test_not_in_transaction.in_main_thread = True
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to