[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