[pypy-commit] pypy stm: Add an argument to the callback invoked by stm_perform_transaction:

arigo noreply at buildbot.pypy.org
Sun Jan 22 10:53:05 CET 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: stm
Changeset: r51626:b8a1df61795a
Date: 2012-01-22 10:51 +0100
http://bitbucket.org/pypy/pypy/changeset/b8a1df61795a/

Log:	Add an argument to the callback invoked by stm_perform_transaction:
	a retry counter starting at 0.

diff --git a/pypy/module/transaction/interp_transaction.py b/pypy/module/transaction/interp_transaction.py
--- a/pypy/module/transaction/interp_transaction.py
+++ b/pypy/module/transaction/interp_transaction.py
@@ -84,11 +84,18 @@
         self.w_callback = w_callback
         self.args = args
 
+    def register(self):
+        id = threadintf.thread_id()
+        state.pending_lists[id].append(self)
+
     def run(self):
         rstm.perform_transaction(Pending._run_in_transaction, Pending, self)
 
     @staticmethod
-    def _run_in_transaction(pending):
+    def _run_in_transaction(pending, retry_counter):
+        if retry_counter > 0:
+            self.register()   # retrying: will be done later, try others first
+            return
         if state.got_exception is not None:
             return   # return early if there is already a 'got_exception'
         try:
@@ -99,8 +106,7 @@
 
 
 def add(space, w_callback, __args__):
-    id = threadintf.thread_id()
-    state.pending_lists[id].append(Pending(w_callback, __args__))
+    Pending(w_callback, __args__).register()
 
 
 def add_list(new_pending_list):
diff --git a/pypy/rlib/rstm.py b/pypy/rlib/rstm.py
--- a/pypy/rlib/rstm.py
+++ b/pypy/rlib/rstm.py
@@ -10,13 +10,13 @@
 
 @specialize.memo()
 def _get_stm_callback(func, argcls):
-    def _stm_callback(llarg):
+    def _stm_callback(llarg, retry_counter):
         if we_are_translated():
             llarg = rffi.cast(rclass.OBJECTPTR, llarg)
             arg = cast_base_ptr_to_instance(argcls, llarg)
         else:
             arg = lltype.TLS.stm_callback_arg
-        res = func(arg)
+        res = func(arg, retry_counter)
         assert res is None
         return lltype.nullptr(rffi.VOIDP.TO)
     return _stm_callback
diff --git a/pypy/rlib/test/test_rstm.py b/pypy/rlib/test/test_rstm.py
--- a/pypy/rlib/test/test_rstm.py
+++ b/pypy/rlib/test/test_rstm.py
@@ -7,7 +7,7 @@
 class Arg(object):
     _alloc_nonmovable_ = True
 
-def setx(arg):
+def setx(arg, retry_counter):
     debug_print(arg.x)
     assert rstm.debug_get_state() == 1
     if arg.x == 303:
diff --git a/pypy/translator/stm/_rffi_stm.py b/pypy/translator/stm/_rffi_stm.py
--- a/pypy/translator/stm/_rffi_stm.py
+++ b/pypy/translator/stm/_rffi_stm.py
@@ -32,7 +32,7 @@
 stm_write_word = llexternal('stm_write_word', [SignedP, lltype.Signed],
                             lltype.Void)
 
-CALLBACK = lltype.Ptr(lltype.FuncType([rffi.VOIDP], rffi.VOIDP))
+CALLBACK = lltype.Ptr(lltype.FuncType([rffi.VOIDP, lltype.Signed], rffi.VOIDP))
 stm_perform_transaction = llexternal('stm_perform_transaction',
                                      [CALLBACK, rffi.VOIDP], rffi.VOIDP)
 
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
@@ -622,16 +622,20 @@
   return d->end_time;
 }
 
