Revert "Priority fixes" Revert submission 3287177-priofix Reason for revert: <Potential culprit for b/406285562 - verifying through ABTD before revert submission. This is part of the standard investigation process, and does not mean your CL will be reverted> Reverted changes: /q/submissionid:3287177-priofix Change-Id: I4a9960dc5a9adc27a8c04f0999e749eec133b457
diff --git a/adbconnection/adbconnection.cc b/adbconnection/adbconnection.cc index 51b58d3..2ef7a84 100644 --- a/adbconnection/adbconnection.cc +++ b/adbconnection/adbconnection.cc
@@ -299,7 +299,7 @@ system_thread_group_field->GetOffset())); return art::WellKnownClasses::java_lang_Thread_init ->NewObject<'L', 'L', 'I', 'Z'>( - hs, self, system_thread_group, thr_name, /*niceness=*/0, /*daemon=*/true) + hs, self, system_thread_group, thr_name, /*priority=*/0, /*daemon=*/true) .Get(); }
diff --git a/openjdkjvmti/ti_thread.cc b/openjdkjvmti/ti_thread.cc index e8fc7cd..f89a9d9 100644 --- a/openjdkjvmti/ti_thread.cc +++ b/openjdkjvmti/ti_thread.cc
@@ -340,9 +340,9 @@ // Priority. { - art::ArtField* f = art::WellKnownClasses::java_lang_Thread_niceness; + art::ArtField* f = art::WellKnownClasses::java_lang_Thread_priority; CHECK(f != nullptr); - info_ptr->priority = static_cast<jint>(art::Thread::NicenessToPriority(f->GetInt(peer))); + info_ptr->priority = static_cast<jint>(f->GetInt(peer)); } // Daemon.
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 12da80f..1176bb1 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc
@@ -403,7 +403,7 @@ StackHandleScope<1> hs(self); Handle<mirror::Class> klass( hs.NewHandle(class_linker_->FindSystemClass(self, descriptor.c_str()))); - ASSERT_TRUE(klass != nullptr) << " Class: " << descriptor.c_str(); + ASSERT_TRUE(klass != nullptr); std::string temp; EXPECT_STREQ(descriptor.c_str(), klass->GetDescriptor(&temp)); EXPECT_OBJ_PTR_EQ(class_loader, klass->GetClassLoader());
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 7d1f172..52a00c9 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -429,15 +429,21 @@ return env->NewStringUTF(GetInstructionSetString(kRuntimeISA)); } -static int VMRuntime_getSystemDaemonNiceness() { +static void VMRuntime_setSystemDaemonThreadPriority([[maybe_unused]] JNIEnv* env, + [[maybe_unused]] jclass klass) { +#ifdef ART_TARGET_ANDROID + Thread* self = Thread::Current(); + DCHECK(self != nullptr); + pid_t tid = self->GetTid(); // We use a priority lower than the default for the system daemon threads (eg HeapTaskDaemon) to - // avoid jank due to CPU contention between GC and other UI-related threads. b/36631902. + // avoid jank due to CPU contentions between GC and other UI-related threads. b/36631902. // We may use a native priority that doesn't have a corresponding java.lang.Thread-level priority. - // Currently we use a niceness value between those corresponding to priority 4 and 5, which - // matches the traditional niceness 4 value with the traditional mapping. - static int systemDaemonNiceValue = - (6 * Thread::PriorityToNiceness(5) + 4 * Thread::PriorityToNiceness(4) + 5) / 10; - return systemDaemonNiceValue; + static constexpr int kSystemDaemonNiceValue = 4; // priority 124 + if (setpriority(PRIO_PROCESS, tid, kSystemDaemonNiceValue) != 0) { + PLOG(INFO) << *self << " setpriority(PRIO_PROCESS, " << tid << ", " + << kSystemDaemonNiceValue << ") failed"; + } +#endif } static void VMRuntime_setDedupeHiddenApiWarnings([[maybe_unused]] JNIEnv* env, @@ -592,7 +598,7 @@ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;I)V"), NATIVE_METHOD(VMRuntime, isBootClassPathOnDisk, "(Ljava/lang/String;)Z"), NATIVE_METHOD(VMRuntime, getCurrentInstructionSet, "()Ljava/lang/String;"), - CRITICAL_NATIVE_METHOD(VMRuntime, getSystemDaemonNiceness, "()I"), + NATIVE_METHOD(VMRuntime, setSystemDaemonThreadPriority, "()V"), NATIVE_METHOD(VMRuntime, setDedupeHiddenApiWarnings, "(Z)V"), NATIVE_METHOD(VMRuntime, setProcessPackageName, "(Ljava/lang/String;)V"), NATIVE_METHOD(VMRuntime, setProcessDataDirectory, "(Ljava/lang/String;)V"),
diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc index 64076b6..2c79a38 100644 --- a/runtime/native/java_lang_Thread.cc +++ b/runtime/native/java_lang_Thread.cc
@@ -161,35 +161,17 @@ } /* - * Change Linux niceness priority for the given thread, returning errno. + * Alter the priority of the specified thread. "new_priority" will range + * from Thread.MIN_PRIORITY to Thread.MAX_PRIORITY (1-10), with "normal" + * threads at Thread.NORM_PRIORITY (5). */ -static int Thread_setNiceness0(JNIEnv* env, jobject java_thread, jint new_niceness) { +static void Thread_setPriority0(JNIEnv* env, jobject java_thread, jint new_priority) { ScopedObjectAccess soa(env); MutexLock mu(soa.Self(), *Locks::thread_list_lock_); Thread* thread = Thread::FromManagedThread(soa, java_thread); if (thread != nullptr) { - return thread->SetNativeNiceness(new_niceness); + thread->SetNativePriority(new_priority); } - return 0; -} - -/* - * Alter the priority of the specified thread. "new_priority" will range - * from Thread.MIN_PRIORITY to Thread.MAX_PRIORITY (1-10), with "normal" - * threads at Thread.NORM_PRIORITY (5). Returns corresponding niceness. - */ -static int Thread_setPriority0(JNIEnv* env, jobject java_thread, jint new_priority) { - int n = Thread::PriorityToNiceness(new_priority); - Thread_setNiceness0(env, java_thread, n); - return n; -} - -static int Thread_priorityForNiceness(int niceness) { - return (Thread::NicenessToPriority(niceness)); -} - -static int Thread_nicenessForPriority(int priority) { - return (Thread::PriorityToNiceness(priority)); } static void Thread_sleep(JNIEnv* env, jclass, jobject java_lock, jlong ms, jint ns) { @@ -209,20 +191,17 @@ } static JNINativeMethod gMethods[] = { - FAST_NATIVE_METHOD(Thread, currentThread, "()Ljava/lang/Thread;"), - FAST_NATIVE_METHOD(Thread, interrupted, "()Z"), - FAST_NATIVE_METHOD(Thread, isInterrupted, "()Z"), - NATIVE_METHOD(Thread, nativeCreate, "(Ljava/lang/Thread;JZ)V"), - NATIVE_METHOD(Thread, nativeGetStatus, "(Z)I"), - CRITICAL_NATIVE_METHOD(Thread, nicenessForPriority, "(I)I"), - NATIVE_METHOD(Thread, holdsLock, "(Ljava/lang/Object;)Z"), - FAST_NATIVE_METHOD(Thread, interrupt0, "()V"), - CRITICAL_NATIVE_METHOD(Thread, priorityForNiceness, "(I)I"), - NATIVE_METHOD(Thread, setNativeName, "(Ljava/lang/String;)V"), - NATIVE_METHOD(Thread, setNiceness0, "(I)I"), - NATIVE_METHOD(Thread, setPriority0, "(I)I"), - FAST_NATIVE_METHOD(Thread, sleep, "(Ljava/lang/Object;JI)V"), - NATIVE_METHOD(Thread, yield, "()V"), + FAST_NATIVE_METHOD(Thread, currentThread, "()Ljava/lang/Thread;"), + FAST_NATIVE_METHOD(Thread, interrupted, "()Z"), + FAST_NATIVE_METHOD(Thread, isInterrupted, "()Z"), + NATIVE_METHOD(Thread, nativeCreate, "(Ljava/lang/Thread;JZ)V"), + NATIVE_METHOD(Thread, nativeGetStatus, "(Z)I"), + NATIVE_METHOD(Thread, holdsLock, "(Ljava/lang/Object;)Z"), + FAST_NATIVE_METHOD(Thread, interrupt0, "()V"), + NATIVE_METHOD(Thread, setNativeName, "(Ljava/lang/String;)V"), + NATIVE_METHOD(Thread, setPriority0, "(I)V"), + FAST_NATIVE_METHOD(Thread, sleep, "(Ljava/lang/Object;JI)V"), + NATIVE_METHOD(Thread, yield, "()V"), }; void register_java_lang_Thread(JNIEnv* env) {
diff --git a/runtime/runtime_callbacks_test.cc b/runtime/runtime_callbacks_test.cc index ad360f3..0fd9efa 100644 --- a/runtime/runtime_callbacks_test.cc +++ b/runtime/runtime_callbacks_test.cc
@@ -177,12 +177,7 @@ hs.NewHandle(soa.Decode<mirror::Object>(runtime_->GetMainThreadGroup())); Handle<mirror::Object> thread = WellKnownClasses::java_lang_Thread_init->NewObject<'L', 'L', 'I', 'Z'>( - hs, - self, - thread_group, - thread_name, - Thread::PriorityToNiceness(kMinThreadPriority), - /*daemon=*/false); + hs, self, thread_group, thread_name, kMinThreadPriority, /*daemon=*/ false); ASSERT_FALSE(self->IsExceptionPending()); ASSERT_TRUE(thread != nullptr);
diff --git a/runtime/thread.cc b/runtime/thread.cc index a67fedc..bec08f2 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc
@@ -35,6 +35,9 @@ #include "android-base/file.h" #include "android-base/stringprintf.h" #include "android-base/strings.h" + +#include "unwindstack/AndroidUnwinder.h" + #include "arch/context-inl.h" #include "arch/context.h" #include "art_field-inl.h" @@ -103,14 +106,13 @@ #include "runtime-inl.h" #include "runtime.h" #include "runtime_callbacks.h" -#include "scoped_disable_public_sdk_checker.h" #include "scoped_thread_state_change-inl.h" +#include "scoped_disable_public_sdk_checker.h" #include "stack.h" #include "thread-inl.h" #include "thread_list.h" #include "trace.h" #include "trace_profile.h" -#include "unwindstack/AndroidUnwinder.h" #include "verify_object.h" #include "well_known_classes-inl.h" @@ -649,8 +651,8 @@ self->DeleteJPeer(self->GetJniEnv()); self->SetThreadName(self->GetThreadName()->ToModifiedUtf8().c_str()); - ArtField* nicenessField = WellKnownClasses::java_lang_Thread_niceness; - self->SetNativeNiceness(nicenessField->GetInt(self->tlsPtr_.opeer)); + ArtField* priorityField = WellKnownClasses::java_lang_Thread_priority; + self->SetNativePriority(priorityField->GetInt(self->tlsPtr_.opeer)); runtime->GetRuntimeCallbacks()->ThreadStart(self); @@ -1211,7 +1213,7 @@ CHECK(self->IsExceptionPending()); return; } - jint thread_niceness = GetNativeNiceness(); + jint thread_priority = GetNativePriority(); DCHECK(WellKnownClasses::java_lang_Thread->IsInitialized()); Handle<mirror::Object> peer = @@ -1222,7 +1224,7 @@ } tlsPtr_.opeer = peer.Get(); WellKnownClasses::java_lang_Thread_init->InvokeInstance<'V', 'L', 'L', 'I', 'Z'>( - self, peer.Get(), thr_group.Get(), thread_name.Get(), thread_niceness, as_daemon); + self, peer.Get(), thr_group.Get(), thread_name.Get(), thread_priority, as_daemon); if (self->IsExceptionPending()) { return; } @@ -1236,10 +1238,17 @@ // available (in the compiler, in tests), we manually assign the // fields the constructor should have set. if (runtime->IsActiveTransaction()) { - InitPeer<true>(tlsPtr_.opeer, as_daemon, thr_group.Get(), thread_name.Get(), thread_niceness); + InitPeer<true>(tlsPtr_.opeer, + as_daemon, + thr_group.Get(), + thread_name.Get(), + thread_priority); } else { - InitPeer<false>( - tlsPtr_.opeer, as_daemon, thr_group.Get(), thread_name.Get(), thread_niceness); + InitPeer<false>(tlsPtr_.opeer, + as_daemon, + thr_group.Get(), + thread_name.Get(), + thread_priority); } peer_thread_name.Assign(GetThreadName()); } @@ -1269,8 +1278,7 @@ CHECK(self->IsExceptionPending()); return nullptr; } - // Always normalize to NORM priority. - jint thread_niceness = PriorityToNiceness(kNormThreadPriority); + jint thread_priority = kNormThreadPriority; // Always normalize to NORM priority. DCHECK(WellKnownClasses::java_lang_Thread->IsInitialized()); Handle<mirror::Object> peer = hs.NewHandle( @@ -1287,27 +1295,33 @@ // available (in the compiler, in tests), we manually assign the // fields the constructor should have set. if (runtime->IsActiveTransaction()) { - InitPeer<true>(peer.Get(), as_daemon, thr_group.Get(), thread_name.Get(), thread_niceness); + InitPeer<true>(peer.Get(), + as_daemon, + thr_group.Get(), + thread_name.Get(), + thread_priority); } else { - InitPeer<false>(peer.Get(), as_daemon, thr_group.Get(), thread_name.Get(), thread_niceness); + InitPeer<false>(peer.Get(), + as_daemon, + thr_group.Get(), + thread_name.Get(), + thread_priority); } return peer.Get(); } -template <bool kTransactionActive> +template<bool kTransactionActive> void Thread::InitPeer(ObjPtr<mirror::Object> peer, bool as_daemon, ObjPtr<mirror::Object> thread_group, ObjPtr<mirror::String> thread_name, - jint thread_niceness) { + jint thread_priority) { WellKnownClasses::java_lang_Thread_daemon->SetBoolean<kTransactionActive>(peer, static_cast<uint8_t>(as_daemon ? 1u : 0u)); WellKnownClasses::java_lang_Thread_group->SetObject<kTransactionActive>(peer, thread_group); WellKnownClasses::java_lang_Thread_name->SetObject<kTransactionActive>(peer, thread_name); - WellKnownClasses::java_lang_Thread_niceness->SetInt<kTransactionActive>(peer, thread_niceness); - WellKnownClasses::java_lang_Thread_priority->SetInt<kTransactionActive>( - peer, NicenessToPriority(thread_niceness)); + WellKnownClasses::java_lang_Thread_priority->SetInt<kTransactionActive>(peer, thread_priority); } void Thread::SetCachedThreadName(const char* name) { @@ -2034,8 +2048,7 @@ // cause ScopedObjectAccessUnchecked to deadlock. if (gAborting == 0 && self != nullptr && thread != nullptr && thread->tlsPtr_.opeer != nullptr) { ScopedObjectAccessUnchecked soa(self); - priority = NicenessToPriority( - WellKnownClasses::java_lang_Thread_niceness->GetInt(thread->tlsPtr_.opeer)); + priority = WellKnownClasses::java_lang_Thread_priority->GetInt(thread->tlsPtr_.opeer); is_daemon = WellKnownClasses::java_lang_Thread_daemon->GetBoolean(thread->tlsPtr_.opeer); ObjPtr<mirror::Object> thread_group = @@ -4876,143 +4889,18 @@ Runtime::Current()->GetThreadList()->RunCheckpoint(&closure); } -static_assert(kMinThreadPriority >= 0); - -static int priorityMap[kMaxThreadPriority + 1]; -static std::once_flag priorityMapInitialized; -static bool canSetPriority = true; - -// Return an int array result, so that result[i] is the native priority, really -// "niceness" corresponding to Java priority i. result[0] is unused. -int* Thread::GetPriorityMap() { - std::call_once(priorityMapInitialized, [&pm = priorityMap]() { - pm[0] = 0; -#ifdef PALETTE_ADDED_MAP_PRIORITY - // TODO(b/389104950): Reenable this and remove #else once aosp/3355710 and aosp/3312350 - // are submitted. - bool success = true; - for (int p = kMinThreadPriority; p <= kMaxThreadPriority; ++p) { - palette_status_t result = PaletteMapPriority(p, &pm[p]); - if (result == PALETTE_STATUS_NOT_SUPPORTED) { - success = false; - break; - } - CHECK(result == PALETTE_STATUS_OK); - } -#else - constexpr bool success = false; -#endif - if (!success) { - // Discover the map the hard way. - int32_t me = static_cast<int32_t>(::art::GetTid()); - bool map_consistent; - errno = 0; - int orig_niceness = getpriority(PRIO_PROCESS, 0 /* self */); - CHECK(orig_niceness != -1 || errno == 0); - constexpr int kMaxIters = 10; - int iters = 0; - do { - map_consistent = true; - ++iters; - CHECK(iters <= kMaxIters); - for (int p = kMinThreadPriority; p <= kMaxThreadPriority; ++p) { - int ret = PaletteSchedSetPriority(me, p); - if (ret == PALETTE_STATUS_OK) { - errno = 0; - pm[p] = getpriority(PRIO_PROCESS, 0 /* self */); - CHECK(pm[p] != -1 || errno == 0); - LOG(INFO) << "Niceness[" << p << "] = " << pm[p]; -#ifdef ART_TARGET_ANDROID - // The map should be strictly monotonically decreasing. - if (p > kMinThreadPriority && pm[p] >= pm[p - 1]) { - // Maybe somebody else mucked with our priority? Start over. - map_consistent = false; - break; - } -#endif - } else { - canSetPriority = false; - LOG(WARNING) << "Cannot set priority to " << p; - // Fake the map with something plausible. - pm[p] = pm[p - 1] - 1; - } - } - } while (!map_consistent); - int ret = setpriority(PRIO_PROCESS, static_cast<id_t>(me), orig_niceness); - CHECK_EQ(ret, 0); - } -#ifndef ART_TARGET_ANDROID - if (pm[kMinThreadPriority] == 0 && pm[kMaxThreadPriority] == 0) { - // Palette calls don't impact getpriority(), as with the traditional - // PaletteSetSchedPriority fake on host. - canSetPriority = false; - LOG(WARNING) << "Failed to retrieve monotonic priority map : faking it"; - // Make the map monotonic, so we can map priority to niceness and back without losing - // information. - for (int p = kMinThreadPriority; p <= kMaxThreadPriority; ++p) { - pm[p] = 5 - p; - } - } -#endif - std::ostringstream priority_map_string; - for (int p = kMinThreadPriority; p <= kMaxThreadPriority; ++p) { - if (p != kMinThreadPriority) { - priority_map_string << ", "; - } - priority_map_string << priorityMap[p]; - } - LOG(INFO) << "Priority-to-niceness mapping: " << priority_map_string.str(); - }); - return priorityMap; +void Thread::SetNativePriority(int new_priority) { + palette_status_t status = PaletteSchedSetPriority(GetTid(), new_priority); + CHECK(status == PALETTE_STATUS_OK || status == PALETTE_STATUS_CHECK_ERRNO); } -// Many niceness values don't correspond to a priority. Find and return a close one. -int Thread::NicenessToPriority(int niceness) { - int* pm = GetPriorityMap(); - int* bound = std::lower_bound(pm + kMinThreadPriority, - pm + kMaxThreadPriority + 1, - niceness, - std::greater() /* niceness decreases */); - if (bound > pm + kMaxThreadPriority) { - return kMaxThreadPriority; - } - if (bound == pm + kMinThreadPriority) { - return kMinThreadPriority; - } - // The closest is either bound[0] or bound[-1]. - DCHECK_LE(bound[0], niceness); - DCHECK_GT(bound[-1], niceness); - // Resolve ties towards the higher priority. This usually maps system daemon priority to Java - // normal priority, which is the traditional behavior we test for. - return static_cast<int>((niceness - bound[0] > bound[-1] - niceness) ? bound - pm - 1 - : bound - pm); +int Thread::GetNativePriority() const { + int priority = 0; + palette_status_t status = PaletteSchedGetPriority(GetTid(), &priority); + CHECK(status == PALETTE_STATUS_OK || status == PALETTE_STATUS_CHECK_ERRNO); + return priority; } -int Thread::SetNativeNiceness(int niceness) { - int ret = setpriority(PRIO_PROCESS, static_cast<id_t>(GetTid()), niceness); - if (ret == 0) { - return 0; - } - LOG(WARNING) << "Cannot set niceness to " << niceness; - return errno; -} - -int Thread::GetNativeNiceness() const { - errno = 0; - int niceness = getpriority(PRIO_PROCESS, static_cast<id_t>(GetTid())); - CHECK(niceness != -1 || errno == 0); - return niceness; -} - -int Thread::SetNativePriority(int new_priority) { - if (canSetPriority) { - return SetNativeNiceness(PriorityToNiceness(new_priority)); - } - return ENODATA; // No priority mapping available. -} - -int Thread::GetNativePriority() const { return NicenessToPriority(GetNativeNiceness()); } - void Thread::AbortInThis(const std::string& message) { std::string thread_name; Thread::Current()->GetThreadName(thread_name);
diff --git a/runtime/thread.h b/runtime/thread.h index 0ac5bac..4a675d4 100644 --- a/runtime/thread.h +++ b/runtime/thread.h
@@ -606,33 +606,12 @@ bool HoldsLock(ObjPtr<mirror::Object> object) const REQUIRES_SHARED(Locks::mutator_lock_); /* - * Set native thread niceness to match the given Java priority. Only used from - * jvmti. Otherwise we represent priority as Linux niceness internally. + * Changes the priority of this thread to match that of the java.lang.Thread object. * * We map a priority value from 1-10 to Linux "nice" values, where lower * numbers indicate higher priority. - * - * Return 0 on success, or errno. */ - int SetNativePriority(int newPriority) REQUIRES_SHARED(Locks::mutator_lock_) - REQUIRES(Locks::thread_list_lock_); - - /* - * Same thing, but niceness is supplied directly. - * - * Return 0 on success, or errno. - */ - int SetNativeNiceness(int newNiceness) REQUIRES_SHARED(Locks::mutator_lock_); - - /* - * Convert Java priority to Posix niceness using palette information. - */ - static int PriorityToNiceness(int priority) { return GetPriorityMap()[priority]; } - - /* - * Convert Posix niceness to the closest Java priority using palette information. - */ - static int NicenessToPriority(int niceness); + void SetNativePriority(int newPriority); /* * Returns the priority of this thread by querying the system. @@ -642,11 +621,6 @@ */ int GetNativePriority() const; - /* - * Return Posix niceness instead of Java priority. A very thin wrapper over getpriority(). - */ - int GetNativeNiceness() const; - // Guaranteed to be non-zero. uint32_t GetThreadId() const { return tls32_.thin_lock_thread_id; @@ -1923,8 +1897,6 @@ static bool IsAotCompiler(); - static int* GetPriorityMap(); - void SetCachedThreadName(const char* name); // Helper functions to get/set the tls stack pointer variables.
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc index 5e01944..29be22c 100644 --- a/runtime/thread_list.cc +++ b/runtime/thread_list.cc
@@ -786,8 +786,7 @@ if (attempt_of_4 != 1) { // TODO: RequestSynchronousCheckpoint routinely passes attempt_of_4 = 0. Can // we avoid the getpriority() call? - if (getpriority(PRIO_PROCESS, 0 /* this thread */) > - Thread::PriorityToNiceness(kNormThreadPriority)) { + if (getpriority(PRIO_PROCESS, 0 /* this thread */) > 0) { // We're a low priority thread, and thus have a longer ANR timeout. Increase the suspend // timeout. avg_wait_multiplier = 3;
diff --git a/runtime/thread_pool.cc b/runtime/thread_pool.cc index fa6d5cf..80fd358 100644 --- a/runtime/thread_pool.cc +++ b/runtime/thread_pool.cc
@@ -154,7 +154,8 @@ runtime->DetachCurrentThread(/* should_run_callbacks= */ false); // On zygote fork, we wait for this thread to exit completely. Set to highest Java priority // to speed that up. - SetPriorityForTid(0 /* this thread */, Thread::PriorityToNiceness(kMaxThreadPriority)); + constexpr int kJavaMaxPrioNiceness = -8; + SetPriorityForTid(0 /* this thread */, kJavaMaxPrioNiceness); return nullptr; }
diff --git a/runtime/thread_priorities.md b/runtime/thread_priorities.md deleted file mode 100644 index 5cce7e8..0000000 --- a/runtime/thread_priorities.md +++ /dev/null
@@ -1,196 +0,0 @@ -Thread Priorities in Android ----------------------------- - -[TODO(b/389104950) Some of the following is currently more aspirational than fact. Implementation -is in progress. ] - -Unfortunately, this topic relies on several different kinds of thread "priority", which we will -try to distinguish as follows: - -1. The priority argument passed to Posix `setpriority()`, which affects Linux threads using - `SCHED_OTHER` scheduling. These range in value from -20 to 19, with larger values correspond to - *lower* scheduling priority. We will refer to these as "niceness". A difference of 1 in - niceness corresponds to something like a factor of 1.25 in processor share when cores are - overcommitted. Details may change as the Linux scheduler changes. - -2. Java thread priorities. In practice, these range from 1 to 10, with higher values corresponding - to higher scheduling priority. We refer to these as "java-priorities". - -3. The value of the `sched_priority` field, for example in the `sched_param` struct passed to - `sched_setparam()`. This affects only `SCHED_FIFO` and `SCHED_RR` scheduling policies. The - latter is not normally used in Android. The former has some limited uses as described below. - These threads always have higher scheduling priority than normal `SCHED_OTHER` threads, and - they can effectively preclude even essential system functions from running. Larger values - correspond to higher scheduling priority. We will refer to these as "rt-priorities". - -ART initially assumed that Java threads always used `SCHED_OTHER` Linux thread scheduling. Under -this discipline all threads get a chance to run, even when cores are overcommitted. However the -share of cpu time allocated to a particular thread varies greatly, by up to a factor of thousands, -depending on its "niceness", as set by `setpriority()` (or the swiss-army-knife `sched_setattr()`). - -In general java-priorities are mapped, via the platform supplied `libartpalette` to corresponding -niceness values for `SCHED_OTHER` threads, These niceness values are then installed with -`setpriority()`. - -The above assumptions are still generally true, but there are two important exceptions: - -1. ART occasionally assigns niceness values for internal daemon threads that are obtained by - interpolating between java-priorities. These niceness values do not map perfectly back onto - java-priorities. Thread.getPriority() rounds them to the nearest java-priority. - -2. Frameworks application management code may temporarily promote certain threads to `SCHED_FIFO` - scheduling with an associated rt-priority. As mentioned above, such threads cannot be preempted - by `SCHED_OTHER` threads. There are currently no clear rules about which threads may run under - `SCHED_FIFO` scheduling. In order to prevent deadlocks, all ART, libcore, and frameworks code - should be written so that it can safely run under `SCHED_FIFO`. This means that wait loops that - either spin consuming CPU time, or attempt to release it by calling `sched_yield()` or - `Thread.yield()` are *incorrect*. At a minimum they should eventually sleep for short periods. - Preferably, they should call an OS waiting primitive. Mutex acquisition, or Java's - `Object.wait()` do so internally. - -How to set priorities ---------------------- - -Java code is arguably allowed to expect that `Thread.getPriority()` returns the last value passed -to `Thread.setPriority()`, at least unless the application itself calls Android-specific code or -native code documented to alter thread priorities. This argues that `Thread.getPriority()` should -cache the current priority. Historically, this has also been done for performance reasons. We -continue to do so, though we now cache niceness rather than java-priority. - -In order to keep this cache accurate, applications should try to set priorities via -`Thread.setPriority(int)`. `android.os.Process.setThreadPriority(int)` may be used to set any -niceness value, and interacts correctly with the `Thread.getPriority()`. (This treatment -of `android.os.Process.setThreadPriority(int)` is currently still future work.) - -All other mechanisms, including `android.os.Process.setThreadPriority(int, int)` (with a thread id -parameter) bypass this cache. This has two effects: - -1. The change of priority is invisible to `Thread.getPriority()`. - -2. If the effect is to set a positive (> 0, i.e. low priority) niceness value, that effect may be - temporary, since ART, or the Java appliction may undo the effect. - -Avoiding races in setting priorities ------------------------------------- - -Priorities may be set either from within the process itself, or by external frameworks components. -If multiple threads or external components try to set the priority of a thread at the same time, -this is prone to races. For example: - -Consider a thread *A* that temporarily wants to raise its own priority from *x* to *y* and then -restore it to the initial priority *x*. If another thread happens to also raise its priority to -*y* while it is already temporarily raised to *y*, resulting in no immediate change, *A* will have -no way to tell that it should not lower the priority back to *x*. The update by the second thread -can thus be lost. - -In order to minimize such issues, all components should avoid racing priority updates and play by -the following rules: - -1. The application is entitled to adjust its own thread priorities. Everything else should - interfere with that as little as possible. The application should adjust priorities using - either `Thread.setPriority(int)` or `android.os.Process.setThreadPriority(int)`. JNI code that - updates the thread priority only for the duration of the call, may be able to adjust its - own priorities using OS calls, using something like the ART protocol outlined below, - so long as the JNI code does not call back into Java code sensitive to thread priorities. - The application should generally restore its priority to an expected value, such as a saved - value previously read via `Thread.getPriority()`, so that the value it restores is unaffected by - by priority adjustment from another process. - -2. ART may temporarily change the priority of an application thread with positive niceness to a - lower non-negative niceness value (usually zero), and then restore it it to the cached value as - detailed below. This happens only from within that thread itself. This is necessary, since - threads with large positive niceness may become esentially unresponsive under heavy load, and - may thus block essential runtime operations. - -3. External process priority updates, usually by another process, should not use mechanisms that - affect the cached value, specifically `android.os.Process.setThreadPriority(int)` or - `Thread.setPriority(int)`, so that such temporary updates do not result in the application - restoring the wrong value after a temprary priority adjustment. This is normally automatic, - since a cross-process niceness change doesn't affect the cached value. - -4. Priority updates using means other than `android.os.Process.setThreadPriority(int)` or - `Thread.setPriority(int)` should set a positive niceness value only when it is OK for ART (or - the application) to overwrite that with the value cached by Java at any point. ART will not - overwrite negative niceness values, unless the negative value is installed exactly between ART's - priority check and priority update. (There is no atomic priority update in Linux.) Hence, - ideally: - -5. In order to minimize interference with applications directly using OS primitive to - adjust priorities, external processes should avoid updating priorities of threads - executing managed code, or that may therwise be concurrently adjusting its own priorities. - If they do, ART can at any moment overwrite their updates and restore its cached value. - That is good, because it is not always clear how to enforce such timing constraints. - -ART may use the following to temporarily increase priority by lowering niceness to zero: - -``` - current_niceness = getpriority(<me>); - if (current_niceness <= 0 || current_niceness != <cached niceness>) - <do not change niceness>; - else - setpriority(<me>, 0); - <do high priority stuff that does not alter priority / niceness> - if (<we changed niceness> && getpriority(<me>) == 0) { - // Either there were no external intervening priority/niceness changes, or an - // external process restored our 0 niceness in the interim. Thread.setPriority(0) - // may have been called by another thread in the interim. In any of those cases, - // it is safe to restore priority with: - setpriority(<me>, <niceness cached by Java>); - // setpriority(<me>, current_niceness) would be incorrect with an intervening - // Thread.setPriority(0). - } -``` - -The above requires sufficient concurrency control to ensure that no `Thread.setPriority()` -calls overlap with the priority restoration at the end. - -Java priority to niceness mapping ---------------------------------- - -The priority mapping is mostly determined by libartpalette, which is a platform component -outside ART. Traditionally that provided `PaletteGetSchedPriority` and `PaletteSetSchedPriority`, -which returned and took Java priority arguments, thus attempting to entirely hide the mapping. -This turned out to be impractical, because some ART components, e.g. ART's system daemons, -were tuned to use niceness values that did not correspond to Java priorities, and thus used -Posix/Linux `setpriority` calls directly. This scheme also prevents us from easily caching -priorities set by `android.os.Process.setThreadPriority(int)`, which traffics in Linux niceness -values. - -Thus libartpalette now also provides `PaletteMapPriority()`, which is used in connection -with Linux `setpriority(), and is preferred when available. - -Kernel-supported priority inheritance ------------------------------------- - -ART often suffers from priority inversions: A high priority thread *A* waits for a lower -priority thread *B*. This may happen because *B* holds a lock that *A* needs, because *A* is -waiting for a condition variable that *B* will eventually signal, or because *A* is waiting -for *B* to pass a barrier, etc. The reason ART needs to explicitly adjust priorities is -mostly to work around this kind of situation. - -In the case of locks, there is a well-established technique for addressing this, which is -partially supported by the Linux kernel: If *A* blocks on a lock held by *B*, we can temporarily -raise *B*'s priority to *A*'s until the lock is released. The Linux kernel provides -`FUTEX_LOCK_PI` and pthreads provides `PTHREAD_PRIO_INHERIT` to support this. The implementation -avoids the race issues we discussed above, along with some others. It is thus quite attractive. - -We plan to make use of this facility in the future. There are ongoing discussions about expanding -it to cover some non-lock cases, which are equally important to us. However, there are currently -some obstacles in the way of such use: - -1. The kernel supports priority inheritance for non-real-time-threads only in 6.12 and later. Pure - real-time priority inheritance does not help us much, since it is, for good reason, rarely used. - -2. User-level support currently only exists for `pthread_mutex`, and not for various kinds of locks - used internally by ART, nor those by Java synchronized blocks, nor the Java-implemented locks - used by java.util.concurrent. For the former two, this would require at least a major redesign, - possibly with some negative performance consequences. For the latter, it's currently impossible - because the implementation builds directly on `park()` / `unpark()`, which do not expose the - thread being waited for to the kernel. - -3. Even for `pthread_mutex_lock()` we would have to be consistent about using - `PTHREAD_PRIO_INHERIT`everywhere. This may have negative performance consequences, and the Posix - standard appears to prohibit defaulting to it. - -Thus, at the moment, we basically do not use kernel-supported priority inheritance. But stay -tuned.
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index 2629b6c..14b0fee 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc
@@ -137,9 +137,8 @@ ArtField* WellKnownClasses::java_lang_Thread_group; ArtField* WellKnownClasses::java_lang_Thread_lock; ArtField* WellKnownClasses::java_lang_Thread_name; -ArtField* WellKnownClasses::java_lang_Thread_niceness; -ArtField* WellKnownClasses::java_lang_Thread_nativePeer; ArtField* WellKnownClasses::java_lang_Thread_priority; +ArtField* WellKnownClasses::java_lang_Thread_nativePeer; ArtField* WellKnownClasses::java_lang_Thread_systemDaemon; ArtField* WellKnownClasses::java_lang_Thread_unparkedBeforeStart; ArtField* WellKnownClasses::java_lang_ThreadGroup_groups; @@ -808,10 +807,9 @@ CacheField(j_l_Thread.Get(), /*is_static=*/ false, "lock", "Ljava/lang/Object;"); java_lang_Thread_name = CacheField(j_l_Thread.Get(), /*is_static=*/ false, "name", "Ljava/lang/String;"); - java_lang_Thread_niceness = CacheField(j_l_Thread.Get(), /*is_static=*/false, "niceness", "I"); + java_lang_Thread_priority = CacheField(j_l_Thread.Get(), /*is_static=*/ false, "priority", "I"); java_lang_Thread_nativePeer = CacheField(j_l_Thread.Get(), /*is_static=*/ false, "nativePeer", "J"); - java_lang_Thread_priority = CacheField(j_l_Thread.Get(), /*is_static=*/false, "priority", "I"); java_lang_Thread_systemDaemon = CacheField(j_l_Thread.Get(), /*is_static=*/ false, "systemDaemon", "Z"); java_lang_Thread_unparkedBeforeStart = @@ -1001,9 +999,8 @@ java_lang_Thread_group = nullptr; java_lang_Thread_lock = nullptr; java_lang_Thread_name = nullptr; - java_lang_Thread_niceness = nullptr; - java_lang_Thread_nativePeer = nullptr; java_lang_Thread_priority = nullptr; + java_lang_Thread_nativePeer = nullptr; java_lang_ThreadGroup_groups = nullptr; java_lang_ThreadGroup_ngroups = nullptr; java_lang_ThreadGroup_mainThreadGroup = nullptr;
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h index c58ff39..8798744 100644 --- a/runtime/well_known_classes.h +++ b/runtime/well_known_classes.h
@@ -183,9 +183,8 @@ static ArtField* java_lang_Thread_group; static ArtField* java_lang_Thread_lock; static ArtField* java_lang_Thread_name; - static ArtField* java_lang_Thread_niceness; - static ArtField* java_lang_Thread_nativePeer; static ArtField* java_lang_Thread_priority; + static ArtField* java_lang_Thread_nativePeer; static ArtField* java_lang_Thread_systemDaemon; static ArtField* java_lang_Thread_unparkedBeforeStart; static ArtField* java_lang_ThreadGroup_groups;
diff --git a/test/733-priority-mappings/build.py b/test/733-priority-mappings/build.py deleted file mode 100644 index 7025b81..0000000 --- a/test/733-priority-mappings/build.py +++ /dev/null
@@ -1,20 +0,0 @@ -# -# Copyright (C) 2022 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -def build(ctx): - if ctx.jvm: - return # The test does not build on JVM - ctx.default_build()
diff --git a/test/733-priority-mappings/expected-stderr.txt b/test/733-priority-mappings/expected-stderr.txt deleted file mode 100644 index e69de29..0000000 --- a/test/733-priority-mappings/expected-stderr.txt +++ /dev/null
diff --git a/test/733-priority-mappings/expected-stdout.txt b/test/733-priority-mappings/expected-stdout.txt deleted file mode 100644 index a965a70..0000000 --- a/test/733-priority-mappings/expected-stdout.txt +++ /dev/null
@@ -1 +0,0 @@ -Done
diff --git a/test/733-priority-mappings/info.txt b/test/733-priority-mappings/info.txt deleted file mode 100644 index b4ab8e0..0000000 --- a/test/733-priority-mappings/info.txt +++ /dev/null
@@ -1,2 +0,0 @@ -Basic check for our priority <--> niceness mapping infrastructure, in support -of Thread.setPriority() and friends.
diff --git a/test/733-priority-mappings/src/Main.java b/test/733-priority-mappings/src/Main.java deleted file mode 100644 index bf02cc0..0000000 --- a/test/733-priority-mappings/src/Main.java +++ /dev/null
@@ -1,57 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import dalvik.system.VMRuntime; - -public class Main { - public static void main(String[] args) throws Exception { - for (int p = Thread.MIN_PRIORITY; p <= Thread.MAX_PRIORITY; ++p) { - int niceness = Thread.nicenessForPriority(p); - if (p > Thread.MIN_PRIORITY && Thread.nicenessForPriority(p - 1) <= niceness) { - throw new Error("Niceness not monotonic at " + p); - } - int mapped_p = Thread.priorityForNiceness(Thread.nicenessForPriority(p)); - if (mapped_p != p) { - throw new Error(p + " mapped to: " + Thread.nicenessForPriority(p) + - " which mapped back to " + mapped_p); - } - } - Thread self = Thread.currentThread(); - VMRuntime vmrt = VMRuntime.getRuntime(); - for (int p = Thread.MIN_PRIORITY; p <= Thread.MAX_PRIORITY; ++p) { - self.setPriority(p); - int result = self.getPriority(); - if (result != p) { - System.out.println("Set priority to " + p + " but got " + result); - } - int niceness_result = vmrt.getThreadNiceness(self); - if (niceness_result != Thread.nicenessForPriority(p)) { - System.out.println("Set priority to " + p - + " but got niceness " + niceness_result); - } - } - for (int n = -20; n <= 19; ++n) { - vmrt.setThreadNiceness(self, n); - int result = vmrt.getThreadNiceness(self); - if (result != n) { - System.out.println("Set niceness to " + n + " but got " + result); - } - } - System.out.println("Done"); - } - - private static native int getThreadPlatformPriority(); -}
diff --git a/test/913-heaps/expected-stdout.txt b/test/913-heaps/expected-stdout.txt index 8bb34ab..87ad2d6 100644 --- a/test/913-heaps/expected-stdout.txt +++ b/test/913-heaps/expected-stdout.txt
@@ -1,8 +1,8 @@ --- true true root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=0,location= 31])--> 1@1000 [size=16, length=-1] -root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1] -root@root --(thread)--> 3000@0 [size=124, length=-1] +root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=120, length=-1] +root@root --(thread)--> 3000@0 [size=120, length=-1] 1001@0 --(superclass)--> 1000@0 [size=123456780000, length=-1] 1002@0 --(interface)--> 2001@0 [size=123456780004, length=-1] 1002@0 --(superclass)--> 1001@0 [size=123456780001, length=-1] @@ -46,8 +46,8 @@ root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1] root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1] root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=5,location= 20])--> 1@1000 [size=16, length=-1] -root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1] -root@root --(thread)--> 3000@0 [size=124, length=-1] +root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=120, length=-1] +root@root --(thread)--> 3000@0 [size=120, length=-1] 1001@0 --(superclass)--> 1000@0 [size=123456780005, length=-1] 1002@0 --(interface)--> 2001@0 [size=123456780009, length=-1] 1002@0 --(superclass)--> 1001@0 [size=123456780006, length=-1] @@ -86,17 +86,17 @@ 5@1002 --(field@9)--> 6@1000 [size=16, length=-1] 6@1000 --(class)--> 1000@0 [size=123456780005, length=-1] --- -root@root --(thread)--> 3000@0 [size=124, length=-1] +root@root --(thread)--> 3000@0 [size=120, length=-1] --- 3@1001 --(class)--> 1001@0 [size=123456780011, length=-1] --- -root@root --(thread)--> 3000@0 [size=124, length=-1] +root@root --(thread)--> 3000@0 [size=120, length=-1] --- 3@1001 --(class)--> 1001@0 [size=123456780016, length=-1] --- root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=0,location= 31])--> 1@1000 [size=16, length=-1] -root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1] -root@root --(thread)--> 3000@0 [size=124, length=-1] +root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=120, length=-1] +root@root --(thread)--> 3000@0 [size=120, length=-1] --- 1001@0 --(superclass)--> 1000@0 [size=123456780020, length=-1] 3@1001 --(class)--> 1001@0 [size=123456780021, length=-1] @@ -108,8 +108,8 @@ root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1] root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1] root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=5,location= 20])--> 1@1000 [size=16, length=-1] -root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1] -root@root --(thread)--> 3000@0 [size=124, length=-1] +root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=120, length=-1] +root@root --(thread)--> 3000@0 [size=120, length=-1] --- 1001@0 --(superclass)--> 1000@0 [size=123456780025, length=-1] 3@1001 --(class)--> 1001@0 [size=123456780026, length=-1] @@ -189,8 +189,8 @@ --- ---- untagged objects root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=0,location= 31])--> 1@1000 [size=16, length=-1] -root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1] -root@root --(thread)--> 3000@0 [size=124, length=-1] +root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=120, length=-1] +root@root --(thread)--> 3000@0 [size=120, length=-1] 1001@0 --(superclass)--> 1000@0 [size=123456780050, length=-1] 1002@0 --(interface)--> 2001@0 [size=123456780054, length=-1] 1002@0 --(superclass)--> 1001@0 [size=123456780051, length=-1] @@ -234,8 +234,8 @@ root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1] root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1] root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=5,location= 20])--> 1@1000 [size=16, length=-1] -root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1] -root@root --(thread)--> 3000@0 [size=124, length=-1] +root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=120, length=-1] +root@root --(thread)--> 3000@0 [size=120, length=-1] 1001@0 --(superclass)--> 1000@0 [size=123456780055, length=-1] 1002@0 --(interface)--> 2001@0 [size=123456780059, length=-1] 1002@0 --(superclass)--> 1001@0 [size=123456780056, length=-1] @@ -275,8 +275,8 @@ 6@1000 --(class)--> 1000@0 [size=123456780055, length=-1] --- ---- tagged classes -root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1] -root@root --(thread)--> 3000@0 [size=124, length=-1] +root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=120, length=-1] +root@root --(thread)--> 3000@0 [size=120, length=-1] 1001@0 --(superclass)--> 1000@0 [size=123456780060, length=-1] 1002@0 --(interface)--> 2001@0 [size=123456780064, length=-1] 1002@0 --(superclass)--> 1001@0 [size=123456780061, length=-1] @@ -301,8 +301,8 @@ 5@1002 --(field@8)--> 500@0 [size=20, length=2] 6@1000 --(class)--> 1000@0 [size=123456780060, length=-1] --- -root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1] -root@root --(thread)--> 3000@0 [size=124, length=-1] +root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=120, length=-1] +root@root --(thread)--> 3000@0 [size=120, length=-1] 1001@0 --(superclass)--> 1000@0 [size=123456780065, length=-1] 1002@0 --(interface)--> 2001@0 [size=123456780069, length=-1] 1002@0 --(superclass)--> 1001@0 [size=123456780066, length=-1]
diff --git a/test/913-heaps/info.txt b/test/913-heaps/info.txt index 5dd3f9e..875a5f6 100644 --- a/test/913-heaps/info.txt +++ b/test/913-heaps/info.txt
@@ -1,2 +1 @@ Tests basic functions in the jvmti plugin. -Output expectation depends on size of Java Thread objects.
diff --git a/test/knownfailures.json b/test/knownfailures.json index 91fc39a..4d2d8ae 100644 --- a/test/knownfailures.json +++ b/test/knownfailures.json
@@ -1141,7 +1141,6 @@ "692-vdex-inmem-loader", "693-vdex-inmem-loader-evict", "723-string-init-range", - "733-priority-mappings", "734-duplicate-fields", "735-interface-clone", "736-interface-super-Object",