[pypy-commit] extradoc extradoc: Updates from trying it out in arigo/hack/stm/c2.

arigo noreply at buildbot.pypy.org
Sat Aug 25 19:17:42 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: extradoc
Changeset: r4722:1ce4e4c16bb3
Date: 2012-08-25 19:17 +0200
http://bitbucket.org/pypy/extradoc/changeset/1ce4e4c16bb3/

Log:	Updates from trying it out in arigo/hack/stm/c2.

diff --git a/talk/stm2012/stmimpl.rst b/talk/stm2012/stmimpl.rst
--- a/talk/stm2012/stmimpl.rst
+++ b/talk/stm2012/stmimpl.rst
@@ -352,7 +352,7 @@
 to the latest version::
 
     def PossiblyUpdateChain(G, R, R_Container, FieldName):
-        if R != G:
+        if R != G and Rarely():
             # compress the chain
             while G->h_revision != R:
                 G_next = G->h_revision
@@ -369,6 +369,17 @@
 the modified values.  It works because the original and each modified
 value are all interchangeable as far as correctness goes.
 
+``Rarely`` uses a thread-local counter to return True only rarely.  We
+do the above update only rarely, rather than always, although it would
+naively seem that doing the update always is a good idea.  The problem
+is that it generates a lot of write traffic to global data that is
+potentially shared between CPUs.  We will need more measurements, but it
+seems that doing it too often causes CPUs to stall.  It is probable that
+updates done by one CPU are sent to other CPUs at high cost, even though
+these updates are not so important in this particular case (i.e. the
+program would work fine if the other CPUs didn't see such updates at all
+and instead repeated the same update logic locally).
+
 
 Validation
 ------------------------------------
@@ -399,15 +410,7 @@
                 AbortTransaction()     #   "has a more recent revision"
             if v >= LOCKED:            # locked
                 if v != my_lock:       # and not by me
-                    spin loop retry OR # jump back to the "v = ..." line
-                    AbortTransaction() # ...or just abort
-
-The choice of waiting or aborting when encountering a read of a locked
-object needs to be done carefully to avoid deadlocks.  Always aborting
-would be correct, but a bit too restrictive.  Always entering a spin
-loop could lead to deadlocks with two transactions that each locked
-objects from the other's ``list_of_read_objects``.  So for the purposes
-of this explanation we will always assume that it aborts.
+                    AbortTransaction()
 
 
 Local garbage collection
@@ -514,13 +517,12 @@
 ``h_revision`` field; it does not involve OS-specific thread locks::
 
     def AcquireLocks():
-        for (R, L, 0) in gcroots:
+        for (R, L, 0) in gcroots SORTED BY R:
             v = R->h_revision
             if not (v & 1):         # "is a pointer", i.e.
                 AbortTransaction()  #   "has a more recent revision"
             if v >= LOCKED:         # already locked by someone else
-                spin loop retry OR  # jump back to the "v = ..." line
-                AbortTransaction()
+                spin loop retry     # jump back to the "v = ..." line
             if not CMPXCHG(&R->h_revision, v, my_lock):
                 spin loop retry     # jump back to the "v = ..." line
             save v into the third item in gcroots, replacing the 0
@@ -531,11 +533,13 @@
 
 We use CMPXCHG to store the lock.  This is required, because we must not
 conflict with another CPU that would try to write its own lock in the
-same field --- in that case, only one CPU can succeed.  The order of
-enumeration of ``global_to_local`` must be the same one --- for example,
-following the numeric order of ``R``.  This is needed to avoid
-deadlocks.  Alternatively we could consider this case rare, and abort
-instead of waiting.
+same field --- in that case, only one CPU can succeed.
+
+Acquiring multiple locks comes with the question of how to avoid
+deadlocks.  In this case, it is prevented by ordering the lock
+acquisitions in the numeric order of the R pointers.  This should be
+enough to prevent deadlocks even if two threads have several objects in
+common in their gcroots.
 
 The lock's value ``my_lock`` is, precisely, a very large odd number, at
 least LOCKED (which should be some value like 0xFFFF0000).  As we can


More information about the pypy-commit mailing list