Index: libcxx/trunk/utils/libcxx/test/format.py =================================================================== --- libcxx/trunk/utils/libcxx/test/format.py +++ libcxx/trunk/utils/libcxx/test/format.py @@ -203,9 +203,11 @@ is_flaky = self._get_parser('FLAKY_TEST.', parsers).getValue() max_retry = 3 if is_flaky else 1 for retry_count in range(max_retry): + lit_config._retry_rwlock.acquire(retry_count) cmd, out, err, rc = self.executor.run(exec_path, [exec_path], local_cwd, data_files, env) + lit_config._retry_rwlock.release(retry_count) if rc == 0: res = lit.Test.PASS if retry_count == 0 else lit.Test.FLAKYPASS return res, '' Index: llvm/trunk/utils/lit/lit/TestRunner.py =================================================================== --- llvm/trunk/utils/lit/lit/TestRunner.py +++ llvm/trunk/utils/lit/lit/TestRunner.py @@ -1200,7 +1200,11 @@ if hasattr(test.config, 'test_retry_attempts'): attempts += test.config.test_retry_attempts for i in range(attempts): + if hasattr(litConfig, '_retry_rwlock'): + litConfig._retry_rwlock.acquire(i) res = _runShTest(test, litConfig, useExternalSh, script, tmpBase) + if hasattr(litConfig, '_retry_rwlock'): + litConfig._retry_rwlock.release(i) if res.code != Test.FAIL: break # If we had to run the test more than once, count it as a flaky pass. These Index: llvm/trunk/utils/lit/lit/run.py =================================================================== --- llvm/trunk/utils/lit/lit/run.py +++ llvm/trunk/utils/lit/lit/run.py @@ -15,6 +15,7 @@ import multiprocessing import lit.Test +import lit.util def abort_now(): """Abort the current process without doing any exception teardown""" @@ -140,6 +141,9 @@ # our task completion callback. self.display = display + # FIXME: It might be in wrong place. + self.lit_config._retry_rwlock = lit.util.RWLock() + self.failure_count = 0 self.hit_max_failures = False if self.lit_config.singleProcess: Index: llvm/trunk/utils/lit/lit/util.py =================================================================== --- llvm/trunk/utils/lit/lit/util.py +++ llvm/trunk/utils/lit/lit/util.py @@ -1,6 +1,7 @@ import errno import itertools import math +import multiprocessing import numbers import os import platform @@ -422,3 +423,55 @@ psutilProc.kill() except psutil.NoSuchProcess: pass + +class RWLock: + """ + Provide RWLock + """ + def __init__(self): + lock = multiprocessing.RLock() + self._lock = lock + self._rcond = multiprocessing.Condition(lock) + self._wcond = multiprocessing.Condition(lock) + self._rval = multiprocessing.Value('i', 0) + self._wval = multiprocessing.Value('i', 0) + + def read_acquire(self): + self._lock.acquire() + while self._wval.value != 0: + self._rcond.wait() + self._rval.value += 1 + self._lock.release() + + def write_acquire(self): + self._lock.acquire() + while self._rval.value > 0: + self._wcond.wait() + assert self._wval.value == 0 + self._wval.value = 1 + + def read_release(self): + self._lock.acquire() + rval = self._rval.value - 1 + self._rval.value = rval + if rval == 0: + self._wcond.notify() + self._lock.release() + + def write_release(self): + self._wval.value = 0 + self._wcond.notify() + self._rcond.notify_all() + self._lock.release() + + def acquire(self, count, exclusive_since=1): + if count < exclusive_since: + self.read_acquire() + else: + self.write_acquire() + + def release(self, count, exclusive_since=1): + if count < exclusive_since: + self.read_release() + else: + self.write_release()