Пример #1
0
 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()
Пример #2
0
 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
Пример #3
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()
Пример #4
0
 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()
Пример #5
0
 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()
Пример #6
0
 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)
Пример #7
0
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()
Пример #8
0
 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
Пример #9
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 ***'
Пример #10
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 ***'
Пример #11
0
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()
Пример #12
0
    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
Пример #13
0
    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
Пример #14
0
 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
Пример #15
0
 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
Пример #16
0
 def lock(self):
     if not self._lock.acquire(False):
         rgil.release()
         self._lock.acquire(True)
         rgil.acquire()