def f(): state.data = [] state.datalen1 = 0 state.datalen2 = 0 state.datalen3 = 0 state.datalen4 = 0 state.threadlocals = gil.GILThreadLocals() state.threadlocals.setup_threads(space) thread.gc_thread_prepare() subident = thread.start_new_thread(bootstrap, ()) mainident = thread.get_ident() runme(True) still_waiting = 3000 while len(state.data) < 2*N: debug_print(len(state.data)) if not still_waiting: raise ValueError("time out") still_waiting -= 1 if not we_are_translated(): gil.before_external_call() time.sleep(0.01) if not we_are_translated(): gil.after_external_call() debug_print("leaving!") i1 = i2 = 0 for tid, i in state.data: if tid == mainident: assert i == i1; i1 += 1 elif tid == subident: assert i == i2; i2 += 1 else: assert 0 assert i1 == N + skew assert i2 == N - skew return len(state.data)
def __init__(self, space, *args): "NOT_RPYTHON: patches space.threadlocals to use real threadlocals" from pypy.module.thread import gil MixedModule.__init__(self, space, *args) prev = space.threadlocals.getvalue() space.threadlocals = gil.GILThreadLocals() space.threadlocals.setvalue(prev)
def __init__(self, space, *args): "NOT_RPYTHON: patches space.threadlocals to use real threadlocals" from pypy.module.thread import gil MixedModule.__init__(self, space, *args) prev = space.threadlocals.getvalue() space.threadlocals = gil.GILThreadLocals() space.threadlocals.initialize(space) space.threadlocals.setvalue(prev) from pypy.module.posix.interp_posix import add_fork_hook from pypy.module.thread.os_thread import reinit_threads add_fork_hook('child', reinit_threads)
class GILTests(test_rthread.AbstractGCTestClass): use_threads = True bigtest = False def test_one_thread(self, skew=+1): from rpython.rlib.debug import debug_print if self.bigtest: N = 100000 skew *= 25000 else: N = 100 skew *= 25 space = FakeSpace() class State: pass state = State() def runme(main=False): j = 0 for i in range(N + [-skew, skew][main]): state.datalen1 += 1 # try to crash if the GIL is not state.datalen2 += 1 # correctly acquired state.data.append((thread.get_ident(), i)) state.datalen3 += 1 state.datalen4 += 1 assert state.datalen1 == len(state.data) assert state.datalen2 == len(state.data) assert state.datalen3 == len(state.data) assert state.datalen4 == len(state.data) debug_print(main, i, state.datalen4) rgil.yield_thread() assert i == j j += 1 def bootstrap(): try: runme() except Exception, e: assert 0 thread.gc_thread_die() my_gil_threadlocals = gil.GILThreadLocals(space) def f(): state.data = [] state.datalen1 = 0 state.datalen2 = 0 state.datalen3 = 0 state.datalen4 = 0 state.threadlocals = my_gil_threadlocals state.threadlocals.setup_threads(space) subident = thread.start_new_thread(bootstrap, ()) mainident = thread.get_ident() runme(True) still_waiting = 3000 while len(state.data) < 2 * N: debug_print(len(state.data)) if not still_waiting: llop.debug_print(lltype.Void, "timeout. progress: " "%d of 2*N (= %f%%)" % \ (len(state.data), 2*N, 100*len(state.data)/(2.0*N))) raise ValueError("time out") still_waiting -= 1 if not we_are_translated(): rgil.release() time.sleep(0.1) if not we_are_translated(): rgil.acquire() debug_print("leaving!") i1 = i2 = 0 for tid, i in state.data: if tid == mainident: assert i == i1 i1 += 1 elif tid == subident: assert i == i2 i2 += 1 else: assert 0 assert i1 == N + skew assert i2 == N - skew return len(state.data) fn = self.getcompiled(f, []) res = fn() assert res == 2 * N