diff options
| -rw-r--r-- | runtime/parsed_options.cc | 4 | ||||
| -rw-r--r-- | runtime/runtime.cc | 2 | ||||
| -rw-r--r-- | runtime/runtime_options.cc | 1 | ||||
| -rw-r--r-- | runtime/runtime_options.def | 2 | ||||
| -rw-r--r-- | runtime/thread_list.cc | 16 | ||||
| -rw-r--r-- | runtime/thread_list.h | 13 | ||||
| -rwxr-xr-x | test/run-test | 9 |
7 files changed, 35 insertions, 12 deletions
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index a72159bc80..d1ad77c910 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -302,6 +302,9 @@ std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognize .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 @@ void ParsedOptions::Usage(const char* fmt, ...) { 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 4936a2f9a7..4a32abee48 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -1045,7 +1045,7 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { 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 e75481c78a..aa147198fc 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 ecabf9adc5..749a36e3b3 100644 --- a/runtime/runtime_options.def +++ b/runtime/runtime_options.def @@ -60,6 +60,8 @@ RUNTIME_OPTIONS_KEY (MillisecondsToNanoseconds, \ 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 c5c7e2cc16..01c940e9df 100644 --- a/runtime/thread_list.cc +++ b/runtime/thread_list.cc @@ -57,7 +57,6 @@ namespace art { 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 @@ static constexpr useconds_t kThreadSuspendMaxSleepUs = 5000; // 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 @@ void ThreadList::SuspendAll(const char* cause, bool long_suspend) { // 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 @@ void ThreadList::SuspendAllInternal(Thread* self, // 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 @@ Thread* ThreadList::SuspendThreadByPeer(jobject peer, 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 @@ Thread* ThreadList::SuspendThreadByThreadId(uint32_t thread_id, 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 658db00ec3..b60fca1fdc 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 TimingLogger; 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 @@ class ThreadList { // 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 9b178021ff..c78fa35e24 100755 --- a/test/run-test +++ b/test/run-test @@ -131,6 +131,7 @@ pic_image_suffix="" 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 @@ while true; do 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 @@ noncanonical_tmp_dir=$tmp_dir 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 @@ if [ "$usage" = "yes" ]; then 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 |