Armin Rigo avatar Armin Rigo committed a8cf7f1

Replace in_main_thread() with in_transaction().

Comments (0)

Files changed (7)

pypy/rpython/memory/gc/stmgc.py

         #
         @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)

pypy/rpython/memory/gc/test/test_stmgc.py

     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
         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)))

pypy/translator/stm/src_stm/et.c

    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*);
 
 /************************************************************/
 {
   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);
 #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;
 /*** 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
 #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. */                     \
     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;                                                           \
 }
 
 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);
 }
 
 
-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));
       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",
 {
   struct tx_descriptor *d = thread_descriptor;
   assert(d != NULL);
+  assert(active_thread_descriptor == NULL);
 
   thread_descriptor = NULL;
 
   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))
         }
       d->num_commits++;
       common_cleanup(d);
+      active_thread_descriptor = NULL;
       return d->start_time;
     }
 
 
   // reset all lists
   common_cleanup(d);
+  active_thread_descriptor = NULL;
   return d->end_time;
 }
 
   jmp_buf _jmpbuf;
   volatile long v_counter = 0;
   long counter;
+  assert(active_thread_descriptor == NULL);
   setjmp(_jmpbuf);
   begin_transaction(&_jmpbuf);
   counter = v_counter;
      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
 {
   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
 }
 
 
-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;
 }
 
 
 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);
 }
 
   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 */

pypy/translator/stm/src_stm/et.h

                                      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);
 
 
 /************************************************************/

pypy/translator/stm/stmgcintf.py

     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)

pypy/translator/stm/test/targetdemo.py

     LENGTH      = 5000
     USE_MEMORY  = False
     anchor      = Node(-1)
+    lock        = ll_thread.allocate_ll_lock()
 glob = Global()
 
 class Arg:

pypy/translator/stm/test/test_stmgcintf.py

 
 
 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):
         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 = {}
                 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):
         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
         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),
         #
         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
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.