[pypy-commit] pypy default: in-progress: call_release_gil

arigo noreply at buildbot.pypy.org
Sat Aug 30 12:10:57 CEST 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r73202:0b926ccd6944
Date: 2014-08-30 12:10 +0200
http://bitbucket.org/pypy/pypy/changeset/0b926ccd6944/

Log:	in-progress: call_release_gil

diff --git a/rpython/jit/backend/arm/callbuilder.py b/rpython/jit/backend/arm/callbuilder.py
--- a/rpython/jit/backend/arm/callbuilder.py
+++ b/rpython/jit/backend/arm/callbuilder.py
@@ -81,31 +81,76 @@
                 self.mc.gen_load_int(r.ip.value, n)
                 self.mc.SUB_rr(r.sp.value, r.sp.value, r.ip.value)
 
-    def select_call_release_gil_mode(self):
-        AbstractCallBuilder.select_call_release_gil_mode(self)
+    def call_releasegil_addr_and_move_real_arguments(self, fastgil):
+        assert self.is_call_release_gil
+        assert not self.asm._is_asmgcc()
 
-    def call_releasegil_addr_and_move_real_arguments(self):
-        assert not self.asm._is_asmgcc()
-        from rpython.jit.backend.arm.regalloc import CoreRegisterManager
-        with saved_registers(self.mc,
-                            CoreRegisterManager.save_around_call_regs):
-            self.mc.BL(self.asm.releasegil_addr)
+        # Save this thread's shadowstack pointer into r7, for later comparison
+        gcrootmap = self.asm.cpu.gc_ll_descr.gcrootmap
+        if gcrootmap:
+            rst = gcrootmap.get_root_stack_top_addr()
+            self.mc.gen_load_int(r.r5.value, rst)
+            self.mc.LDR_ri(r.r7.value, r.r5.value)
+
+        # change 'rpy_fastgil' to 0 (it should be non-zero right now)
+        self.mc.DMB()
+        self.mc.gen_load_int(r.r6.value, fastgil)
+        self.mc.MOV_ri(r.ip.value, 0)
+        self.mc.STR_ri(r.ip.value, r.r6.value)
 
         if not we_are_translated():                     # for testing: we should not access
             self.mc.ADD_ri(r.fp.value, r.fp.value, 1)   # fp any more
 
-    def move_real_result_and_call_reacqgil_addr(self):
+    def move_real_result_and_call_reacqgil_addr(self, fastgil):
+        # try to reacquire the lock.  The registers r5 to r7 are still
+        # valid from before the call:
+        #     r5 == &root_stack_top
+        #     r6 == fastgil
+        #     r7 == previous value of root_stack_top
+        self.mc.LDREX(r.i3.value, r.r6.value)    # load the lock value
+        self.mc.MOV_ri(r.ip.value, 1)
+        self.mc.CMP_ri(r.r3.value, 0)            # is the lock free?
+        self.mc.STREX(r.r3.value, r.ipvalue, r.r6.value, c=cond.EQ)
+                                                 # try to claim the lock
+        self.mc.CMP_ri(r.r3.value, 0, c=cond.EQ) # did this succeed?
+        self.mc.DMB()
+        # the success of the lock acquisition is defined by
+        # 'EQ is true', or equivalently by 'r3 == 0'.
+        #
+        if self.asm.cpu.gc_ll_descr.gcrootmap:
+            # When doing a call_release_gil with shadowstack, there
+            # is the risk that the 'rpy_fastgil' was free but the
+            # current shadowstack can be the one of a different
+            # thread.  So here we check if the shadowstack pointer
+            # is still the same as before we released the GIL (saved
+            # in 'r7'), and if not, we fall back to 'reacqgil_addr'.
+            self.mc.LDR_ri(r.ip.value, r.r5.value, c=cond.EQ)
+            self.mc.CMP_rr(r.ip.value, r.r7.value, c=cond.EQ)
+            b1_location = self.mc.currpos()
+            self.mc.BKPT()                       # BEQ below
+            # there are two cases here: either EQ was false from
+            # the beginning, or EQ was true at first but the CMP
+            # made it false.  In the second case we need to
+            # release the fastgil here.  We know which case it is
+            # by checking again r3.
+            self.mc.CMP_ri(r.r3.value, 0)
+            self.mc.STR_ri(r.r3.value, r.r6.value, c=cond.EQ)
+        else:
+            b1_location = self.mc.currpos()
+            self.mc.BKPT()                       # BEQ below
+        #
         # save the result we just got
-        assert not self.asm._is_asmgcc()
         gpr_to_save, vfp_to_save = self.get_result_locs()
         with saved_registers(self.mc, gpr_to_save, vfp_to_save):
             self.mc.BL(self.asm.reacqgil_addr)
 
+        # replace b1_location with B(here, cond.EQ)
+        pmc = OverwritingBuilder(self.mc, b1_location, WORD)
+        pmc.B_offs(self.mc.currpos(), c.EQ)
+
         if not we_are_translated():                    # for testing: now we can accesss
             self.mc.SUB_ri(r.fp.value, r.fp.value, 1)  # fp again
 
-        #   for shadowstack, done for us by _reload_frame_if_necessary()
-
     def get_result_locs(self):
         raise NotImplementedError
 


More information about the pypy-commit mailing list