Author: Armin Rigo <[email protected]>
Branch: errno-again
Changeset: r75338:1aeb4e18a1a3
Date: 2015-01-15 11:33 +0100
http://bitbucket.org/pypy/pypy/changeset/1aeb4e18a1a3/

Log:    rffi.RFFI_READSAVED_ERRNO

diff --git a/rpython/jit/backend/llsupport/callbuilder.py 
b/rpython/jit/backend/llsupport/callbuilder.py
--- a/rpython/jit/backend/llsupport/callbuilder.py
+++ b/rpython/jit/backend/llsupport/callbuilder.py
@@ -50,9 +50,10 @@
         self.prepare_arguments()
         self.push_gcmap_for_call_release_gil()
         self.call_releasegil_addr_and_move_real_arguments(fastgil)
+        self.write_real_errno(save_err)
         self.emit_raw_call()
         self.restore_stack_pointer()
-        self.save_errno(save_err)
+        self.read_real_errno(save_err)
         self.move_real_result_and_call_reacqgil_addr(fastgil)
         self.pop_gcmap()
         self.load_result()
@@ -63,7 +64,10 @@
     def move_real_result_and_call_reacqgil_addr(self, fastgil):
         raise NotImplementedError
 
-    def save_errno(self, save_err):
+    def write_real_errno(self, save_err):
+        raise NotImplementedError
+
+    def read_real_errno(self, save_err):
         raise NotImplementedError
 
     def select_call_release_gil_mode(self):
diff --git a/rpython/jit/backend/test/runner_test.py 
b/rpython/jit/backend/test/runner_test.py
--- a/rpython/jit/backend/test/runner_test.py
+++ b/rpython/jit/backend/test/runner_test.py
@@ -2961,7 +2961,45 @@
                 assert result == 24      # not touched
 
     def test_call_release_gil_readsaved_errno(self):
-        XXX
+        from rpython.translator.tool.cbuild import ExternalCompilationInfo
+        from rpython.rlib.libffi import types
+        from rpython.jit.backend.llsupport import llerrno
+        #
+        eci = ExternalCompilationInfo(
+            separate_module_sources=[r'''
+                #include <stdio.h>
+                #include <errno.h>
+                RPY_EXPORTED int test_call_release_gil_readsaved_errno(void) {
+                    int r = errno;
+                    printf("read saved errno: %d\n", r);
+                    return r;
+                }
+            '''])
+        fn_name = 'test_call_release_gil_readsaved_errno'
+        func1_ptr = rffi.llexternal(fn_name, [], rffi.INT,
+                                    compilation_info=eci, _nowrapper=True)
+        func1_adr = rffi.cast(lltype.Signed, func1_ptr)
+        calldescr = self.cpu._calldescr_dynamic_for_tests([], types.sint32)
+        #
+        for saveerr in [rffi.RFFI_READSAVED_ERRNO]:
+            faildescr = BasicFailDescr(1)
+            i1 = BoxInt()
+            ops = [
+                ResOperation(rop.CALL_RELEASE_GIL,
+                             [ConstInt(saveerr), ConstInt(func1_adr)], i1,
+                             descr=calldescr),
+                ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
+                ResOperation(rop.FINISH, [i1], None, descr=BasicFinalDescr(0))
+            ]
+            ops[-2].setfailargs([])
+            looptoken = JitCellToken()
+            self.cpu.compile_loop([], ops, looptoken)
+            #
+            llerrno.set_debug_saved_errno(self.cpu, 24)
+            deadframe = self.cpu.execute_token(looptoken)
+            result = self.cpu.get_int_value(deadframe, 0)
+            assert llerrno.get_debug_saved_errno(self.cpu) == 24
+            assert result == 24
 
     def test_call_release_gil_zero_errno_before(self):
         XXX
diff --git a/rpython/jit/backend/x86/callbuilder.py 
b/rpython/jit/backend/x86/callbuilder.py
--- a/rpython/jit/backend/x86/callbuilder.py
+++ b/rpython/jit/backend/x86/callbuilder.py
@@ -149,7 +149,21 @@
         if not we_are_translated():        # for testing: we should not access
             self.mc.ADD(ebp, imm(1))       # ebp any more
 
-    def save_errno(self, save_err):
+    def write_real_errno(self, save_err):
+        if save_err & rffi.RFFI_READSAVED_ERRNO:
+            # Just before a call, read 'rpy_errno' and write it into the
+            # real 'errno'.  Most registers are free here, including the
+            # callee-saved ones, except 'ebx' and except the ones used to
+            # pass the arguments on x86-64.
+            rpy_errno = llerrno.get_rpy_errno_offset(self.asm.cpu)
+            p_errno = llerrno.get_p_errno_offset(self.asm.cpu)
+            mc = self.mc
+            mc.MOV_rs(eax.value, THREADLOCAL_OFS - self.current_esp)
+            mc.MOV_rm(edx.value, (eax.value, p_errno))
+            mc.MOV32_rm(eax.value, (eax.value, rpy_errno))
+            mc.MOV32_mr((edx.value, 0), eax.value)
+
+    def read_real_errno(self, save_err):
         if save_err & rffi.RFFI_SAVE_ERRNO:
             # Just after a call, read the real 'errno' and save a copy of
             # it inside our thread-local 'rpy_errno'.  Most registers are
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to