def setup_threads(self, space): """Enable threads in the object space, if they haven't already been.""" if not self.ll_GIL: try: self.ll_GIL = thread.allocate_ll_lock() except thread.error: raise wrap_thread_error(space, "can't allocate GIL") thread.acquire_NOAUTO(self.ll_GIL, True) self.enter_thread(space) # setup the main thread result = True else: result = False # already set up # add the GIL-releasing callback around external function calls. # # XXX we assume a single space, but this is not quite true during # testing; for example, if you run the whole of test_lock you get # a deadlock caused by the first test's space being reused by # test_lock_again after the global state was cleared by # test_compile_lock. As a workaround, we repatch these global # fields systematically. spacestate.ll_GIL = self.ll_GIL spacestate.actionflag = space.actionflag invoke_around_extcall(before_external_call, after_external_call) return result
def after(): ll_thread.acquire_NOAUTO(state.ll_lock, True)
def before(): ll_assert(not ll_thread.acquire_NOAUTO(state.ll_lock, False), "lock not held!") ll_thread.release_NOAUTO(state.ll_lock)
def after(): debug_print("waiting...") ll_thread.acquire_NOAUTO(state.ll_lock, True) debug_print("acquired")
def before(): debug_print("releasing...") ll_assert(not ll_thread.acquire_NOAUTO(state.ll_lock, False), "lock not held!") ll_thread.release_NOAUTO(state.ll_lock) debug_print("released")
def reinit_threads(self, space): if self.ll_GIL: self.ll_GIL = thread.allocate_ll_lock() thread.acquire_NOAUTO(self.ll_GIL, True) self.enter_thread(space)
def after_external_call(): e = get_errno() thread.acquire_NOAUTO(spacestate.ll_GIL, True) thread.gc_thread_run() spacestate.after_thread_switch() set_errno(e)
def after(): ll_thread.acquire_NOAUTO(state.ll_lock, True) ll_thread.gc_thread_run()