Use higher default thread suspend timeout for run tests
Increase the default for tests from 10s-50s to 500s. This is done
by adding a run-test option "--suspend-timeout" that defaults to
500000.
Example when passing a low value of 100:
test/run-test --host --suspend-timeout 100 --dev 004-ThreadStress
Results in:
dalvikvm32 F 01-22 13:33:31 12067 12118 thread_list.cc:669] Timed
out waiting for threads to suspend, waited for 100.114ms
This should fix some of the recent test flakiness.
Test: test-art-host
Change-Id: I303c4f198e560e9f38ec375e9d7a80a5e61f776e
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index a72159b..d1ad77c 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -302,6 +302,9 @@
.IntoKey(M::Plugins)
.Define("-Xfully-deoptable")
.IntoKey(M::FullyDeoptable)
+ .Define("-XX:ThreadSuspendTimeout=_") // in ms
+ .WithType<MillisecondsToNanoseconds>() // store as ns
+ .IntoKey(M::ThreadSuspendTimeout)
.Ignore({
"-ea", "-da", "-enableassertions", "-disableassertions", "--runtime-arg", "-esa",
"-dsa", "-enablesystemassertions", "-disablesystemassertions", "-Xrs", "-Xint:_",
@@ -724,6 +727,7 @@
UsageMessage(stream, " -XX:MaxSpinsBeforeThinLockInflation=integervalue\n");
UsageMessage(stream, " -XX:LongPauseLogThreshold=integervalue\n");
UsageMessage(stream, " -XX:LongGCLogThreshold=integervalue\n");
+ UsageMessage(stream, " -XX:ThreadSuspendTimeout=integervalue\n");
UsageMessage(stream, " -XX:DumpGCPerformanceOnShutdown\n");
UsageMessage(stream, " -XX:DumpJITInfoOnShutdown\n");
UsageMessage(stream, " -XX:IgnoreMaxFootprint\n");
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 4936a2f..4a32abe 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1045,7 +1045,7 @@
monitor_list_ = new MonitorList;
monitor_pool_ = MonitorPool::Create();
- thread_list_ = new ThreadList;
+ thread_list_ = new ThreadList(runtime_options.GetOrDefault(Opt::ThreadSuspendTimeout));
intern_table_ = new InternTable;
verify_ = runtime_options.GetOrDefault(Opt::Verify);
diff --git a/runtime/runtime_options.cc b/runtime/runtime_options.cc
index e75481c..aa14719 100644
--- a/runtime/runtime_options.cc
+++ b/runtime/runtime_options.cc
@@ -21,6 +21,7 @@
#include "gc/heap.h"
#include "monitor.h"
#include "runtime.h"
+#include "thread_list.h"
#include "trace.h"
#include "utils.h"
#include "debugger.h"
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index ecabf9a..749a36e 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -60,6 +60,8 @@
LongPauseLogThreshold, gc::Heap::kDefaultLongPauseLogThreshold)
RUNTIME_OPTIONS_KEY (MillisecondsToNanoseconds, \
LongGCLogThreshold, gc::Heap::kDefaultLongGCLogThreshold)
+RUNTIME_OPTIONS_KEY (MillisecondsToNanoseconds, \
+ ThreadSuspendTimeout, ThreadList::kDefaultThreadSuspendTimeout)
RUNTIME_OPTIONS_KEY (Unit, DumpGCPerformanceOnShutdown)
RUNTIME_OPTIONS_KEY (Unit, DumpJITInfoOnShutdown)
RUNTIME_OPTIONS_KEY (Unit, IgnoreMaxFootprint)
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index c5c7e2c..01c940e 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -57,7 +57,6 @@
using android::base::StringPrintf;
static constexpr uint64_t kLongThreadSuspendThreshold = MsToNs(5);
-static constexpr uint64_t kThreadSuspendTimeoutMs = 30 * 1000; // 30s.
// Use 0 since we want to yield to prevent blocking for an unpredictable amount of time.
static constexpr useconds_t kThreadSuspendInitialSleepUs = 0;
static constexpr useconds_t kThreadSuspendMaxYieldUs = 3000;
@@ -68,12 +67,13 @@
// Turned off again. b/29248079
static constexpr bool kDumpUnattachedThreadNativeStackForSigQuit = false;
-ThreadList::ThreadList()
+ThreadList::ThreadList(uint64_t thread_suspend_timeout_ns)
: suspend_all_count_(0),
debug_suspend_all_count_(0),
unregistering_count_(0),
suspend_all_historam_("suspend all histogram", 16, 64),
long_suspend_(false),
+ thread_suspend_timeout_ns_(thread_suspend_timeout_ns),
empty_checkpoint_barrier_(new Barrier(0)) {
CHECK(Monitor::IsValidLockWord(LockWord::FromThinLockId(kMaxThreadId, 1, 0U)));
}
@@ -554,12 +554,14 @@
// Make sure this thread grabs exclusive access to the mutator lock and its protected data.
#if HAVE_TIMED_RWLOCK
while (true) {
- if (Locks::mutator_lock_->ExclusiveLockWithTimeout(self, kThreadSuspendTimeoutMs, 0)) {
+ if (Locks::mutator_lock_->ExclusiveLockWithTimeout(self,
+ NsToMs(thread_suspend_timeout_ns_),
+ 0)) {
break;
} else if (!long_suspend_) {
// Reading long_suspend without the mutator lock is slightly racy, in some rare cases, this
// could result in a thread suspend timeout.
- // Timeout if we wait more than kThreadSuspendTimeoutMs seconds.
+ // Timeout if we wait more than thread_suspend_timeout_ns_ nanoseconds.
UnsafeLogFatalForThreadSuspendAllTimeout();
}
}
@@ -653,7 +655,7 @@
// is done with a timeout so that we can detect problems.
#if ART_USE_FUTEXES
timespec wait_timeout;
- InitTimeSpec(false, CLOCK_MONOTONIC, kIsDebugBuild ? 50000 : 10000, 0, &wait_timeout);
+ InitTimeSpec(false, CLOCK_MONOTONIC, NsToMs(thread_suspend_timeout_ns_), 0, &wait_timeout);
#endif
const uint64_t start_time = NanoTime();
while (true) {
@@ -863,7 +865,7 @@
return thread;
}
const uint64_t total_delay = NanoTime() - start_time;
- if (total_delay >= MsToNs(kThreadSuspendTimeoutMs)) {
+ if (total_delay >= thread_suspend_timeout_ns_) {
ThreadSuspendByPeerWarning(self,
::android::base::FATAL,
"Thread suspension timed out",
@@ -969,7 +971,7 @@
return thread;
}
const uint64_t total_delay = NanoTime() - start_time;
- if (total_delay >= MsToNs(kThreadSuspendTimeoutMs)) {
+ if (total_delay >= thread_suspend_timeout_ns_) {
ThreadSuspendByThreadIdWarning(::android::base::WARNING,
"Thread suspension timed out",
thread_id);
diff --git a/runtime/thread_list.h b/runtime/thread_list.h
index 658db00..b60fca1 100644
--- a/runtime/thread_list.h
+++ b/runtime/thread_list.h
@@ -20,6 +20,7 @@
#include "barrier.h"
#include "base/histogram.h"
#include "base/mutex.h"
+#include "base/time_utils.h"
#include "base/value_object.h"
#include "gc_root.h"
#include "jni.h"
@@ -41,11 +42,12 @@
class ThreadList {
public:
- static const uint32_t kMaxThreadId = 0xFFFF;
- static const uint32_t kInvalidThreadId = 0;
- static const uint32_t kMainThreadId = 1;
+ static constexpr uint32_t kMaxThreadId = 0xFFFF;
+ static constexpr uint32_t kInvalidThreadId = 0;
+ static constexpr uint32_t kMainThreadId = 1;
+ static constexpr uint64_t kDefaultThreadSuspendTimeout = MsToNs(kIsDebugBuild ? 50000 : 10000);
- explicit ThreadList();
+ explicit ThreadList(uint64_t thread_suspend_timeout_ns);
~ThreadList();
void DumpForSigQuit(std::ostream& os)
@@ -219,6 +221,9 @@
// Whether or not the current thread suspension is long.
bool long_suspend_;
+ // Thread suspension timeout in nanoseconds.
+ const uint64_t thread_suspend_timeout_ns_;
+
std::unique_ptr<Barrier> empty_checkpoint_barrier_;
friend class Thread;
diff --git a/test/run-test b/test/run-test
index 9b17802..c78fa35 100755
--- a/test/run-test
+++ b/test/run-test
@@ -131,6 +131,7 @@
multi_image_suffix=""
android_root="/system"
bisection_search="no"
+suspend_timeout="500000"
# By default we will use optimizing.
image_args=""
image_suffix=""
@@ -219,6 +220,10 @@
basic_verify="true"
gc_stress="true"
shift
+ elif [ "x$1" = "x--suspend-timeout" ]; then
+ shift
+ suspend_timeout="$1"
+ shift
elif [ "x$1" = "x--image" ]; then
shift
image="$1"
@@ -402,6 +407,9 @@
tmp_dir="`cd $oldwd ; python -c "import os; print os.path.realpath('$tmp_dir')"`"
mkdir -p $tmp_dir
+# Add thread suspend timeout flag
+run_args="${run_args} --runtime-option -XX:ThreadSuspendTimeout=$suspend_timeout"
+
if [ "$basic_verify" = "true" ]; then
# Set HspaceCompactForOOMMinIntervalMs to zero to run hspace compaction for OOM more frequently in tests.
run_args="${run_args} --runtime-option -Xgc:preverify --runtime-option -Xgc:postverify --runtime-option -XX:HspaceCompactForOOMMinIntervalMs=0"
@@ -649,6 +657,7 @@
echo " --quiet Don't print anything except failure messages"
echo " --bisection-search Perform bisection bug search."
echo " --vdex Test using vdex as in input to dex2oat. Only works with --prebuild."
+ echo " --suspend-timeout Change thread suspend timeout ms (default 500000)."
) 1>&2 # Direct to stderr so usage is not printed if --quiet is set.
exit 1
fi