Author: Armin Rigo <ar...@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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit