[pypy-svn] r55319 - in pypy/branch/gc+thread/pypy: interpreter module/thread module/thread/test rpython/lltypesystem

arigo at codespeak.net arigo at codespeak.net
Tue May 27 22:16:20 CEST 2008


Author: arigo
Date: Tue May 27 22:16:18 2008
New Revision: 55319

Modified:
   pypy/branch/gc+thread/pypy/interpreter/miscutils.py
   pypy/branch/gc+thread/pypy/module/thread/gil.py
   pypy/branch/gc+thread/pypy/module/thread/ll_thread.py
   pypy/branch/gc+thread/pypy/module/thread/test/support.py
   pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py
   pypy/branch/gc+thread/pypy/module/thread/threadlocals.py
   pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py
Log:
It's all slightly delicate, but overall it looks like progress, maybe.


Modified: pypy/branch/gc+thread/pypy/interpreter/miscutils.py
==============================================================================
--- pypy/branch/gc+thread/pypy/interpreter/miscutils.py	(original)
+++ pypy/branch/gc+thread/pypy/interpreter/miscutils.py	Tue May 27 22:16:18 2008
@@ -168,9 +168,6 @@
     def getmainthreadvalue(self):
         return self._value
 
-    def getGIL(self):
-        return None    # XXX temporary hack!
-
 
 class Action(object):
     """Abstract base class for actions that must be performed regularly,

Modified: pypy/branch/gc+thread/pypy/module/thread/gil.py
==============================================================================
--- pypy/branch/gc+thread/pypy/module/thread/gil.py	(original)
+++ pypy/branch/gc+thread/pypy/module/thread/gil.py	Tue May 27 22:16:18 2008
@@ -16,16 +16,16 @@
 
 class GILThreadLocals(OSThreadLocals):
     """A version of OSThreadLocals that enforces a GIL."""
-    GIL = None
+    ll_GIL = None
 
     def setup_threads(self, space):
         """Enable threads in the object space, if they haven't already been."""
-        if self.GIL is None:
+        if self.ll_GIL is None:
             try:
-                self.GIL = thread.allocate_lock_NOAUTO()
+                self.ll_GIL = thread.allocate_ll_lock()
             except thread.error:
                 raise wrap_thread_error(space, "can't allocate GIL")
-            self.GIL.acquire(True)
+            thread.acquire_NOAUTO(self.ll_GIL, True)
             self.enter_thread(space)   # setup the main thread
             # add the GIL-releasing callback as an action on the space
             space.pending_actions.append(GILReleaseAction(self))
@@ -41,23 +41,20 @@
         # test_lock_again after the global state was cleared by
         # test_compile_lock.  As a workaround, we repatch these global
         # fields systematically.
-        spacestate.GIL = self.GIL
+        spacestate.ll_GIL = self.ll_GIL
         invoke_around_extcall(before_external_call, after_external_call)
         return result
 
     def yield_thread(self):
         """Notification that the current thread is between two bytecodes:
         release the GIL for a little while."""
-        GIL = self.GIL
+        ll_GIL = self.ll_GIL
         # Other threads can run between the release() and the acquire().
         # This is a single external function so that we are sure that nothing
         # occurs between the release and the acquire, e.g. no GC operation.
-        GIL.fused_release_acquire()
+        thread.fused_release_acquire_NOAUTO(ll_GIL)
         thread.gc_thread_run()
 
