PageRenderTime 50ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/thread/test/test_gil.py

https://bitbucket.org/pypy/pypy/
Python | 121 lines | 110 code | 11 blank | 0 comment | 13 complexity | 462bbc8ab4393d8e79b592bb1f1d4a6a MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import time
  2. from pypy.module.thread import gil
  3. from rpython.rtyper.lltypesystem.lloperation import llop
  4. from rpython.rtyper.lltypesystem import lltype
  5. from rpython.rlib import rgil
  6. from rpython.rlib.test import test_rthread
  7. from rpython.rlib import rthread as thread
  8. from rpython.rlib.objectmodel import we_are_translated
  9. class FakeEC(object):
  10. pass
  11. class FakeActionFlag(object):
  12. def register_periodic_action(self, action, use_bytecode_counter):
  13. pass
  14. def get(self):
  15. return 0
  16. def set(self, x):
  17. pass
  18. class FakeSpace(object):
  19. def __init__(self):
  20. self.actionflag = FakeActionFlag()
  21. def _freeze_(self):
  22. return True
  23. def getexecutioncontext(self):
  24. return FakeEC()
  25. def fromcache(self, key):
  26. raise NotImplementedError
  27. class GILTests(test_rthread.AbstractGCTestClass):
  28. use_threads = True
  29. bigtest = False
  30. def test_one_thread(self, skew=+1):
  31. from rpython.rlib.debug import debug_print
  32. if self.bigtest:
  33. N = 100000
  34. skew *= 25000
  35. else:
  36. N = 100
  37. skew *= 25
  38. space = FakeSpace()
  39. class State:
  40. pass
  41. state = State()
  42. def runme(main=False):
  43. j = 0
  44. for i in range(N + [-skew, skew][main]):
  45. state.datalen1 += 1 # try to crash if the GIL is not
  46. state.datalen2 += 1 # correctly acquired
  47. state.data.append((thread.get_ident(), i))
  48. state.datalen3 += 1
  49. state.datalen4 += 1
  50. assert state.datalen1 == len(state.data)
  51. assert state.datalen2 == len(state.data)
  52. assert state.datalen3 == len(state.data)
  53. assert state.datalen4 == len(state.data)
  54. debug_print(main, i, state.datalen4)
  55. rgil.yield_thread()
  56. assert i == j
  57. j += 1
  58. def bootstrap():
  59. try:
  60. runme()
  61. except Exception as e:
  62. assert 0
  63. thread.gc_thread_die()
  64. my_gil_threadlocals = gil.GILThreadLocals(space)
  65. def f():
  66. state.data = []
  67. state.datalen1 = 0
  68. state.datalen2 = 0
  69. state.datalen3 = 0
  70. state.datalen4 = 0
  71. state.threadlocals = my_gil_threadlocals
  72. state.threadlocals.setup_threads(space)
  73. subident = thread.start_new_thread(bootstrap, ())
  74. mainident = thread.get_ident()
  75. runme(True)
  76. still_waiting = 3000
  77. while len(state.data) < 2*N:
  78. debug_print(len(state.data))
  79. if not still_waiting:
  80. llop.debug_print(lltype.Void, "timeout. progress: "
  81. "%d of 2*N (= %f%%)" % \
  82. (len(state.data), 2*N, 100*len(state.data)/(2.0*N)))
  83. raise ValueError("time out")
  84. still_waiting -= 1
  85. if not we_are_translated(): rgil.release()
  86. time.sleep(0.1)
  87. if not we_are_translated(): rgil.acquire()
  88. debug_print("leaving!")
  89. i1 = i2 = 0
  90. for tid, i in state.data:
  91. if tid == mainident:
  92. assert i == i1; i1 += 1
  93. elif tid == subident:
  94. assert i == i2; i2 += 1
  95. else:
  96. assert 0
  97. assert i1 == N + skew
  98. assert i2 == N - skew
  99. return len(state.data)
  100. fn = self.getcompiled(f, [])
  101. res = fn()
  102. assert res == 2*N
  103. def test_one_thread_rev(self):
  104. self.test_one_thread(skew=-1)
  105. class TestRunDirectly(GILTests):
  106. def getcompiled(self, f, argtypes):
  107. return f
  108. class TestUsingFramework(GILTests):
  109. gcpolicy = 'generation'
  110. bigtest = True