Author: Remi Meier Branch: c7-refactor Changeset: r804:24e260eabf78 Date: 2014-02-21 09:41 +0100 http://bitbucket.org/pypy/stmgc/changeset/24e260eabf78/
Log: add stm_become_inevitable to random tests diff --git a/c7/test/test_random.py b/c7/test/test_random.py --- a/c7/test/test_random.py +++ b/c7/test/test_random.py @@ -28,18 +28,32 @@ return r +class WriteWriteConflictNotTestable(Exception): + # How can I test a write-write conflict between + # an inevitable and a normal transaction? The + # inevitable transaction would have to wait, + # but now for tests we simply abort. Of course + # aborting the inevitable transaction is not possible.. + pass + _global_time = 0 def contention_management(our_trs, other_trs, wait=False, objs_in_conflict=None): """exact copy of logic in contention.c""" + if our_trs.inevitable and wait: + # we win but cannot wait in tests... + raise WriteWriteConflictNotTestable - if other_trs.start_time < our_trs.start_time: + if our_trs.inevitable: + other_trs.set_must_abort(objs_in_conflict) + elif other_trs.start_time < our_trs.start_time: pass - else: + elif not other_trs.inevitable: other_trs.set_must_abort(objs_in_conflict) if not other_trs.check_must_abort(): our_trs.set_must_abort(objs_in_conflict) elif wait: + assert not our_trs.inevitable # abort anyway: our_trs.set_must_abort(objs_in_conflict) @@ -56,8 +70,10 @@ self._must_abort = False self.start_time = start_time self.objs_in_conflict = set() + self.inevitable = False def set_must_abort(self, objs_in_conflict=None): + assert not self.inevitable if objs_in_conflict is not None: self.objs_in_conflict |= objs_in_conflict self._must_abort = True @@ -271,10 +287,32 @@ class OpAbortTransaction(Operation): def do(self, ex, global_state, thread_state): - thread_state.transaction_state.set_must_abort() + trs = thread_state.transaction_state + if trs.inevitable: + return + trs.set_must_abort() thread_state.abort_transaction() ex.do('self.abort_transaction()') +class OpBecomeInevitable(Operation): + def do(self, ex, global_state, thread_state): + trs = thread_state.transaction_state + for ts in global_state.thread_states: + other_trs = ts.transaction_state + if (other_trs and trs is not other_trs + and other_trs.inevitable): + trs.set_must_abort() + break + + thread_state.push_roots(ex) + if trs.check_must_abort(): + thread_state.abort_transaction() + ex.do('py.test.raises(Conflict, stm_become_inevitable)') + else: + trs.inevitable = True + ex.do('stm_become_inevitable()') + thread_state.pop_roots(ex) + thread_state.reload_roots(ex) class OpAllocate(Operation): @@ -326,14 +364,27 @@ else: v = ord(global_state.rnd.choice("abcdefghijklmnop")) trs = thread_state.transaction_state - trs.write_root(r, v) # if is_ref_type_map[r]: ex.do("idx = (stm_get_obj_size(%s) - HDR) / WORD - 1" % r) else: ex.do("offset = stm_get_obj_size(%s) - 1" % r) # - global_state.check_for_write_write_conflicts(trs) + was_written = False + try: + # HACK to avoid calling write_root() just yet + was_written = r in trs.write_set + trs.write_set.add(r) + global_state.check_for_write_write_conflicts(trs) + except WriteWriteConflictNotTestable: + if not was_written: + trs.write_set.remove(r) + ex.do("# this is an untestable write-write conflict between an") + ex.do("# inevitable and a normal transaction :(") + return + # + trs.write_root(r, v) + # if trs.check_must_abort(): thread_state.abort_transaction() if is_ref_type_map[r]: @@ -445,6 +496,7 @@ OpCommitTransaction, OpAbortTransaction, OpForgetRoot, + OpBecomeInevitable, # OpMinorCollect, ] for _ in range(200): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit