[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