-    def getGIL(self):
-        return self.GIL    # XXX temporary hack!
-
 
 class GILReleaseAction(Action):
     """An action called when the current thread is between two bytecodes
@@ -82,11 +79,11 @@
     # this function must not raise, in such a way that the exception
     # transformer knows that it cannot raise!
     e = get_errno()
-    spacestate.GIL.release()
+    thread.release_NOAUTO(spacestate.ll_GIL)
     set_errno(e)
 
 def after_external_call():
     e = get_errno()
-    spacestate.GIL.acquire(True)
+    thread.acquire_NOAUTO(spacestate.ll_GIL, True)
     thread.gc_thread_run()
     set_errno(e)

Modified: pypy/branch/gc+thread/pypy/module/thread/ll_thread.py
==============================================================================
--- pypy/branch/gc+thread/pypy/module/thread/ll_thread.py	(original)
+++ pypy/branch/gc+thread/pypy/module/thread/ll_thread.py	Tue May 27 22:16:18 2008
@@ -31,13 +31,23 @@
 )
 
 def llexternal(name, args, result, **kwds):
+    kwds.setdefault('sandboxsafe', True)
     return rffi.llexternal(name, args, result, compilation_info=eci,
                            **kwds)
 
 def _emulated_start_new_thread(func):
+    "NOT_RPYTHON"
     import thread
+    def runner():
+        if rffi.aroundstate.after:
+            rffi.aroundstate.after()
+        try:
+            func()
+        finally:
+            if rffi.aroundstate.before:
+                rffi.aroundstate.before()
     try:
-        ident = thread.start_new_thread(func, ())
+        ident = thread.start_new_thread(runner, ())
     except thread.error:
         ident = -1
     return rffi.cast(rffi.INT, ident)
@@ -45,43 +55,33 @@
 CALLBACK = lltype.Ptr(lltype.FuncType([], lltype.Void))
 c_thread_start = llexternal('RPyThreadStart', [CALLBACK], rffi.INT,
                             _callable=_emulated_start_new_thread)
-c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.INT)
+c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.INT,
+                                _nowrapper=True)    # always call directly
 
 TLOCKP = rffi.COpaquePtr('struct RPyOpaque_ThreadLock',
                           compilation_info=eci)
 
 c_thread_lock_init = llexternal('RPyThreadLockInit', [TLOCKP], lltype.Void)
 c_thread_acquirelock = llexternal('RPyThreadAcquireLock', [TLOCKP, rffi.INT],
-                                  rffi.INT)
-c_thread_releaselock = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void)
+                                  rffi.INT,
+                                  threadsafe=True)    # release the GIL
+c_thread_releaselock = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void,
+                                  threadsafe=True)    # release the GIL
 
 # another set of functions, this time in versions that don't cause the
 # GIL to be released.  To use to handle the GIL lock itself.
 c_thread_acquirelock_NOAUTO = llexternal('RPyThreadAcquireLock',
                                          [TLOCKP, rffi.INT], rffi.INT,
-                                         threadsafe=False)
+                                         _nowrapper=True)
 c_thread_releaselock_NOAUTO = llexternal('RPyThreadReleaseLock',
                                          [TLOCKP], lltype.Void,
-                                         threadsafe=False)
+                                         _nowrapper=True)
 c_thread_fused_releaseacquirelock_NOAUTO = llexternal(
      'RPyThreadFusedReleaseAcquireLock', [TLOCKP], lltype.Void,
-                                         threadsafe=False)
+                                         _nowrapper=True)
 
 def allocate_lock():
-    ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw')
-    res = c_thread_lock_init(ll_lock)
-    if res == -1:
-        lltype.free(ll_lock, flavor='raw')
-        raise error("out of resources")
-    return Lock(ll_lock)
-
-def allocate_lock_NOAUTO():
-    ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw')
-    res = c_thread_lock_init(ll_lock)
-    if res == -1:
-        lltype.free(ll_lock, flavor='raw')
-        raise error("out of resources")
-    return Lock_NOAUTO(ll_lock)
+    return Lock(allocate_ll_lock())
 
 def ll_start_new_thread(func):
     ident = c_thread_start(func)
@@ -123,26 +123,31 @@
     def __del__(self):
         lltype.free(self._lock, flavor='raw')
 
-class Lock_NOAUTO(object):
-    """A special lock that doesn't cause the GIL to be released when
-    we try to acquire it.  Used for the GIL itself."""
-
-    def __init__(self, ll_lock):
-        self._lock = ll_lock
-
-    def acquire(self, flag):
-        return bool(c_thread_acquirelock_NOAUTO(self._lock, int(flag)))
-
-    def release(self):
-        ll_assert(not self.acquire(False), "Lock_NOAUTO was not held!")
-        c_thread_releaselock_NOAUTO(self._lock)
+# ____________________________________________________________
+#
+# GIL support wrappers
 
-    def fused_release_acquire(self):
-        ll_assert(not self.acquire(False), "Lock_NOAUTO was not held!")
-        c_thread_fused_releaseacquirelock_NOAUTO(self._lock)
+def allocate_ll_lock():
+    ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw')
+    res = c_thread_lock_init(ll_lock)
+    if res == -1:
+        lltype.free(ll_lock, flavor='raw')
+        raise error("out of resources")
+    return ll_lock
 
-    def __del__(self):
-        lltype.free(self._lock, flavor='raw')
+def acquire_NOAUTO(ll_lock, flag):
+    flag = rffi.cast(rffi.INT, flag)
+    return bool(c_thread_acquirelock_NOAUTO(ll_lock, flag))
+
+def release_NOAUTO(ll_lock):
+    if not we_are_translated():
+        ll_assert(not acquire_NOAUTO(ll_lock, False), "NOAUTO lock not held!")
+    c_thread_releaselock_NOAUTO(ll_lock)
+
+def fused_release_acquire_NOAUTO(ll_lock):
+    if not we_are_translated():
+        ll_assert(not acquire_NOAUTO(ll_lock, False), "NOAUTO lock not held!")
+    c_thread_fused_releaseacquirelock_NOAUTO(ll_lock)
 
 # ____________________________________________________________
 #
@@ -164,6 +169,7 @@
     """
     if we_are_translated():
         llop.gc_thread_run(lltype.Void)
+gc_thread_run._always_inline_ = True
 
 def gc_thread_die():
     """To call just before the final GIL release done by a dying
@@ -172,3 +178,4 @@
     """
     if we_are_translated():
         llop.gc_thread_die(lltype.Void)
