Author: Armin Rigo <[email protected]>
Branch:
Changeset: r51744:80d054b4615d
Date: 2012-01-24 22:07 +0100
http://bitbucket.org/pypy/pypy/changeset/80d054b4615d/
Log: Test and fix for "Ambiguous low-level helper specialization" when
the same RPython program contains several calls to
start_new_thread().
diff --git a/pypy/module/thread/ll_thread.py b/pypy/module/thread/ll_thread.py
--- a/pypy/module/thread/ll_thread.py
+++ b/pypy/module/thread/ll_thread.py
@@ -4,7 +4,7 @@
import py
from pypy.rlib import jit, rgc
from pypy.rlib.debug import ll_assert
-from pypy.rlib.objectmodel import we_are_translated
+from pypy.rlib.objectmodel import we_are_translated, specialize
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.tool import rffi_platform
from pypy.tool import autopath
@@ -85,6 +85,7 @@
def allocate_lock():
return Lock(allocate_ll_lock())
[email protected](0)
def ll_start_new_thread(func):
ident = c_thread_start(func)
if ident == -1:
@@ -97,6 +98,7 @@
def get_ident():
return rffi.cast(lltype.Signed, c_thread_get_ident())
[email protected](0)
def start_new_thread(x, y):
"""In RPython, no argument can be passed. You have to use global
variables to pass information to the new thread. That's not very
diff --git a/pypy/module/thread/test/test_ll_thread.py
b/pypy/module/thread/test/test_ll_thread.py
--- a/pypy/module/thread/test/test_ll_thread.py
+++ b/pypy/module/thread/test/test_ll_thread.py
@@ -34,72 +34,34 @@
use_threads = True
def test_start_new_thread(self):
- py.test.skip("xxx ideally, investigate why it fails randomly")
- # xxx but in practice start_new_thread() is also tested by the
- # next test, and it's a mess to test start_new_thread() without
- # the proper GIL to protect the GC
import time
class State:
pass
state = State()
- class Z:
- def __init__(self, value):
- self.value = value
- def __del__(self):
- state.freed_counter += 1
-
- def bootstrap():
- state.my_thread_ident = state.z.ident = get_ident()
- assert state.my_thread_ident == get_ident()
- assert get_ident() == state.z.ident
- state.seen_value = state.z.value
- state.z = None
- # I think that we would need here a memory barrier in order
- # to make the test pass reliably. The issue is that the
- # main thread may see 'state.done = 1' before seeing the
- # effect of the other assignments done above. For now let's
- # emulate the write barrier by doing a system call and
- # waiting a bit...
- time.sleep(0.012)
- state.done = 1
-
- def g(i):
- state.z = Z(i)
- return start_new_thread(bootstrap, ())
- g._dont_inline_ = True
+ def bootstrap1():
+ state.my_thread_ident1 = get_ident()
+ def bootstrap2():
+ state.my_thread_ident2 = get_ident()
def f():
- main_ident = get_ident()
- assert main_ident == get_ident()
- state.freed_counter = 0
- for i in range(50):
- state.done = 0
- state.seen_value = 0
- ident = g(i)
- gc.collect()
- willing_to_wait_more = 1000
- while not state.done:
- willing_to_wait_more -= 1
- if not willing_to_wait_more:
- raise Exception("thread didn't start?")
- time.sleep(0.01)
- assert state.my_thread_ident != main_ident
- assert state.my_thread_ident == ident
- assert state.seen_value == i
- # try to force Boehm to do some freeing
- for i in range(3):
- gc.collect()
- return state.freed_counter
+ state.my_thread_ident1 = get_ident()
+ state.my_thread_ident2 = get_ident()
+ start_new_thread(bootstrap1, ())
+ start_new_thread(bootstrap2, ())
+ willing_to_wait_more = 1000
+ while (state.my_thread_ident1 == get_ident() or
+ state.my_thread_ident2 == get_ident()):
+ willing_to_wait_more -= 1
+ if not willing_to_wait_more:
+ raise Exception("thread didn't start?")
+ time.sleep(0.01)
+ return 42
fn = self.getcompiled(f, [])
- freed_counter = fn()
- print freed_counter
- if self.gcpolicy == 'boehm':
- assert freed_counter > 0
- else:
- assert freed_counter == 50
+ res = fn()
+ assert res == 42
def test_gc_locking(self):
import time
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit