[pypy-commit] pypy errno-again: start work on supporting GetLastError/SetLastError
arigo
noreply at buildbot.pypy.org
Fri Jan 16 12:58:41 CET 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: errno-again
Changeset: r75382:80dbb6ecf211
Date: 2015-01-16 12:58 +0100
http://bitbucket.org/pypy/pypy/changeset/80dbb6ecf211/
Log: start work on supporting GetLastError/SetLastError
diff --git a/rpython/jit/backend/llsupport/llerrno.py b/rpython/jit/backend/llsupport/llerrno.py
--- a/rpython/jit/backend/llsupport/llerrno.py
+++ b/rpython/jit/backend/llsupport/llerrno.py
@@ -17,6 +17,22 @@
else:
return 3 * WORD
+
+def get_debug_saved_lasterror(cpu):
+ return cpu._debug_errno_container[4]
+
+def set_debug_saved_lasterror(cpu, nerrno):
+ assert nerrno >= 0
+ cpu._debug_errno_container[4] = nerrno
+
+def get_rpy_lasterror_offset(cpu):
+ if cpu.translate_support_code:
+ from rpython.rlib import rthread
+ return rthread.tlfield_rpy_lasterror.getoffset()
+ else:
+ return 4 * WORD
+
+
def _fetch_addr_errno():
eci = ExternalCompilationInfo(
separate_module_sources=['''
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
@@ -3026,10 +3026,113 @@
assert result == 0 + 345678900
def test_call_release_gil_save_lasterror(self):
- XXX
+ from rpython.translator.tool.cbuild import ExternalCompilationInfo
+ from rpython.rlib.libffi import types
+ from rpython.jit.backend.llsupport import llerrno
+ #
+ if not isinstance(self.cpu, AbstractLLCPU):
+ py.test.skip("not on LLGraph")
+ if sys.platform != 'win32':
+ py.test.skip("Windows test only")
+ eci = ExternalCompilationInfo(
+ separate_module_sources=['''
+ #include <windows.h>
+ RPY_EXPORTED
+ long __stdcall test_call_release_gil_save_lasterror(
+ long a, long b, long c, long d, long e, long f, long g) {
+ SetLastError(42);
+ return (a + 10*b + 100*c + 1000*d +
+ 10000*e + 100000*f + 1000000*g);
+ }
+ '''])
+ fn_name = 'test_call_release_gil_save_lasterror'
+ func1_ptr = rffi.llexternal(fn_name, [lltype.Signed]*7, lltype.Signed,
+ compilation_info=eci, _nowrapper=True)
+ func1_adr = rffi.cast(lltype.Signed, func1_ptr)
+ calldescr = self.cpu._calldescr_dynamic_for_tests([types.slong]*7,
+ types.slong)
+ #
+ for saveerr in [rffi.RFFI_SAVE_ERRNO, # but not _LASTERROR
+ rffi.RFFI_SAVE_LASTERROR]:
+ faildescr = BasicFailDescr(1)
+ inputargs = [BoxInt() for i in range(7)]
+ i1 = BoxInt()
+ ops = [
+ ResOperation(rop.CALL_RELEASE_GIL,
+ [ConstInt(saveerr), ConstInt(func1_adr)]
+ + inputargs, 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(inputargs, ops, looptoken)
+ #
+ llerrno.set_debug_saved_lasterror(self.cpu, 24)
+ deadframe = self.cpu.execute_token(looptoken, 9, 8, 7, 6, 5, 4, 3)
+ original_result = self.cpu.get_int_value(deadframe, 0)
+ result = llerrno.get_debug_saved_lasterror(self.cpu)
+ print 'saveerr =', saveerr, ': got result =', result
+ #
+ if saveerr == rffi.RFFI_SAVE_LASTERROR:
+ assert result == 42 # from the C code
+ else:
+ assert result == 24 # not touched
+ assert original_result == 3456789
def test_call_release_gil_readsaved_lasterror(self):
- XXX
+ from rpython.translator.tool.cbuild import ExternalCompilationInfo
+ from rpython.rlib.libffi import types
+ from rpython.jit.backend.llsupport import llerrno
+ #
+ if not isinstance(self.cpu, AbstractLLCPU):
+ py.test.skip("not on LLGraph")
+ if sys.platform != 'win32':
+ py.test.skip("Windows test only")
+ eci = ExternalCompilationInfo(
+ separate_module_sources=[r'''
+ #include <stdio.h>
+ #include <errno.h>
+ RPY_EXPORTED
+ long __stdcall test_call_release_gil_readsaved_lasterror(
+ long a, long b, long c, long d, long e, long f, long g) {
+ long r = GetLastError();
+ printf("GetLastError() result: %ld\n", r);
+ r += 100 * (a + 10*b + 100*c + 1000*d +
+ 10000*e + 100000*f + 1000000*g);
+ return r;
+ }
+ '''])
+ fn_name = 'test_call_release_gil_readsaved_lasterror'
+ func1_ptr = rffi.llexternal(fn_name, [lltype.Signed]*7, lltype.Signed,
+ compilation_info=eci, _nowrapper=True)
+ func1_adr = rffi.cast(lltype.Signed, func1_ptr)
+ calldescr = self.cpu._calldescr_dynamic_for_tests([types.slong]*7,
+ types.slong)
+ #
+ for saveerr in [rffi.RFFI_READSAVED_LASTERROR]:
+ faildescr = BasicFailDescr(1)
+ inputargs = [BoxInt() for i in range(7)]
+ i1 = BoxInt()
+ ops = [
+ ResOperation(rop.CALL_RELEASE_GIL,
+ [ConstInt(saveerr), ConstInt(func1_adr)]
+ + inputargs, 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(inputargs, ops, looptoken)
+ #
+ llerrno.set_debug_saved_lasterror(self.cpu, 24)
+ deadframe = self.cpu.execute_token(looptoken, 9, 8, 7, 6, 5, 4, 3)
+ result = self.cpu.get_int_value(deadframe, 0)
+ assert llerrno.get_debug_saved_lasterror(self.cpu) == 24
+ #
+ assert result == 24 + 345678900
def test_guard_not_invalidated(self):
cpu = self.cpu
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -7,6 +7,8 @@
from rpython.rlib import jit
from rpython.translator.platform import platform
+WIN32 = os.name == "nt"
+
class CConstantErrno(CConstant):
# these accessors are used when calling get_errno() or set_errno()
@@ -109,6 +111,9 @@
@specialize.call_location()
def _errno_before(save_err):
+ if WIN32 and (save_err & rffi.RFFI_READSAVED_LASTERROR):
+ from rpython.rlib import rthread, rwin32
+ rwin32._SetLastError(rthread.tlfield_rpy_lasterror.getraw())
if save_err & rffi.RFFI_READSAVED_ERRNO:
from rpython.rlib import rthread
_set_errno(rthread.tlfield_rpy_errno.getraw())
@@ -120,6 +125,9 @@
if save_err & rffi.RFFI_SAVE_ERRNO:
from rpython.rlib import rthread
rthread.tlfield_rpy_errno.setraw(_get_errno())
+ if WIN32 and (save_err & rffi.RFFI_SAVE_LASTERROR):
+ from rpython.rlib import rthread, rwin32
+ rthread.tlfield_rpy_lasterror.setraw(rwin32._GetLastError())
if os.name == 'nt':
diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py
--- a/rpython/rlib/rwin32.py
+++ b/rpython/rlib/rwin32.py
@@ -123,12 +123,6 @@
_SetLastError = winexternal('SetLastError', [DWORD], lltype.Void,
_nowrapper=True, sandboxsafe=True)
- def GetLastError_real():
- return rffi.cast(lltype.Signed, _GetLastError())
-
- def SetLastError_real(err):
- _SetLastError(rffi.cast(DWORD, err))
-
def GetLastError_saved():
from rpython.rlib import rthread
return rffi.cast(lltype.Signed, rthread.tlfield_rpy_lasterror.getraw())
diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py
--- a/rpython/rtyper/lltypesystem/rffi.py
+++ b/rpython/rtyper/lltypesystem/rffi.py
@@ -64,8 +64,8 @@
RFFI_ZERO_ERRNO_BEFORE = 4 # copy the value 0 into real errno before call
RFFI_FULL_ERRNO = RFFI_SAVE_ERRNO | RFFI_READSAVED_ERRNO
RFFI_FULL_ERRNO_ZERO = RFFI_SAVE_ERRNO | RFFI_ZERO_ERRNO_BEFORE
-RFFI_SAVE_LASTERROR = 8 # XXX implement me!
-RFFI_READSAVED_LASTERROR = 16 # XXX implement me!
+RFFI_SAVE_LASTERROR = 8 # win32: save GetLastError() after the call
+RFFI_READSAVED_LASTERROR = 16 # win32: call SetLastError() before the call
RFFI_FULL_LASTERROR = RFFI_SAVE_LASTERROR | RFFI_READSAVED_LASTERROR
RFFI_ERR_NONE = 0
RFFI_ERR_ALL = RFFI_FULL_ERRNO | RFFI_FULL_LASTERROR
More information about the pypy-commit
mailing list