[pypy-svn] r46563 - in pypy/dist/pypy: rlib rpython/lltypesystem rpython/lltypesystem/test

arigo at codespeak.net arigo at codespeak.net
Fri Sep 14 09:58:15 CEST 2007


Author: arigo
Date: Fri Sep 14 09:58:13 2007
New Revision: 46563

Modified:
   pypy/dist/pypy/rlib/objectmodel.py
   pypy/dist/pypy/rpython/lltypesystem/rffi.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py
Log:
Support for a custom before()/after() pair of handlers around external
function calls.  In this approach the pair is set up at run-time, so we
get an indirect_call.  The goal is both simplicity and, for the upcoming
GIL-releasing code, minimal overhead when the app-level program does
not use threads.


Modified: pypy/dist/pypy/rlib/objectmodel.py
==============================================================================
--- pypy/dist/pypy/rlib/objectmodel.py	(original)
+++ pypy/dist/pypy/rlib/objectmodel.py	Fri Sep 14 09:58:13 2007
@@ -148,6 +148,17 @@
 def hlinvoke(repr, llcallable, *args):
     raise TypeError, "hlinvoke is meant to be rtyped and not called direclty"
 
+def invoke_around_extcall(before, after):
+    """Call before() before any external function call, and after() after.
+    At the moment only one pair before()/after() can be registered at a time.
+    """
+    if not we_are_translated():
+        raise NotImplementedError("only works after rtyping")
+    from pypy.rpython.lltypesystem import rffi
+    from pypy.rpython.annlowlevel import llhelper
+    rffi._ll_invoke_around_extcall(llhelper(rffi.AroundFnPtr, before),
+                                   llhelper(rffi.AroundFnPtr, after))
+
 
 class UnboxedValue(object):
     """A mixin class to use for classes that have exactly one field which

Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rffi.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rffi.py	Fri Sep 14 09:58:13 2007
@@ -55,6 +55,7 @@
     if _nowrapper:
         return funcptr
 
+    invoke_around_handlers = not sandboxsafe
     unrolling_arg_tps = unrolling_iterable(enumerate(args))
     def wrapper(*args):
         # XXX the next line is a workaround for the annotation bug
@@ -81,7 +82,13 @@
                     to_free = to_free + (ll_str,)
                 else:
                     to_free = to_free + (None,)
+        if invoke_around_handlers:
+            before = aroundstate.before
+            after = aroundstate.after
+            if before: before()
         result = funcptr(*real_args)
+        if invoke_around_handlers:
+            if after: after()
         if stringpolicy == 'fullauto':
             for i, tp in unrolling_arg_tps:
                 if tp is CCHARP:
@@ -92,6 +99,17 @@
     wrapper._ptr = funcptr
     return func_with_new_name(wrapper, name)
 
+AroundFnPtr = lltype.Ptr(lltype.FuncType([], lltype.Void))
+AroundState = lltype.Struct('AroundState',
+                             ('before', AroundFnPtr),
+                             ('after',  AroundFnPtr))
+aroundstate = lltype.malloc(AroundState, immortal=True, zero=True)
+def _ll_invoke_around_extcall(before, after):
+    aroundstate.before = before
+    aroundstate.after = after
+
+# ____________________________________________________________
+
 from pypy.rpython.tool.rfficache import platform
 
 TYPES = []

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py	Fri Sep 14 09:58:13 2007
@@ -359,3 +359,36 @@
 
     assert interpret(f, [], backendopt=True) == 3
     
+def test_around_extcall():
+    import os
+    from pypy.annotation import model as annmodel
+    from pypy.rlib.objectmodel import invoke_around_extcall
+    from pypy.rpython.extfuncregistry import register_external
+    read_fd, write_fd = os.pipe()
+    try:
+        # we need an external function that is not going to get wrapped around
+        # before()/after() calls, in order to call it from before()/after()...
+        def mywrite(s):
+            os.write(write_fd, s)
+        def llimpl(s):
+            s = ''.join(s.chars)
+            os.write(write_fd, s)
+        register_external(mywrite, [str], annmodel.s_None, 'll_mywrite',
+                          llfakeimpl=llimpl, sandboxsafe=True)
+
+        def before():
+            mywrite("B")
+        def after():
+            mywrite("A")
+        def f():
+            os.write(write_fd, "-")
+            invoke_around_extcall(before, after)
+            os.write(write_fd, "E")
+
+        interpret(f, [])
+        data = os.read(read_fd, 99)
+        assert data == "-BEA"
+
+    finally:
+        os.close(write_fd)
+        os.close(read_fd)



More information about the Pypy-commit mailing list