+gc_thread_die._always_inline_ = True

Modified: pypy/branch/gc+thread/pypy/module/thread/test/support.py
==============================================================================
--- pypy/branch/gc+thread/pypy/module/thread/test/support.py	(original)
+++ pypy/branch/gc+thread/pypy/module/thread/test/support.py	Tue May 27 22:16:18 2008
@@ -2,6 +2,7 @@
 import time, gc
 from pypy.conftest import gettestobjspace, option
 from pypy.interpreter.gateway import ObjSpace, W_Root, interp2app_temp
+from pypy.module.thread import gil
 
 
 NORMAL_TIMEOUT = 300.0   # 5 minutes
@@ -10,10 +11,9 @@
     adaptivedelay = 0.04
     limit = time.time() + delay * NORMAL_TIMEOUT
     while time.time() <= limit:
-        GIL = space.threadlocals.GIL
-        GIL.release()
+        gil.before_external_call()
         time.sleep(adaptivedelay)
-        GIL.acquire(True)
+        gil.after_external_call()
         gc.collect()
         if space.is_true(space.call_function(w_condition)):
             return

Modified: pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py
==============================================================================
--- pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py	(original)
+++ pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py	Tue May 27 22:16:18 2008
@@ -29,13 +29,13 @@
         py.test.fail("Did not raise")
 
 def test_fused():
-    l = allocate_lock_NOAUTO()
-    l.acquire(True)
-    l.fused_release_acquire()
-    could_acquire_again = l.acquire(False)
+    l = allocate_ll_lock()
+    acquire_NOAUTO(l, True)
+    fused_release_acquire_NOAUTO(l)
+    could_acquire_again = acquire_NOAUTO(l, False)
     assert not could_acquire_again
-    l.release()
-    could_acquire_again = l.acquire(False)
+    release_NOAUTO(l)
+    could_acquire_again = acquire_NOAUTO(l, False)
     assert could_acquire_again
 
 
@@ -122,13 +122,13 @@
             run._dont_inline_ = True
 
         def bootstrap():
-            state.gil.acquire(True)
+            acquire_NOAUTO(state.gil, True)
             gc_thread_run()
             z = state.z
             state.z = None
             z.run()
             gc_thread_die()
-            state.gil.release()
+            release_NOAUTO(state.gil)
 
         def g(i, j):
             state.z = Z(i, j)
@@ -139,14 +139,14 @@
             while state.z is not None:
                 assert willing_to_wait_more > 0
                 willing_to_wait_more -= 1
-                state.gil.release()
+                release_NOAUTO(state.gil)
                 time.sleep(0.005)
-                state.gil.acquire(True)
+                acquire_NOAUTO(state.gil, True)
                 gc_thread_run()
 
         def f():
-            state.gil = allocate_lock_NOAUTO()
-            state.gil.acquire(True)
+            state.gil = allocate_ll_lock()
+            acquire_NOAUTO(state.gil, True)
             state.answers = []
             state.finished = 0
             g(7, 1)
@@ -159,11 +159,11 @@
                                                       expected))
                 willing_to_wait_more -= 1
                 done = len(state.answers) == expected
-                state.gil.release()
+                release_NOAUTO(state.gil)
                 time.sleep(0.01)
-                state.gil.acquire(True)
+                acquire_NOAUTO(state.gil, True)
                 gc_thread_run()
-            state.gil.release()
+            release_NOAUTO(state.gil)
             time.sleep(0.1)
             return len(state.answers)
 

Modified: pypy/branch/gc+thread/pypy/module/thread/threadlocals.py
==============================================================================
--- pypy/branch/gc+thread/pypy/module/thread/threadlocals.py	(original)
+++ pypy/branch/gc+thread/pypy/module/thread/threadlocals.py	Tue May 27 22:16:18 2008
@@ -52,7 +52,3 @@
     def atthreadexit(self, space, exit_func, w_obj):
         ec = space.getexecutioncontext()
         ec.thread_exit_funcs.append((exit_func, w_obj))
-
-    def getGIL(self):
-        return None
-

Modified: pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py	(original)
+++ pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py	Tue May 27 22:16:18 2008
@@ -192,6 +192,9 @@
                 os.write(2,
                     "Warning: uncaught exception in callback: %%s %%s\n" %%
                     (callable_name, str(e)))
+                if not we_are_translated():
+                    import traceback
+                    traceback.print_exc()
                 result = errorcode
             if before:
                 before()
@@ -203,6 +206,7 @@
     miniglobals = locals().copy()
     miniglobals['Exception'] = Exception
     miniglobals['os'] = os
+    miniglobals['we_are_translated'] = we_are_translated
     exec source.compile() in miniglobals
     return miniglobals['wrapper']
 _make_wrapper_for._annspecialcase_ = 'specialize:memo'



More information about the Pypy-commit mailing list