Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7ae454f authored by Riddle Hsu's avatar Riddle Hsu Committed by android-build-merger
Browse files

Merge "Reduce system calls of ThreadPriorityBooster" into qt-dev

am: 00e76b8c

Change-Id: I1cd901b20b5bd08519fde5c105de87c2e8664e94
parents 33a49acd 00e76b8c
Loading
Loading
Loading
Loading
+12 −14
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.os.Process.setThreadPriority;
public class ThreadPriorityBooster {

    private static final boolean ENABLE_LOCK_GUARD = false;
    private static final int PRIORITY_NOT_ADJUSTED = Integer.MAX_VALUE;

    private volatile int mBoostToPriority;
    private final int mLockGuardIndex;
@@ -42,13 +43,12 @@ public class ThreadPriorityBooster {
    }

    public void boost() {
        final int tid = myTid();
        final PriorityState state = mThreadState.get();
        if (state.regionCounter == 0) {
            final int prevPriority = getThreadPriority(tid);
            state.prevPriority = prevPriority;
            final int prevPriority = getThreadPriority(state.tid);
            if (prevPriority > mBoostToPriority) {
                setThreadPriority(tid, mBoostToPriority);
                setThreadPriority(state.tid, mBoostToPriority);
                state.prevPriority = prevPriority;
            }
        }
        state.regionCounter++;
@@ -60,11 +60,9 @@ public class ThreadPriorityBooster {
    public void reset() {
        final PriorityState state = mThreadState.get();
        state.regionCounter--;
        if (state.regionCounter == 0) {
            final int currentPriority = getThreadPriority(myTid());
            if (state.prevPriority != currentPriority) {
                setThreadPriority(myTid(), state.prevPriority);
            }
        if (state.regionCounter == 0 && state.prevPriority != PRIORITY_NOT_ADJUSTED) {
            setThreadPriority(state.tid, state.prevPriority);
            state.prevPriority = PRIORITY_NOT_ADJUSTED;
        }
    }

@@ -78,16 +76,16 @@ public class ThreadPriorityBooster {
        // variable immediately.
        mBoostToPriority = priority;
        final PriorityState state = mThreadState.get();
        final int tid = myTid();
        if (state.regionCounter != 0) {
            final int prevPriority = getThreadPriority(tid);
            final int prevPriority = getThreadPriority(state.tid);
            if (prevPriority != priority) {
                setThreadPriority(tid, priority);
                setThreadPriority(state.tid, priority);
            }
        }
    }

    private static class PriorityState {
        final int tid = myTid();

        /**
         * 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.
         */
        int prevPriority;
        int prevPriority = PRIORITY_NOT_ADJUSTED;
    }
}
+97 −0
Original line number Diff line number Diff line
/*
 * 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();
        }
    }
}