[pypy-commit] pypy stm-thread: Intermediate check-in
arigo
noreply at buildbot.pypy.org
Fri May 4 18:59:20 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: stm-thread
Changeset: r54890:1fdaa02047f0
Date: 2012-05-04 18:00 +0200
http://bitbucket.org/pypy/pypy/changeset/1fdaa02047f0/
Log: Intermediate check-in
diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -108,6 +108,7 @@
BoolOption("stm", "enable use of Software Transactional Memory",
default=False, cmdline="--stm",
requires=[("translation.gc", "stmgc"),
+ ("translation.thread", True),
("translation.continuation", False), # XXX for now
]),
BoolOption("sandbox", "Produce a fully-sandboxed executable",
diff --git a/pypy/rlib/rstm.py b/pypy/rlib/rstm.py
new file mode 100644
--- /dev/null
+++ b/pypy/rlib/rstm.py
@@ -0,0 +1,17 @@
+from pypy.translator.stm import stmgcintf
+
+
+def before_external_call():
+ stmgcintf.StmOperations.before_external_call()
+before_external_call._gctransformer_hint_cannot_collect_ = True
+before_external_call._dont_reach_me_in_del_ = True
+
+def after_external_call():
+ stmgcintf.StmOperations.after_external_call()
+after_external_call._gctransformer_hint_cannot_collect_ = True
+after_external_call._dont_reach_me_in_del_ = True
+
+def do_yield_thread():
+ stmgcintf.StmOperations.do_yield_thread()
+do_yield_thread._gctransformer_hint_close_stack_ = True
+do_yield_thread._dont_reach_me_in_del_ = True
diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -403,14 +403,10 @@
'stm_getarrayitem': LLOp(sideeffects=False, canrun=True),
'stm_getinteriorfield': LLOp(sideeffects=False, canrun=True),
'stm_become_inevitable': LLOp(),
- 'stm_enter_transactional_mode': LLOp(canrun=True, canmallocgc=True),
- 'stm_leave_transactional_mode': LLOp(canrun=True, canmallocgc=True),
'stm_writebarrier': LLOp(),
'stm_normalize_global': LLOp(),
'stm_start_transaction': LLOp(canrun=True, canmallocgc=True),
'stm_stop_transaction': LLOp(canrun=True, canmallocgc=True),
- 'stm_thread_starting': LLOp(),
- 'stm_thread_stopping': LLOp(),
# __________ address operations __________
diff --git a/pypy/rpython/memory/gc/stmgc.py b/pypy/rpython/memory/gc/stmgc.py
--- a/pypy/rpython/memory/gc/stmgc.py
+++ b/pypy/rpython/memory/gc/stmgc.py
@@ -24,7 +24,8 @@
# - Each object lives either in the shared area, or in a thread-local
# nursery. The shared area contains:
# - the prebuilt objects
-# - the small objects allocated via minimarkpage.py
+# - the small objects allocated via minimarkpage.py (XXX so far,
+# just with malloc)
# - the non-small raw-malloced objects
#
# - The GLOBAL objects are all located in the shared area.
@@ -38,27 +39,25 @@
# is not actually generational (slow when running long transactions
# or before running transactions at all).
#
-# - A few details are different depending on the running mode:
-# either "transactional" or "non-transactional". The transactional
-# mode is where we have multiple threads, in a transaction.run()
-# call. The non-transactional mode has got only the main thread.
+# - So far, the GC is always running in "transactional" mode. Later,
+# it would be possible to speed it up in case there is only one
+# (non-blocked) thread.
#
# GC Flags on objects:
#
# - GCFLAG_GLOBAL: identifies GLOBAL objects. All prebuilt objects
# start as GLOBAL; conversely, all freshly allocated objects start
-# as LOCAL. But they may switch between the two; see below.
-# All objects that are or have been GLOBAL are immortal for now
+# as LOCAL, and become GLOBAL if they survive an end-of-transaction.
+# All objects that are GLOBAL are immortal for now
# (global_collect() will be done later).
#
# - GCFLAG_WAS_COPIED: means that the object is either a LOCAL COPY
-# or, if GLOBAL, then it has or had at least one LOCAL COPY. Used
-# in transactional mode only; see below.
+# or, if GLOBAL, then it has or had at least one LOCAL COPY. See
+# below.
#
# - GCFLAG_VISITED: used during collections to flag objects found to be
# surviving. Between collections, it must be set on the LOCAL COPY
-# objects or the ones from 'mt_global_turned_local' (see below), and
-# only on them.
+# objects, and only on them.
#
# - GCFLAG_HAS_SHADOW: set on nursery objects whose id() or identityhash()
# was taken. Means that we already have a corresponding object allocated
@@ -69,51 +68,34 @@
# When the mutator (= the program outside the GC) wants to write to an
# object, stm_writebarrier() does something special on GLOBAL objects:
#
-# - In non-transactional mode, the write barrier turns the object LOCAL
-# and add it in the list 'main_thread_tls.mt_global_turned_local'.
-# This list contains all previously-GLOBAL objects that have been
-# modified. [XXX:TODO]Objects turned LOCAL are changed back to GLOBAL and
-# removed from 'mt_global_turned_local' by the next collection,
-# unless they are also found in the stack (the reason being that if
-# they are in the stack and stm_writebarrier() has already been
-# called, then it might not be called a second time if they are
-# changed again after collection).
-#
-# - In transactional mode, the write barrier creates a LOCAL COPY of
-# the object and returns it (or, if already created by the same
-# transaction, finds it again). The list of LOCAL COPY objects has
-# a role similar to 'mt_global_turned_local', but is maintained by C
-# code (see tldict_lookup()).
+# - In transactional mode (always for now), the write barrier creates
+# a LOCAL COPY of the object and returns it (or, if already created by
+# the same transaction, finds it again). The mapping from GLOBAL to
+# LOCAL COPY objects is maintained by C code (see tldict_lookup()).
#
# Invariant: between two transactions, all objects visible from the current
# thread are always GLOBAL. In particular:
#
# - The LOCAL objects of a thread are not visible at all from other threads.
-# This means that in transactional mode there is *no* pointer from a
-# GLOBAL object directly to a LOCAL object.
-#
-# - At the end of enter_transactional_mode(), and at the beginning of
-# leave_transactional_mode(), *all* objects everywhere are GLOBAL.
+# This means that there is *no* pointer from a GLOBAL object directly to
+# a LOCAL object. At most, there can be pointers from a GLOBAL object to
+# another GLOBAL object that itself has a LOCAL COPY --- or, of course,
+# pointers from a LOCAL object to anything.
#
# Collection: for now we have only local_collection(), which ignores all
# GLOBAL objects.
#
-# - In non-transactional mode, we use 'mt_global_turned_local' as a list
-# of roots, together with the stack. By construction, all objects that
-# are still GLOBAL can be ignored, because they cannot point to a LOCAL
-# object (except to a 'mt_global_turned_local' object).
-#
-# - In transactional mode, we similarly use the list maintained by C code
+# - To find the roots, we take the list (maintained by the C code)
# of the LOCAL COPY objects of the current transaction, together with
-# the stack. Again, GLOBAL objects can be ignored because they have no
-# pointer to any LOCAL object at all in that mode.
+# the stack. GLOBAL objects can be ignored because they have no
+# pointer to any LOCAL object at all.
#
# - A special case is the end-of-transaction collection, done by the same
# local_collection() with a twist: all pointers to a LOCAL COPY object
-# are replaced with copies to the corresponding GLOBAL original. When
+# are replaced with pointers to the corresponding GLOBAL original. When
# it is done, we mark all surviving LOCAL objects as GLOBAL too, and we
# are back to the situation where this thread sees only GLOBAL objects.
-# What we leave to the C code to do "as a finishing touch" is to copy
+# What we leave to the C code to do "as the finishing touch" is to copy
# transactionally the content of the LOCAL COPY objects back over the
# GLOBAL originals; before this is done, the transaction can be aborted
# at any point with no visible side-effect on any object that other
@@ -129,11 +111,8 @@
# - if GCFLAG_HAS_SHADOW, to the shadow object outside the nursery.
# (It is not used on other nursery objects before collection.)
#
-# - it contains the 'next' object of the 'mt_global_turned_local' list.
-#
# - it contains the 'next' object of the 'sharedarea_tls.chained_list'
-# list, which describes all LOCAL objects malloced outside the nursery
-# (excluding the ones that were GLOBAL at some point).
+# list, which describes all LOCAL objects malloced outside the nursery.
#
# - for nursery objects, during collection, if they are copied outside
# the nursery, they grow GCFLAG_VISITED and their 'version' points
@@ -199,7 +178,6 @@
self.stm_operations = stm_operations
self.nursery_size = nursery_size
self.sharedarea = stmshared.StmGCSharedArea(self)
- self.transactional_mode = False
#
def _stm_getsize(obj): # indirection to hide 'self'
return self.get_size(obj)
@@ -224,16 +202,17 @@
#
self.sharedarea.setup()
#
- from pypy.rpython.memory.gc.stmtls import StmGCTLS
- self.main_thread_tls = StmGCTLS(self, in_main_thread=True)
- self.main_thread_tls.start_transaction()
+ self.setup_thread()
def setup_thread(self):
from pypy.rpython.memory.gc.stmtls import StmGCTLS
- StmGCTLS(self, in_main_thread=False)
+ StmGCTLS(self).start_transaction()
def teardown_thread(self):
- self.get_tls().teardown_thread()
+ self.stm_operations.try_inevitable()
+ stmtls = self.get_tls()
+ stmtls.stop_transaction()
+ stmtls.delete()
@always_inline
def get_tls(self):
@@ -241,16 +220,6 @@
tls = self.stm_operations.get_tls()
return StmGCTLS.cast_address_to_tls_object(tls)
- def enter_transactional_mode(self):
- ll_assert(not self.transactional_mode, "already in transactional mode")
- self.main_thread_tls.enter_transactional_mode()
- self.transactional_mode = True
-
- def leave_transactional_mode(self):
- ll_assert(self.transactional_mode, "already in non-transactional mode")
- self.transactional_mode = False
- self.main_thread_tls.leave_transactional_mode()
-
# ----------
def malloc_fixedsize_clear(self, typeid, size,
@@ -259,11 +228,7 @@
contains_weakptr=False):
#assert not needs_finalizer, "XXX" --- finalizer is just ignored
#
- # Check the mode: either in a transactional thread, or in
- # the main thread. For now we do the same thing in both
- # modes, but set different flags.
- #
- # Get the memory from the nursery.
+ # Get the memory from the thread-local nursery.
size_gc_header = self.gcheaderbuilder.size_gc_header
totalsize = size_gc_header + size
tls = self.get_tls()
@@ -380,15 +345,7 @@
#
@dont_inline
def _stm_write_barrier_global(obj):
- tls = self.get_tls()
- if tls is self.main_thread_tls:
- # not in a transaction: the main thread writes to a global obj.
- # In this case we turn the object local.
- tls.main_thread_writes_to_global_obj(obj)
- return obj
- #
- # else, in a transaction: we find or make a local copy of the
- # global object
+ # find or make a local copy of the global object
hdr = self.header(obj)
if hdr.tid & GCFLAG_WAS_COPIED == 0:
#
@@ -410,10 +367,13 @@
# Here, we need to really make a local copy
size = self.get_size(obj)
totalsize = self.gcheaderbuilder.size_gc_header + size
+ tls = self.get_tls()
try:
localobj = tls.malloc_local_copy(totalsize)
except MemoryError:
- # XXX
+ # should not really let the exception propagate.
+ # XXX do something slightly better, like abort the transaction
+ # and raise a MemoryError when retrying
fatalerror("MemoryError in _stm_write_barrier_global -- sorry")
return llmemory.NULL
#
@@ -446,8 +406,8 @@
comparison with another pointer. If 'obj' is the local
version of an existing global object, then returns the
global object. Don't use for e.g. hashing, because if 'obj'
- is a purely local object, it just returns 'obj' --- which
- will change at the next commit.
+ is a local object, it just returns 'obj' --- even for nursery
+ objects, which move at the next local collection.
"""
if not obj:
return obj
@@ -472,7 +432,7 @@
#
# The object is still in the nursery of the current TLS.
# (It cannot be in the nursery of a different thread, because
- # such objects are not visible to different threads at all.)
+ # such an object would not be visible to this thread at all.)
#
ll_assert(hdr.tid & GCFLAG_WAS_COPIED == 0, "id: WAS_COPIED?")
#
diff --git a/pypy/rpython/memory/gc/stmtls.py b/pypy/rpython/memory/gc/stmtls.py
--- a/pypy/rpython/memory/gc/stmtls.py
+++ b/pypy/rpython/memory/gc/stmtls.py
@@ -22,9 +22,8 @@
nontranslated_dict = {}
- def __init__(self, gc, in_main_thread):
+ def __init__(self, gc):
self.gc = gc
- self.in_main_thread = in_main_thread
self.stm_operations = self.gc.stm_operations
self.null_address_dict = self.gc.null_address_dict
self.AddressStack = self.gc.AddressStack
@@ -48,14 +47,10 @@
# --- the LOCAL objects which are weakrefs. They are also listed
# in the appropriate place, like sharedarea_tls, if needed.
self.local_weakrefs = self.AddressStack()
- # --- main thread only: this is the list of GLOBAL objects that
- # have been turned into LOCAL objects
- if in_main_thread:
- self.mt_global_turned_local = NULL
#
self._register_with_C_code()
- def teardown_thread(self):
+ def delete(self):
self._cleanup_state()
self._unregister_with_C_code()
self.local_weakrefs.delete()
@@ -81,7 +76,7 @@
n = 10000 + len(StmGCTLS.nontranslated_dict)
tlsaddr = rffi.cast(llmemory.Address, n)
StmGCTLS.nontranslated_dict[n] = self
- self.stm_operations.set_tls(tlsaddr, int(self.in_main_thread))
+ self.stm_operations.set_tls(tlsaddr)
def _unregister_with_C_code(self):
ll_assert(self.gc.get_tls() is self,
@@ -106,74 +101,12 @@
# ------------------------------------------------------------
- def enter_transactional_mode(self):
- """Called on the main thread, just before spawning the other
- threads."""
- self.stop_transaction()
- #
- # We must also mark the following objects as GLOBAL again
- obj = self.mt_global_turned_local
- self.mt_global_turned_local = NULL
- self.mt_save_prebuilt_turned_local = self.AddressStack()
- while obj:
- hdr = self.gc.header(obj)
- if hdr.tid & GCFLAG_PREBUILT:
- self.mt_save_prebuilt_turned_local.append(obj)
- obj = hdr.version
- ll_assert(hdr.tid & GCFLAG_GLOBAL == 0, "already GLOBAL [2]")
- ll_assert(hdr.tid & GCFLAG_VISITED != 0, "missing VISITED [2]")
- hdr.tid += GCFLAG_GLOBAL - GCFLAG_VISITED
- self._clear_version_for_global_object(hdr)
- if not we_are_translated():
- del self.mt_global_turned_local # don't use any more
- #
- if self.gc.DEBUG:
- self.check_all_global_objects()
-
- def leave_transactional_mode(self):
- """Restart using the main thread for mallocs."""
- if not we_are_translated():
- for key, value in StmGCTLS.nontranslated_dict.items():
- if value is not self:
- del StmGCTLS.nontranslated_dict[key]
- self.start_transaction()
- #
- if self.gc.DEBUG:
- self.check_all_global_objects()
- #
- # Do something special here after we restarted the execution
- # in the main thread. At this point, *all* objects are GLOBAL.
- # The write_barrier will ensure that any write makes the written-to
- # objects LOCAL again. However, it is possible that the write
- # barrier was called before the enter/leave_transactional_mode()
- # and will not be called again before writing. But such objects
- # are right now directly in the stack. So to fix this issue, we
- # conservatively mark as local all objects directly from the stack.
- # XXX TODO: do the same thing after each local_collection() by
- # the main thread.
- self.mt_global_turned_local = NULL
- self.gc.root_walker.walk_current_stack_roots(
- StmGCTLS._remark_object_as_local, self)
- # Messy, because prebuilt objects may be Constants in the flow
- # graphs and so don't appear in the stack, so need a special case.
- # We save and restore which *prebuilt* objects were originally
- # in mt_global_turned_local. (Note that we can't simply save
- # and restore mt_global_turned_local for *all* objects, because
- # that would not be enough: the stack typically contains also many
- # fresh objects that used to be local in enter_transactional_mode().)
- while self.mt_save_prebuilt_turned_local.non_empty():
- obj = self.mt_save_prebuilt_turned_local.pop()
- hdr = self.gc.header(obj)
- if hdr.tid & GCFLAG_GLOBAL:
- self.main_thread_writes_to_global_obj(obj)
- self.mt_save_prebuilt_turned_local.delete()
-
def start_transaction(self):
"""Start a transaction: performs any pending cleanups, and set
up a fresh state for allocating. Called at the start of
- each transaction, and at the start of the main thread."""
- # Note that the calls to enter() and
- # end_of_transaction_collection() are not balanced: if a
+ each transaction, including at the start of a thread."""
+ # Note that the calls to start_transaction() and
+ # stop_transaction() are not balanced: if a
# transaction is aborted, the latter might never be called.
# Be ready here to clean up any state.
self._cleanup_state()
@@ -186,6 +119,10 @@
llarena.arena_reset(self.nursery_start, clear_size, 2)
self.nursery_free = self.nursery_start
self.nursery_top = self.nursery_start + self.nursery_size
+ # At this point, all visible objects are GLOBAL, but newly
+ # malloced objects will be LOCAL.
+ if self.gc.DEBUG:
+ self.check_all_global_objects()
def stop_transaction(self):
"""Stop a transaction: do a local collection to empty the
@@ -193,7 +130,7 @@
then mark all these objects as global."""
self.local_collection(end_of_transaction=1)
if not self.local_nursery_is_empty():
- self.local_collection(end_of_transaction=2)
+ self.local_collection(end_of_transaction=1, run_finalizers=False)
self._promote_locals_to_globals()
self._disable_mallocs()
@@ -204,15 +141,14 @@
# ------------------------------------------------------------
- def local_collection(self, end_of_transaction=0):
+ def local_collection(self, end_of_transaction=0, run_finalizers=True):
"""Do a local collection. This should be equivalent to a minor
collection only, but the GC is not generational so far, so it is
for now the same as a full collection --- but only on LOCAL
objects, not touching the GLOBAL objects. More precisely, this
- finds all YOUNG LOCAL objects, move them out of the nursery if
- necessary, and make them OLD LOCAL objects. This starts from
- the roots from the stack. The flag GCFLAG_WAS_COPIED is kept
- and the C tree is updated if the local young objects move.
+ finds all LOCAL objects alive, moving them if necessary out of the
+ nursery. This starts from the roots from the stack and the LOCAL
+ COPY objects.
"""
#
debug_start("gc-local")
@@ -243,10 +179,7 @@
#
# Also find the roots that are the local copy of GCFLAG_WAS_COPIED
# objects.
- if not self.in_main_thread:
- self.collect_roots_from_tldict()
- else:
- self.collect_from_mt_global_turned_local()
+ self.collect_roots_from_tldict()
#
# Now repeatedly follow objects until 'pending' is empty.
self.collect_flush_pending()
@@ -264,7 +197,7 @@
# don't have GCFLAG_VISITED. As the newly allocated nursery
# objects don't have it either, at the start of the next
# collection, the only LOCAL objects that have it are the ones
- # in 'mt_global_turned_local' or the C tldict with GCFLAG_WAS_COPIED.
+ # in the C tldict, together with GCFLAG_WAS_COPIED.
#
# All live nursery objects are out, and the rest dies. Fill
# the whole nursery with zero and reset the current nursery pointer.
@@ -292,13 +225,15 @@
fatalerror("malloc in a non-main thread but outside a transaction")
if llmemory.raw_malloc_usage(size) > self.nursery_size // 8 * 7:
fatalerror("object too large to ever fit in the nursery")
- while True:
- self.local_collection()
+ self.local_collection()
+ free = self.nursery_free
+ top = self.nursery_top
+ if (top - free) < llmemory.raw_malloc_usage(size):
+ # try again
+ self.local_collection(run_finalizers=False)
+ ll_assert(self.local_nursery_is_empty(), "nursery must be empty [0]")
free = self.nursery_free
- top = self.nursery_top
- if (top - free) < llmemory.raw_malloc_usage(size):
- continue # try again
- return free
+ return free
def is_in_nursery(self, addr):
ll_assert(llmemory.cast_adr_to_int(addr) & 1 == 0,
@@ -306,7 +241,7 @@
return self.nursery_start <= addr < self.nursery_top
def malloc_local_copy(self, totalsize):
- """Allocate an object that will be used as a LOCAL copy of
+ """Allocate an object that will be used as a LOCAL COPY of
some GLOBAL object."""
localobj = self.sharedarea_tls.malloc_object(totalsize)
self.copied_local_objects.append(localobj)
@@ -315,25 +250,6 @@
def fresh_new_weakref(self, obj):
self.local_weakrefs.append(obj)
- def _remark_object_as_local(self, root):
- obj = root.address[0]
- hdr = self.gc.header(obj)
- if hdr.tid & GCFLAG_GLOBAL:
- self.main_thread_writes_to_global_obj(obj)
-
- def main_thread_writes_to_global_obj(self, obj):
- hdr = self.gc.header(obj)
- # XXX should we also remove GCFLAG_WAS_COPIED here if it is set?
- ll_assert(hdr.tid & GCFLAG_VISITED == 0,
- "write in main thread: unexpected GCFLAG_VISITED")
- # remove GCFLAG_GLOBAL and (if it was there) GCFLAG_WAS_COPIED,
- # and add GCFLAG_VISITED
- hdr.tid &= ~(GCFLAG_GLOBAL | GCFLAG_WAS_COPIED)
- hdr.tid |= GCFLAG_VISITED
- # add the object into this linked list
- hdr.version = self.mt_global_turned_local
- self.mt_global_turned_local = obj
-
# ------------------------------------------------------------
def _promote_locals_to_globals(self):
@@ -392,9 +308,10 @@
def trace_and_drag_out_of_nursery(self, obj):
# This is called to fix the references inside 'obj', to ensure that
# they are global. If necessary, the referenced objects are copied
- # into the global area first. This is called on the LOCAL copy of
+ # out of the nursery first. This is called on the LOCAL copy of
# the roots, and on the freshly OLD copy of all other reached LOCAL
- # objects.
+ # objects. This only looks inside 'obj': it does not depend on or
+ # touch the flags of 'obj'.
self.gc.trace(obj, self._trace_drag_out, None)
def _trace_drag_out1(self, root):
@@ -454,6 +371,8 @@
#
# If 'obj' was already forwarded, change it to its forwarding address.
# If 'obj' has already a shadow but isn't forwarded so far, use it.
+ # The common case is the "else" part, so we use only one test to
+ # know if we are in the common case or not.
if hdr.tid & (GCFLAG_VISITED | GCFLAG_HAS_SHADOW):
#
if hdr.tid & GCFLAG_VISITED:
@@ -552,19 +471,6 @@
#
self.trace_and_drag_out_of_nursery(localobj)
- def collect_from_mt_global_turned_local(self):
- # NB. all objects in the 'mt_global_turned_local' list are
- # currently immortal (because they were once GLOBAL)
- obj = self.mt_global_turned_local
- while obj:
- hdr = self.gc.header(obj)
- ll_assert(hdr.tid & GCFLAG_GLOBAL == 0,
- "unexpected GCFLAG_GLOBAL in mt_global_turned_local")
- ll_assert(hdr.tid & GCFLAG_VISITED != 0,
- "missing GCFLAG_VISITED in mt_global_turned_local")
- self.trace_and_drag_out_of_nursery(obj)
- obj = hdr.version
-
def collect_flush_pending(self):
# Follow the objects in the 'pending' stack and move the
# young objects they point to out of the nursery.
diff --git a/pypy/translator/stm/stmgcintf.py b/pypy/translator/stm/stmgcintf.py
--- a/pypy/translator/stm/stmgcintf.py
+++ b/pypy/translator/stm/stmgcintf.py
@@ -47,9 +47,12 @@
# C part of the implementation of the pypy.rlib.rstm module
in_transaction = smexternal('stm_in_transaction', [], lltype.Signed)
- run_all_transactions = smexternal('stm_run_all_transactions',
- [rffi.VOIDP, lltype.Signed],
- lltype.Void)
+ before_external_call = smexternal('stm_before_external_call',
+ [], lltype.Void)
+ after_external_call = smexternal('stm_after_external_call',
+ [], lltype.Void)
+ do_yield_thread = smexternal('stm_do_yield_thread',
+ [], lltype.Void)
# for the GC: store and read a thread-local-storage field, as well
# as initialize and shut down the internal thread_descriptor
diff --git a/pypy/translator/stm/test/targetdemo2.py b/pypy/translator/stm/test/targetdemo2.py
--- a/pypy/translator/stm/test/targetdemo2.py
+++ b/pypy/translator/stm/test/targetdemo2.py
@@ -1,5 +1,6 @@
import time
-from pypy.module.thread import ll_thread, gil
+from pypy.module.thread import ll_thread
+from pypy.rlib import rstm
from pypy.rlib.objectmodel import invoke_around_extcall, we_are_translated
@@ -69,7 +70,7 @@
def really_run(self):
for value in range(glob.LENGTH):
add_at_end_of_chained_list(glob.anchor, value, self.index)
- gil.do_yield_thread()
+ rstm.do_yield_thread()
# ____________________________________________________________
# bah, we are really missing an RPython interface to threads
@@ -129,7 +130,7 @@
def setup_threads():
#space.threadlocals.setup_threads(space)
bootstrapper.setup()
- invoke_around_extcall(gil.before_external_call, gil.after_external_call)
+ invoke_around_extcall(rstm.before_external_call, rstm.after_external_call)
def start_thread(args):
bootstrapper.acquire(args)
More information about the pypy-commit
mailing list