-void* stm_perform_transaction(void*(*callback)(void*), void *arg)
+void* stm_perform_transaction(void*(*callback)(void*, long), void *arg)
 {
   void *result;
   jmp_buf _jmpbuf;
+  volatile long v_counter = 0;
+  long counter;
   /* you need to call descriptor_init() before calling
      stm_perform_transaction() */
   assert(thread_descriptor != NULL_TX);
   setjmp(_jmpbuf);
   begin_transaction(&_jmpbuf);
-  result = callback(arg);
+  counter = v_counter;
+  v_counter = counter + 1;
+  result = callback(arg, counter);
   commit_transaction();
   return result;
 }
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
@@ -22,7 +22,7 @@
 
 void stm_descriptor_init(void);
 void stm_descriptor_done(void);
-void* stm_perform_transaction(void*(*)(void*), void*);
+void* stm_perform_transaction(void*(*)(void*, long), void*);
 long stm_read_word(long* addr);
 void stm_write_word(long* addr, long val);
 void stm_try_inevitable(STM_CCHARP1(why));
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
@@ -20,7 +20,7 @@
     _alloc_nonmovable_ = True
 
 
-def add_at_end_of_chained_list(arg):
+def add_at_end_of_chained_list(arg, retry_counter):
     node = arg.anchor
     value = arg.value
     x = Node(value)
@@ -52,7 +52,7 @@
     print "check ok!"
 
 
-def increment_done(arg):
+def increment_done(arg, retry_counter):
     print "thread done."
     glob.done += 1
 
diff --git a/pypy/translator/stm/test/test_funcgen.py b/pypy/translator/stm/test/test_funcgen.py
--- a/pypy/translator/stm/test/test_funcgen.py
+++ b/pypy/translator/stm/test/test_funcgen.py
@@ -93,7 +93,7 @@
     return a
 a_prebuilt = make_a_1()
 
-def _play_with_getfield(dummy_arg):
+def _play_with_getfield(dummy_arg, retry_counter):
     a = a_prebuilt
     assert a.x == -611
     assert a.c1 == '/'
@@ -106,7 +106,7 @@
     assert float(a.sb) == float(rs1b)
     return NULL
     
-def _play_with_setfields(dummy_arg):
+def _play_with_setfields(dummy_arg, retry_counter):
     a = a_prebuilt
     #
     a.x = 12871981
@@ -125,10 +125,10 @@
     a.sb = rs2b
     # read the values which have not been commited yet, but are local to the
     # transaction
-    _check_values_of_fields(dummy_arg)
+    _check_values_of_fields(dummy_arg, retry_counter)
     return NULL
 
-def _check_values_of_fields(dummy_arg):
+def _check_values_of_fields(dummy_arg, retry_counter):
     a = a_prebuilt
     assert a.x == 12871981
     assert a.c1 == '('
@@ -162,14 +162,14 @@
         array[i] = rffi.cast(lltype.typeOf(array).TO.OF, newvalues[i])
 change._annspecialcase_ = 'specialize:ll'
 
-def _play_with_getarrayitem(dummy_arg):
+def _play_with_getarrayitem(dummy_arg, retry_counter):
     check(prebuilt_array_signed, [1, 10, -1, -10, 42])
     check(prebuilt_array_char,   [chr(1), chr(10), chr(255),
                                   chr(246), chr(42)])
     return NULL
 
 
-def _play_with_setarrayitem_1(dummy_arg):
+def _play_with_setarrayitem_1(dummy_arg, retry_counter):
     change(prebuilt_array_signed, [500000, -10000000, 3])
     check(prebuilt_array_signed,  [500000, -10000000, 3, -10, 42])
     prebuilt_array_char[0] = 'A'
@@ -180,7 +180,7 @@
     check(prebuilt_array_char,    ['A', chr(10), chr(255), 'B', 'C'])
     return NULL
 
