def _reacquire_gil_shadowstack(): # Simplified version of _reacquire_gil_asmgcc(): in shadowstack mode, # 'rpy_fastgil' contains only zero or non-zero, and this is only # called when the old value stored in 'rpy_fastgil' was non-zero # (i.e. still locked, must wait with the regular mutex) from rpython.rlib import rgil rgil.acquire()
def main(argv): rgil.release() # don't have the GIL here rgil.acquire() rgil.yield_thread() print "OK" # there is also a release/acquire pair here return 0
def do_random_work(): thread_index = glob.n_threads glob.n_threads += 1 ops = ops_by_thread[thread_index] nextop = 0 while nextop < len(ops): op = ops[nextop] nextop += 1 if op == OP_YIELD: rgil.yield_thread() check("after yield", nextop) elif op == OP_RELEASE_AND_ACQUIRE: rgil.release() check("after release_gil", nextop, expected=False) rgil.acquire() check("after acquire_gil", nextop) else: arg = ops[nextop] nextop += 1 if op == OP_BUSY: end_time = time.time() + arg * 1e-6 while time.time() < end_time: pass check("after busy work", nextop) else: time.sleep(arg * 1e-6) check("after time.sleep()", nextop) finish_lock = glob.my_locks[thread_index] finish_lock.release()
def _reacquire_gil_shadowstack(): # This used to be more complex for asmgcc. In shadowstack mode, # 'rpy_fastgil' contains only zero or non-zero, and this is only # called when the old value stored in 'rpy_fastgil' was non-zero # (i.e. still locked, must wait with the regular mutex) from rpython.rlib import rgil rgil.acquire()
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)
def _cffi_call_python(ll_externpy, ll_args): """Invoked by the helpers generated from extern "Python" in the cdef. 'externpy' is a static structure that describes which of the extern "Python" functions is called. It has got fields 'name' and 'type_index' describing the function, and more reserved fields that are initially zero. These reserved fields are set up by ffi.def_extern(), which invokes externpy_deco() below. 'args' is a pointer to an array of 8-byte entries. Each entry contains an argument. If an argument is less than 8 bytes, only the part at the beginning of the entry is initialized. If an argument is 'long double' or a struct/union, then it is passed by reference. 'args' is also used as the place to write the result to (directly, even if more than 8 bytes). In all cases, 'args' is at least 8 bytes in size. """ from pypy.module._cffi_backend.ccallback import reveal_callback from rpython.rlib import rgil rgil.acquire() rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py cerrno._errno_after(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO) if not ll_externpy.c_reserved1: # Not initialized! We don't have a space at all. # Write the error to the file descriptor stderr. try: funcname = rffi.charp2str(ll_externpy.c_name) msg = ( 'extern "Python": function %s() called, but no code was ' "attached to it yet with @ffi.def_extern(). " "Returning 0.\n" % (funcname,) ) os.write(STDERR, msg) except: pass for i in range(intmask(ll_externpy.c_size_of_result)): ll_args[i] = "\x00" else: externpython = reveal_callback(ll_externpy.c_reserved1) # the same buffer is used both for passing arguments and # the result value externpython.invoke(ll_args, ll_args) cerrno._errno_before(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO) rffi.stackcounter.stacks_counter -= 1 rgil.release()
def main(argv): check('1') rgil.release() # don't have the GIL here check('2', False) rgil.acquire() check('3') rgil.yield_thread() check('4') print "OK" # there is also a release/acquire pair here check('5') return 0
def waitfor(space, w_condition, delay=1): adaptivedelay = 0.04 limit = time.time() + delay * NORMAL_TIMEOUT while time.time() <= limit: rgil.release() time.sleep(adaptivedelay) rgil.acquire() gc.collect() if space.is_true(space.call_function(w_condition)): return adaptivedelay *= 1.05 print '*** timed out ***'
def _cffi_call_python(ll_externpy, ll_args): """Invoked by the helpers generated from extern "Python" in the cdef. 'externpy' is a static structure that describes which of the extern "Python" functions is called. It has got fields 'name' and 'type_index' describing the function, and more reserved fields that are initially zero. These reserved fields are set up by ffi.def_extern(), which invokes externpy_deco() below. 'args' is a pointer to an array of 8-byte entries. Each entry contains an argument. If an argument is less than 8 bytes, only the part at the beginning of the entry is initialized. If an argument is 'long double' or a struct/union, then it is passed by reference. 'args' is also used as the place to write the result to (directly, even if more than 8 bytes). In all cases, 'args' is at least 8 bytes in size. """ from pypy.module._cffi_backend.ccallback import reveal_callback from rpython.rlib import rgil rgil.acquire() rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py cerrno._errno_after(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO) if not ll_externpy.c_reserved1: # Not initialized! We don't have a space at all. # Write the error to the file descriptor stderr. try: funcname = rffi.charp2str(ll_externpy.c_name) msg = ("extern \"Python\": function %s() called, but no code was " "attached to it yet with @ffi.def_extern(). " "Returning 0.\n" % (funcname,)) os.write(STDERR, msg) except: pass for i in range(intmask(ll_externpy.c_size_of_result)): ll_args[i] = '\x00' else: externpython = reveal_callback(ll_externpy.c_reserved1) # the same buffer is used both for passing arguments and # the result value externpython.invoke(ll_args, ll_args) cerrno._errno_before(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO) rffi.stackcounter.stacks_counter -= 1 rgil.release()
def _reacquire_gil_asmgcc(css, old_rpy_fastgil): # Before doing an external call, 'rpy_fastgil' is initialized to # be equal to css. This function is called if we find out after # the call that it is no longer equal to css. See description # in translator/c/src/thread_pthread.c. # XXX some duplicated logic here, but note that rgil.acquire() # does more than just RPyGilAcquire() if old_rpy_fastgil == 0: # this case occurs if some other thread stole the GIL but # released it again. What occurred here is that we changed # 'rpy_fastgil' from 0 to 1, thus successfully reaquiring the # GIL. pass elif old_rpy_fastgil == 1: # 'rpy_fastgil' was (and still is) locked by someone else. # We need to wait for the regular mutex. from rpython.rlib import rgil rgil.acquire() else: # stole the GIL from a different thread that is also # currently in an external call from the jit. Attach # the 'old_rpy_fastgil' into the chained list. from rpython.memory.gctransform import asmgcroot oth = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, old_rpy_fastgil) next = asmgcroot.gcrootanchor.next oth.next = next oth.prev = asmgcroot.gcrootanchor asmgcroot.gcrootanchor.next = oth next.prev = oth # similar to trackgcroot.py:pypy_asm_stackwalk, second part: # detach the 'css' from the chained list from rpython.memory.gctransform import asmgcroot old = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css) prev = old.prev next = old.next prev.next = next next.prev = prev
def fetch_global_var_addr(self): if self.ptr: result = self.ptr else: if not we_are_translated(): FNPTR = rffi.CCallback([], rffi.VOIDP) fetch_addr = rffi.cast(FNPTR, self.fetch_addr) rgil.release() result = fetch_addr() rgil.acquire() else: # careful in translated versions: we need to call fetch_addr, # but in a GIL-releasing way. The easiest is to invoke a # llexternal() helper. result = pypy__cffi_fetch_var(self.fetch_addr) result = rffi.cast(rffi.CCHARP, result) if not result: from pypy.module._cffi_backend import ffi_obj ffierror = ffi_obj.get_ffi_error(self.space) raise oefmt(ffierror, "global variable '%s' is at address NULL", self.name) return result
def lock(self): if not self._lock.acquire(False): rgil.release() self._lock.acquire(True) rgil.acquire()