[pypy-commit] pypy stm-thread: Fish from the history stm_perform_transaction().

arigo noreply at buildbot.pypy.org
Sun May 6 15:16:13 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: stm-thread
Changeset: r54909:61d19c0aebe3
Date: 2012-05-06 15:15 +0200
http://bitbucket.org/pypy/pypy/changeset/61d19c0aebe3/

Log:	Fish from the history stm_perform_transaction(). Now, it is the only
	way to start a non-inevitable transaction.

diff --git a/pypy/rlib/rstm.py b/pypy/rlib/rstm.py
--- a/pypy/rlib/rstm.py
+++ b/pypy/rlib/rstm.py
@@ -1,8 +1,12 @@
+import threading
 from pypy.translator.stm import stmgcintf
 from pypy.rlib.debug import ll_assert
-from pypy.rpython.lltypesystem import lltype
+from pypy.rlib.objectmodel import keepalive_until_here, specialize
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass
 from pypy.rpython.lltypesystem.lloperation import llop
-
+from pypy.rpython.annlowlevel import (cast_base_ptr_to_instance,
+                                      cast_instance_to_base_ptr,
+                                      llhelper)
 
 def before_external_call():
     llop.stm_stop_transaction(lltype.Void)
@@ -36,8 +40,31 @@
 leave_callback_call._dont_reach_me_in_del_ = True
 leave_callback_call._transaction_break_ = True
 
-def do_yield_thread():
-    stmgcintf.StmOperations.do_yield_thread()
-do_yield_thread._gctransformer_hint_close_stack_ = True
-do_yield_thread._dont_reach_me_in_del_ = True
-do_yield_thread._transaction_break_ = True
+# ____________________________________________________________
+
+ at specialize.memo()
+def _get_stm_callback(func, argcls):
+    def _stm_callback(llarg, retry_counter):
+        llop.stm_start_transaction(lltype.Void)
+        llarg = rffi.cast(rclass.OBJECTPTR, llarg)
+        arg = cast_base_ptr_to_instance(argcls, llarg)
+        try:
+            func(arg, retry_counter)
+        finally:
+            llop.stm_stop_transaction(lltype.Void)
+    return _stm_callback
+
+ at specialize.arg(0, 1)
+def perform_transaction(func, argcls, arg):
+    ll_assert(arg is None or isinstance(arg, argcls),
+              "perform_transaction: wrong class")
+    before_external_call()
+    llarg = cast_instance_to_base_ptr(arg)
+    llarg = rffi.cast(rffi.VOIDP, llarg)
+    adr_of_top = llop.gc_adr_of_root_stack_top(llmemory.Address)
+    #
+    callback = _get_stm_callback(func, argcls)
+    llcallback = llhelper(stmgcintf.StmOperations.CALLBACK_TX, callback)
+    stmgcintf.StmOperations.perform_transaction(llcallback, llarg, adr_of_top)
+    after_external_call()
+    keepalive_until_here(arg)
diff --git a/pypy/translator/stm/src_stm/core.c b/pypy/translator/stm/src_stm/core.c
--- a/pypy/translator/stm/src_stm/core.c
+++ b/pypy/translator/stm/src_stm/core.c
@@ -188,18 +188,15 @@
   d->active = 0;
 }
 
-static void tx_cleanup(struct tx_descriptor *d)
+static void tx_restart(struct tx_descriptor *d)
 {
   // release the locks and restore version numbers
   releaseAndRevertLocks(d);
+  // notifies the CPU that we're potentially in a spin loop
+  tx_spinloop(0);
   // reset all lists
   common_cleanup(d);
-}
-
-static void tx_restart(struct tx_descriptor *d)
-{
-  tx_cleanup(d);
-  tx_spinloop(0);
+  // jump back to the setjmp_buf (this call does not return)
   longjmp(*d->setjmp_buf, 1);
 }
 