-def _play_with_setarrayitem_2(dummy_arg):
+def _play_with_setarrayitem_2(dummy_arg, retry_counter):
     check(prebuilt_array_char,    ['A', chr(10), chr(255), 'B', 'C'])
     prebuilt_array_char[1] = 'D'
     check(prebuilt_array_char,    ['A', 'D', chr(255), 'B', 'C'])
@@ -188,7 +188,7 @@
     check(prebuilt_array_char,    ['A', 'D', 'E', 'B', 'C'])
     return NULL
 
-def _play_with_setarrayitem_3(dummy_arg):
+def _play_with_setarrayitem_3(dummy_arg, retry_counter):
     check(prebuilt_array_char,    ['A', 'D', 'E', 'B', 'C'])
     return NULL
 
@@ -222,14 +222,14 @@
         array[i].y = rffi.cast(lltype.typeOf(array).TO.OF.y, newvalues2[i])
 change2._annspecialcase_ = 'specialize:ll'
 
-def _play_with_getinteriorfield(dummy_arg):
+def _play_with_getinteriorfield(dummy_arg, retry_counter):
     check2(prebuilt_array_signed_signed, [1, -1, -50], [10, 20, -30])
     check2(prebuilt_array_char_char, [chr(1), chr(255), chr(206)],
                                      [chr(10), chr(20), chr(226)])
     return NULL
 
 
-def _play_with_setinteriorfield_1(dummy_arg):
+def _play_with_setinteriorfield_1(dummy_arg, retry_counter):
     change2(prebuilt_array_signed_signed, [500000, -10000000], [102101202])
     check2(prebuilt_array_signed_signed, [500000, -10000000, -50],
                                          [102101202, 20, -30])
@@ -238,7 +238,7 @@
                                      ['b', chr(20), chr(226)])
     return NULL
 
