Author: Armin Rigo <ar...@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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit