Merge "Reduce system calls of ThreadPriorityBooster" into qt-dev
am: 00e76b8c13
Change-Id: I1cd901b20b5bd08519fde5c105de87c2e8664e94
This commit is contained in:
@@ -26,6 +26,7 @@ import static android.os.Process.setThreadPriority;
|
|||||||
public class ThreadPriorityBooster {
|
public class ThreadPriorityBooster {
|
||||||
|
|
||||||
private static final boolean ENABLE_LOCK_GUARD = false;
|
private static final boolean ENABLE_LOCK_GUARD = false;
|
||||||
|
private static final int PRIORITY_NOT_ADJUSTED = Integer.MAX_VALUE;
|
||||||
|
|
||||||
private volatile int mBoostToPriority;
|
private volatile int mBoostToPriority;
|
||||||
private final int mLockGuardIndex;
|
private final int mLockGuardIndex;
|
||||||
@@ -42,13 +43,12 @@ public class ThreadPriorityBooster {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void boost() {
|
public void boost() {
|
||||||
final int tid = myTid();
|
|
||||||
final PriorityState state = mThreadState.get();
|
final PriorityState state = mThreadState.get();
|
||||||
if (state.regionCounter == 0) {
|
if (state.regionCounter == 0) {
|
||||||
final int prevPriority = getThreadPriority(tid);
|
final int prevPriority = getThreadPriority(state.tid);
|
||||||
state.prevPriority = prevPriority;
|
|
||||||
if (prevPriority > mBoostToPriority) {
|
if (prevPriority > mBoostToPriority) {
|
||||||
setThreadPriority(tid, mBoostToPriority);
|
setThreadPriority(state.tid, mBoostToPriority);
|
||||||
|
state.prevPriority = prevPriority;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.regionCounter++;
|
state.regionCounter++;
|
||||||
@@ -60,11 +60,9 @@ public class ThreadPriorityBooster {
|
|||||||
public void reset() {
|
public void reset() {
|
||||||
final PriorityState state = mThreadState.get();
|
final PriorityState state = mThreadState.get();
|
||||||
state.regionCounter--;
|
state.regionCounter--;
|
||||||
if (state.regionCounter == 0) {
|
if (state.regionCounter == 0 && state.prevPriority != PRIORITY_NOT_ADJUSTED) {
|
||||||
final int currentPriority = getThreadPriority(myTid());
|
setThreadPriority(state.tid, state.prevPriority);
|
||||||
if (state.prevPriority != currentPriority) {
|
state.prevPriority = PRIORITY_NOT_ADJUSTED;
|
||||||
setThreadPriority(myTid(), state.prevPriority);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,16 +76,16 @@ public class ThreadPriorityBooster {
|
|||||||
// variable immediately.
|
// variable immediately.
|
||||||
mBoostToPriority = priority;
|
mBoostToPriority = priority;
|
||||||
final PriorityState state = mThreadState.get();
|
final PriorityState state = mThreadState.get();
|
||||||
final int tid = myTid();
|
|
||||||
if (state.regionCounter != 0) {
|
if (state.regionCounter != 0) {
|
||||||
final int prevPriority = getThreadPriority(tid);
|
final int prevPriority = getThreadPriority(state.tid);
|
||||||
if (prevPriority != priority) {
|
if (prevPriority != priority) {
|
||||||
setThreadPriority(tid, priority);
|
setThreadPriority(state.tid, priority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class PriorityState {
|
private static class PriorityState {
|
||||||
|
final int tid = myTid();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Acts as counter for number of synchronized region that needs to acquire 'this' as a lock
|
* Acts as counter for number of synchronized region that needs to acquire 'this' as a lock
|
||||||
@@ -99,6 +97,6 @@ public class ThreadPriorityBooster {
|
|||||||
/**
|
/**
|
||||||
* The thread's previous priority before boosting.
|
* The thread's previous priority before boosting.
|
||||||
*/
|
*/
|
||||||
int prevPriority;
|
int prevPriority = PRIORITY_NOT_ADJUSTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.server;
|
||||||
|
|
||||||
|
import static android.os.Process.getThreadPriority;
|
||||||
|
import static android.os.Process.myTid;
|
||||||
|
import static android.os.Process.setThreadPriority;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import android.os.Process;
|
||||||
|
import android.platform.test.annotations.Presubmit;
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link ThreadPriorityBooster}.
|
||||||
|
* Build/Install/Run:
|
||||||
|
* atest FrameworksServicesTests:ThreadPriorityBoosterTest
|
||||||
|
*/
|
||||||
|
@SmallTest
|
||||||
|
@Presubmit
|
||||||
|
public class ThreadPriorityBoosterTest {
|
||||||
|
private static final int PRIORITY_BOOST = Process.THREAD_PRIORITY_FOREGROUND;
|
||||||
|
private static final int PRIORITY_BOOST_MORE = Process.THREAD_PRIORITY_DISPLAY;
|
||||||
|
|
||||||
|
private final ThreadPriorityBooster mBooster = new ThreadPriorityBooster(PRIORITY_BOOST,
|
||||||
|
0 /* lockGuardIndex */);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThreadPriorityBooster() {
|
||||||
|
joinNewThread(() -> {
|
||||||
|
final int origPriority = Process.THREAD_PRIORITY_DEFAULT;
|
||||||
|
setThreadPriority(origPriority);
|
||||||
|
|
||||||
|
boost(() -> {
|
||||||
|
assertThreadPriority(PRIORITY_BOOST);
|
||||||
|
boost(() -> {
|
||||||
|
// Inside the boost region, the priority should also apply to current thread.
|
||||||
|
mBooster.setBoostToPriority(PRIORITY_BOOST_MORE);
|
||||||
|
assertThreadPriority(PRIORITY_BOOST_MORE);
|
||||||
|
});
|
||||||
|
// It is still in the boost region so the set priority should be kept.
|
||||||
|
assertThreadPriority(PRIORITY_BOOST_MORE);
|
||||||
|
|
||||||
|
joinNewThread(() -> boost(() -> assertThreadPriority(PRIORITY_BOOST_MORE)));
|
||||||
|
});
|
||||||
|
// The priority should be restored after leaving the boost region.
|
||||||
|
assertThreadPriority(origPriority);
|
||||||
|
|
||||||
|
// It doesn't apply to current thread because outside of the boost region, but the boost
|
||||||
|
// in other threads will use the set priority.
|
||||||
|
mBooster.setBoostToPriority(PRIORITY_BOOST);
|
||||||
|
joinNewThread(() -> boost(() -> assertThreadPriority(PRIORITY_BOOST)));
|
||||||
|
|
||||||
|
assertThreadPriority(origPriority);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertThreadPriority(int expectedPriority) {
|
||||||
|
assertEquals(expectedPriority, getThreadPriority(myTid()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void joinNewThread(Runnable action) {
|
||||||
|
final Thread thread = new Thread(action);
|
||||||
|
thread.start();
|
||||||
|
try {
|
||||||
|
thread.join();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void boost(Runnable action) {
|
||||||
|
try {
|
||||||
|
mBooster.boost();
|
||||||
|
action.run();
|
||||||
|
} finally {
|
||||||
|
mBooster.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user