[pypy-commit] pypy stmgc-c7: Fight fight until I can reliably get a failure mode for weakrefs
arigo
noreply at buildbot.pypy.org
Mon Feb 2 23:38:59 CET 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c7
Changeset: r75670:5b9137e56e6b
Date: 2015-02-02 23:38 +0100
http://bitbucket.org/pypy/pypy/changeset/5b9137e56e6b/
Log: Fight fight until I can reliably get a failure mode for weakrefs
diff --git a/pypy/module/pypystm/test_pypy_c/support.py b/pypy/module/pypystm/test_pypy_c/support.py
--- a/pypy/module/pypystm/test_pypy_c/support.py
+++ b/pypy/module/pypystm/test_pypy_c/support.py
@@ -8,27 +8,66 @@
HEADER = """
import thread, pypystm
-def _run(lock, result, function, args):
+NUM_THREADS = 3
+
+_b_to_go = NUM_THREADS
+_b_done = False
+_b_lock = thread.allocate_lock()
+_b_locks = [thread.allocate_lock() for _i in range(NUM_THREADS)]
+for _bl in _b_locks:
+ _bl.acquire()
+
+class BarrierThreadsDone(Exception):
+ pass
+
+def barrier(tnum, done=False):
+ '''Waits until NUM_THREADS call this function, and then returns
+ in all these threads at once.'''
+ global _b_to_go, _b_done
+ _b_lock.acquire()
+ if done:
+ _b_done = True
+ _b_to_go -= 1
+ if _b_to_go > 0:
+ _b_lock.release()
+ _b_locks[tnum].acquire()
+ else:
+ _b_to_go = NUM_THREADS
+ for i in range(NUM_THREADS):
+ if i != tnum:
+ _b_locks[i].release()
+ _b_lock.release()
+ if _b_done:
+ raise BarrierThreadsDone
+
+def _run(tnum, lock, result, function, args):
start = pypystm.time()
try:
- while True:
- function(*args)
- if pypystm.time() - start >= 3.0:
- break
+ try:
+ while True:
+ function(*args)
+ if pypystm.time() - start >= 3.0:
+ break
+ except BarrierThreadsDone:
+ pass
result.append(1)
finally:
lock.release()
+ while len(result) != NUM_THREADS:
+ barrier(tnum, done=True)
-def run_in_threads(function, arg_thread_num=False):
+def run_in_threads(function, arg_thread_num=False, arg_class=None):
locks = []
result = []
- for i in range(3):
+ for i in range(NUM_THREADS):
lock = thread.allocate_lock()
lock.acquire()
args = ()
if arg_thread_num:
args += (i,)
- thread.start_new_thread(_run, (lock, result, function, args))
+ if arg_class:
+ args += (arg_class(),)
+ thread.start_new_thread(_run, (i, lock, result, function, args))
locks.append(lock)
for lock in locks:
lock._py3k_acquire(timeout=30)
@@ -98,6 +137,10 @@
count = self._check_count_conflicts(*args)
assert count < 500
- def check_many_conflicts(self, *args):
+ def check_MANY_conflicts(self, *args):
count = self._check_count_conflicts(*args)
assert count > 20000
+
+ def check_SOME_conflicts(self, *args):
+ count = self._check_count_conflicts(*args)
+ assert count > 1000
diff --git a/pypy/module/pypystm/test_pypy_c/test_conflict.py b/pypy/module/pypystm/test_pypy_c/test_conflict.py
--- a/pypy/module/pypystm/test_pypy_c/test_conflict.py
+++ b/pypy/module/pypystm/test_pypy_c/test_conflict.py
@@ -13,7 +13,7 @@
x.a += 1
run_in_threads(g)
#
- self.check_many_conflicts(f)
+ self.check_MANY_conflicts(f)
def test_plain_dict_access(self):
def f():
@@ -22,4 +22,25 @@
d[n] = d.get(n, 0) + 1
run_in_threads(g, arg_thread_num=True)
#
- self.check_many_conflicts(f)
+ self.check_MANY_conflicts(f)
+
+ def test_write_to_many_objects_in_order(self):
+ def f():
+ import weakref
+
+ class X(object):
+ pass
+
+ lst = [] # shared
+
+ def g(tnum):
+ if tnum == 0:
+ lst[:] = [X() for i in range(1000)]
+ barrier(tnum)
+ for x in lst:
+ x.a = 5
+ barrier(tnum)
+
+ run_in_threads(g, arg_thread_num=True)
+ #
+ self.check_SOME_conflicts(f)
diff --git a/pypy/module/pypystm/test_pypy_c/test_no_conflict.py b/pypy/module/pypystm/test_pypy_c/test_no_conflict.py
--- a/pypy/module/pypystm/test_pypy_c/test_no_conflict.py
+++ b/pypy/module/pypystm/test_pypy_c/test_no_conflict.py
@@ -1,3 +1,4 @@
+import py
from pypy.module.pypystm.test_pypy_c.support import BaseTestSTM
@@ -27,3 +28,25 @@
run_in_threads(g, arg_thread_num=True)
#
self.check_almost_no_conflict(f)
+
+ def test_weakrefs(self):
+ py.test.skip("next issue")
+ def f():
+ import weakref
+
+ class X(object):
+ pass
+
+ lst = [] # shared
+
+ def g(tnum):
+ if tnum == 0:
+ lst[:] = [X() for i in range(1000)]
+ barrier(tnum)
+ for x in lst:
+ weakref.ref(x)
+ barrier(tnum)
+
+ run_in_threads(g, arg_thread_num=True)
+ #
+ self.check_almost_no_conflict(f)
More information about the pypy-commit
mailing list