blob: f38da4305e985d65ed78f3cf703153ec79a5c202 [file]
/*
* Copyright (C) 2025 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.
*/
#include "scoped_thread_priority_change.h"
#include <sys/resource.h>
#include "base/mutex.h"
#include "com_android_libcore.h"
#include "thread-inl.h"
namespace art HIDDEN {
void ScopedPriorityChange::SetToNormalOrBetter() {
static bool enabled = com::android::libcore::niceness_apis();
if (!enabled) {
return;
}
DCHECK(!priority_changed_);
int cached_niceness = self_->GetCachedNiceness();
if (cached_niceness > 0 /* excludes no Java peer case */) {
int old_niceness = getpriority(PRIO_PROCESS, 0);
if (old_niceness == cached_niceness) {
// Reduce nicenesss to zero, increasing our priority.
// Should succeed on Android; will probably fail elsewhere.
int ret = setpriority(PRIO_PROCESS, 0, 0);
if (ret == 0) {
priority_changed_ = true;
}
} else if (old_niceness > 0) {
// Priority increase is warranted, but cache is out of sync.
LOG(WARNING) << "Cached niceness = " << cached_niceness
<< "; actual niceness = " << old_niceness;
}
}
}
void ScopedPriorityChange::ResetInternal() {
DCHECK(priority_changed_);
DCHECK(com::android::libcore::niceness_apis());
Locks::mutator_lock_->AssertSharedHeld(self_);
if (getpriority(PRIO_PROCESS, 0) == 0) {
// We changed priority and nobody visibly altered it in the interim; change it to the current
// cached value.
int cached_niceness = self_->GetCachedNiceness();
int old_cached_niceness;
// We cannot acquire the Java monitor that normally protects the niceness field here, since that
// would sometimes require us to suspend. We instead rely on the fact that any updates to the
// niceness fields while the thread is running are followed by a setpriority() call with the
// same niceness value.
do {
int ret = setpriority(PRIO_PROCESS, 0, cached_niceness);
// Increasing our niceness should always work, especially since decreasing it did.
CHECK_EQ(ret, 0) << strerror(errno);
old_cached_niceness = cached_niceness;
cached_niceness = self_->GetCachedNiceness();
// If it changed in the interim, we may have restored an obsolete niceness value, and we
// need to fix that. Otherwise any later updates will come with following setpriority()
// calls, which will overwrite ours.
} while (cached_niceness != old_cached_niceness);
} else {
LOG(WARNING) << "Priority change inside ScopedPriorityChange";
// Do not restore priority, since somebody else changed it in the interim.
}
}
} // namespace art