-def _play_with_setinteriorfield_2(dummy_arg):
+def _play_with_setinteriorfield_2(dummy_arg, retry_counter):
     check2(prebuilt_array_signed_signed, [500000, -10000000, -50],
                                          [102101202, 20, -30])
     check2(prebuilt_array_char_char, ['a', chr(255), chr(206)],
@@ -253,7 +253,7 @@
 
     def test_getfield_all_sizes(self):
         def do_stm_getfield(argv):
-            _play_with_getfield(None)
+            _play_with_getfield(None, 0)
             return 0
         t, cbuilder = self.compile(do_stm_getfield)
         cbuilder.cmdexec('')
@@ -272,7 +272,7 @@
         def do_stm_getfield(argv):
             stm_descriptor_init()
             # we have a descriptor, but we don't call it in a transaction
-            _play_with_getfield(None)
+            _play_with_getfield(None, 0)
             stm_descriptor_done()
             return 0
         t, cbuilder = self.compile(do_stm_getfield)
@@ -280,7 +280,7 @@
 
     def test_setfield_all_sizes(self):
         def do_stm_setfield(argv):
-            _play_with_setfields(None)
+            _play_with_setfields(None, 0)
             return 0
         t, cbuilder = self.compile(do_stm_setfield)
         cbuilder.cmdexec('')
@@ -301,7 +301,7 @@
     def test_setfield_all_sizes_outside_transaction(self):
         def do_stm_setfield(argv):
             stm_descriptor_init()
-            _play_with_setfields(None)
+            _play_with_setfields(None, 0)
             stm_descriptor_done()
             return 0
         t, cbuilder = self.compile(do_stm_setfield)
@@ -309,7 +309,7 @@
 
     def test_getarrayitem_all_sizes(self):
         def do_stm_getarrayitem(argv):
-            _play_with_getarrayitem(None)
+            _play_with_getarrayitem(None, 0)
             return 0
         t, cbuilder = self.compile(do_stm_getarrayitem)
         cbuilder.cmdexec('')
@@ -327,9 +327,9 @@
 
     def test_setarrayitem_all_sizes(self):
         def do_stm_setarrayitem(argv):
-            _play_with_setarrayitem_1(None)
-            _play_with_setarrayitem_2(None)
-            _play_with_setarrayitem_3(None)
+            _play_with_setarrayitem_1(None, 0)
+            _play_with_setarrayitem_2(None, 0)
+            _play_with_setarrayitem_3(None, 0)
             return 0
         t, cbuilder = self.compile(do_stm_setarrayitem)
         cbuilder.cmdexec('')
@@ -351,7 +351,7 @@
 
     def test_getinteriorfield_all_sizes(self):
         def do_stm_getinteriorfield(argv):
-            _play_with_getinteriorfield(None)
+            _play_with_getinteriorfield(None, 0)
             return 0
         t, cbuilder = self.compile(do_stm_getinteriorfield)
         cbuilder.cmdexec('')
@@ -369,8 +369,8 @@
 
     def test_setinteriorfield_all_sizes(self):
         def do_stm_setinteriorfield(argv):
-            _play_with_setinteriorfield_1(None)
-            _play_with_setinteriorfield_2(None)
+            _play_with_setinteriorfield_1(None, 0)
+            _play_with_setinteriorfield_2(None, 0)
             return 0
         t, cbuilder = self.compile(do_stm_setinteriorfield)
         cbuilder.cmdexec('')
diff --git a/pypy/translator/stm/test/test_llstm.py b/pypy/translator/stm/test/test_llstm.py
--- a/pypy/translator/stm/test/test_llstm.py
+++ b/pypy/translator/stm/test/test_llstm.py
@@ -19,8 +19,9 @@
 rs1b = r_singlefloat(40.121)
 rs2b = r_singlefloat(-9e9)
 
-def callback1(a):
+def callback1(a, retry_counter):
     a = rffi.cast(lltype.Ptr(A), a)
+    assert retry_counter == a.y      # non-transactionally
     assert a.x == -611
     assert a.c1 == '/'
     assert a.c2 == '\\'
@@ -76,7 +77,7 @@
     assert a.y == 10
     lltype.free(a, flavor='raw')
 
-def callback2(a):
+def callback2(a, retry_counter):
     a = rffi.cast(lltype.Ptr(A), a)
     assert a.x == -611
     assert a.c1 == '&'
diff --git a/pypy/translator/stm/test/test_rffi_stm.py b/pypy/translator/stm/test/test_rffi_stm.py
--- a/pypy/translator/stm/test/test_rffi_stm.py
+++ b/pypy/translator/stm/test/test_rffi_stm.py
@@ -6,7 +6,7 @@
     stm_descriptor_done()
 
 def test_stm_perform_transaction():
-    def callback1(x):
+    def callback1(x, retry_counter):
         return lltype.nullptr(rffi.VOIDP.TO)
     stm_descriptor_init()
     stm_perform_transaction(llhelper(CALLBACK, callback1),
@@ -17,7 +17,8 @@
     A = lltype.Struct('A', ('x', lltype.Signed), ('y', lltype.Signed))
     a = lltype.malloc(A, immortal=True, flavor='raw')
     a.y = 0
-    def callback1(x):
+    def callback1(x, retry_counter):
+        assert retry_counter == a.y
         if a.y < 10:
             a.y += 1    # non-transactionally
             stm_abort_and_retry()
@@ -35,7 +36,8 @@
     a = lltype.malloc(A, immortal=True, flavor='raw')
     a.x = -611
     a.y = 0
-    def callback1(x):
+    def callback1(x, retry_counter):
+        assert retry_counter == a.y
         assert a.x == -611
         p = lltype.direct_fieldptr(a, 'x')
         p = rffi.cast(SignedP, p)
@@ -55,7 +57,7 @@
     assert a.x == 420
 
 def test_stm_debug_get_state():
-    def callback1(x):
+    def callback1(x, retry_counter):
         assert stm_debug_get_state() == 1
         stm_try_inevitable()
         assert stm_debug_get_state() == 2


More information about the pypy-commit mailing list