@@ -542,22 +539,27 @@
 
   while (1)
     {
-      mutex_lock();
-      unsigned long curtime = get_global_timestamp(d) & ~1;
-      if (change_global_timestamp(d, curtime, curtime + 1))
+      unsigned long curtime = get_global_timestamp(d);
+      if (curtime & 1)
         {
-          d->start_time = curtime;
-          break;
+          /* already an inevitable transaction: wait */
+          tx_spinloop(6);
+          mutex_lock();
+          mutex_unlock();
         }
-      mutex_unlock();
-      tx_spinloop(6);
+      else
+        if (change_global_timestamp(d, curtime, curtime + 1))
+          {
+            d->start_time = curtime;
+            break;
+          }
     }
 }
 
 void stm_commit_transaction(void)
 {
   struct tx_descriptor *d = thread_descriptor;
-  assert(d != NULL);
+  assert(d->active != 0);
 
   // if I don't have writes, I'm committed
   if (!redolog_any_entry(&d->redolog))
@@ -740,6 +742,27 @@
   return is_inevitable(d);
 }
 
+void stm_perform_transaction(void(*callback)(void*, long), void *arg,
+                             void *save_and_restore)
+{
+  jmp_buf _jmpbuf;
+  long volatile v_counter = 0;
+  long counter;
+  void *volatile saved_value;
+  struct tx_descriptor *d = thread_descriptor;
+  assert(d->active == 0);
+  saved_value = *(void**)save_and_restore;
+  /***/
+  setjmp(_jmpbuf);
+  /***/
+  *(void**)save_and_restore = saved_value;
+  begin_transaction(&_jmpbuf);
+  counter = v_counter;
+  v_counter = counter + 1;
+  callback(arg, counter);
+  stm_commit_transaction();
+}
+
 #undef GETVERSION
 #undef GETVERSIONREF
 #undef SETVERSION
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
@@ -30,6 +30,8 @@
 long stm_in_transaction(void);
 long stm_is_inevitable(void);
 
+void stm_perform_transaction(void(*)(void*, long), void*, void*);
+
 /* these functions are declared by generated C code from pypy.rlib.rstm
    and from the GC (see llop.nop(...)) */
 extern void pypy_g__stm_thread_starting(void);
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
@@ -35,8 +35,8 @@
                          '4f': rffi.FLOAT}
 
     INIT_DONE       = lltype.Ptr(lltype.FuncType([], lltype.Void))
-    RUN_TRANSACTION = lltype.Ptr(lltype.FuncType([rffi.VOIDP, lltype.Signed],
-                                                 rffi.VOIDP))
+    CALLBACK_TX     = lltype.Ptr(lltype.FuncType([rffi.VOIDP, lltype.Signed],
+                                                 lltype.Void))
     GETSIZE         = lltype.Ptr(lltype.FuncType([llmemory.Address],
                                                  lltype.Signed))
     CALLBACK_ENUM   = lltype.Ptr(lltype.FuncType([llmemory.Address]*3,
@@ -54,8 +54,9 @@
         'stm_begin_inevitable_transaction', [], lltype.Void)
     commit_transaction = smexternal(
         'stm_commit_transaction', [], lltype.Void)
-    do_yield_thread = smexternal('stm_do_yield_thread',
-                                 [], lltype.Void)
+    perform_transaction = smexternal('stm_perform_transaction',
+                                     [CALLBACK_TX, rffi.VOIDP, llmemory.Address],
+                                     lltype.Void)
 
     # for the GC: store and read a thread-local-storage field, as well
     # as initialize and shut down the internal thread_descriptor
diff --git a/pypy/translator/stm/test/targetdemo2.py b/pypy/translator/stm/test/targetdemo2.py
--- a/pypy/translator/stm/test/targetdemo2.py
+++ b/pypy/translator/stm/test/targetdemo2.py
@@ -64,11 +64,15 @@
     def run(self):
         try:
             for value in range(glob.LENGTH):
-                add_at_end_of_chained_list(glob.anchor, value, self.index)
-                #rstm.do_yield_thread()
+                self.value = value
+                rstm.perform_transaction(ThreadRunner.run_really,
+                                         ThreadRunner, self)
         finally:
             self.finished_lock.release()
 
+    def run_really(self, retry_counter):
+        add_at_end_of_chained_list(glob.anchor, self.value, self.index)
+
 # ____________________________________________________________
 # bah, we are really missing an RPython interface to threads
 


More information about the pypy-commit mailing list