[pypy-commit] pypy stm-gc: Fix. See comment.
arigo
noreply at buildbot.pypy.org
Fri Apr 20 19:02:37 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: stm-gc
Changeset: r54587:d1daac6a89d2
Date: 2012-04-20 18:52 +0200
http://bitbucket.org/pypy/pypy/changeset/d1daac6a89d2/
Log: Fix. See comment.
diff --git a/pypy/module/transaction/interp_transaction.py b/pypy/module/transaction/interp_transaction.py
--- a/pypy/module/transaction/interp_transaction.py
+++ b/pypy/module/transaction/interp_transaction.py
@@ -12,19 +12,28 @@
class State(object):
+ # Warning: this is the class of a singleton. It Must Not Be Used
+ # Inside Any Transaction!!!! This code is written with the
+ # expectation that it is really a global singleton used for
+ # synchronization between transactions. So if the STM logic kicks
+ # in and makes local copies of it, we loose.
+ #
+ # Instead, we have a TransactionalState instance that can be
+ # written to by transactions (possibly causing conflicts).
def initialize(self, space):
self.space = space
self.running = False
self.num_threads = NUM_THREADS_DEFAULT
+ self.transactionalstate = None
#
self.w_error = None
self.ll_lock = threadintf.null_ll_lock
self.ll_no_tasks_pending_lock = threadintf.null_ll_lock
self.ll_unfinished_lock = threadintf.null_ll_lock
+ self.ll_not_ready_to_start_lock = threadintf.null_ll_lock
self.threadobjs = {} # empty during translation
self.threadnums = {} # empty during translation
- self.epolls = None
self.pending = Fifo()
def _freeze_(self):
@@ -41,6 +50,7 @@
self.ll_no_tasks_pending_lock = threadintf.allocate_lock()
self.ll_unfinished_lock = threadintf.allocate_lock()
self.lock_unfinished()
+ self.ll_not_ready_to_start_lock = threadintf.allocate_lock()
self.startup_run()
def startup_run(self):
@@ -139,8 +149,21 @@
"""Release ll_unfinished_lock."""
threadintf.release(self.ll_unfinished_lock)
- def init_exceptions(self):
+ def lock_not_ready_to_start(self):
+ """This lock is acquired when the threads are still starting.
+ It is released when all threads are past their initialization."""
+ threadintf.acquire(self.ll_not_ready_to_start_lock, True)
+
+ def unlock_not_ready_to_start(self):
+ """Release ll_not_ready_to_start_lock."""
+ threadintf.release(self.ll_not_ready_to_start_lock)
+
+
+class TransactionalState(object):
+
+ def __init__(self):
self._reraise_exception = None
+ self.epolls = None
def has_exception(self):
return self._reraise_exception is not None
@@ -150,7 +173,7 @@
def close_exceptions(self):
if self._reraise_exception is not None:
- self._reraise_exception()
+ self._reraise_exception(self)
state = State()
@@ -184,13 +207,15 @@
if retry_counter > 0:
pending.register() # retrying: will be done later, try others first
return
- if state.has_exception():
+ ts = state.transactionalstate
+ if ts.has_exception():
return # return early if there is already an exception to reraise
try:
pending.run_in_transaction(state.space)
except Exception, e:
- state.got_exception_applevel = e
- state.must_reraise_exception(_reraise_from_applevel)
+ ts = state.transactionalstate
+ ts.got_exception_applevel = e
+ ts.must_reraise_exception(_reraise_from_applevel)
class Pending(AbstractPending):
@@ -202,9 +227,9 @@
space.call_args(self.w_callback, self.args)
-def _reraise_from_applevel():
- e = state.got_exception_applevel
- state.got_exception_applevel = None
+def _reraise_from_applevel(transactionalstate):
+ e = transactionalstate.got_exception_applevel
+ transactionalstate.got_exception_applevel = None
raise e
@@ -235,8 +260,17 @@
# so we need to be very careful.
rstm.descriptor_init()
state.lock()
+ rstm.perform_transaction(_setup_thread, AbstractPending, None)
+ # wait until all threads reach this point to continue
+ if state.num_waiting_threads + 1 < state.num_threads:
+ state.num_waiting_threads += 1
+ state.unlock()
+ state.lock_not_ready_to_start()
+ state.lock()
+ else:
+ state.num_waiting_threads = 0
+ state.unlock_not_ready_to_start()
#
- rstm.perform_transaction(_setup_thread, AbstractPending, None)
my_transactions_pending = state.getvalue()._transaction_pending
#
while True:
@@ -312,8 +346,9 @@
state.num_waiting_threads = 0
state.finished = False
#
+ state.transactionalstate = TransactionalState()
+ state.lock_not_ready_to_start()
state.running = True
- state.init_exceptions()
#
# start the threads and wait for all of them to finish
_run()
@@ -323,7 +358,8 @@
assert not state.is_locked_no_tasks_pending()
state.clear_all_values_apart_from_main()
state.running = False
- state.epolls = None
+ ts = state.transactionalstate
+ state.transactionalstate = None
#
# now re-raise the exception that we got in a transaction
- state.close_exceptions()
+ ts.close_exceptions()
More information about the pypy-commit
mailing list