huangcm
2025-05-08 76a1e955045b9ab0f6ff3d883403d08e1fcd2752
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*
 * Copyright (C) 2017 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;
 
/**
 * Utility class to boost threads in sections where important locks are held.
 */
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;
 
    private final ThreadLocal<PriorityState> mThreadState = new ThreadLocal<PriorityState>() {
        @Override protected PriorityState initialValue() {
            return new PriorityState();
        }
    };
 
    public ThreadPriorityBooster(int boostToPriority, int lockGuardIndex) {
        mBoostToPriority = boostToPriority;
        mLockGuardIndex = lockGuardIndex;
    }
 
    public void boost() {
        final PriorityState state = mThreadState.get();
        if (state.regionCounter == 0) {
            final int prevPriority = getThreadPriority(state.tid);
            if (prevPriority > mBoostToPriority) {
                setThreadPriority(state.tid, mBoostToPriority);
                state.prevPriority = prevPriority;
            }
        }
        state.regionCounter++;
        if (ENABLE_LOCK_GUARD) {
            LockGuard.guard(mLockGuardIndex);
        }
    }
 
    public void reset() {
        final PriorityState state = mThreadState.get();
        state.regionCounter--;
        if (state.regionCounter == 0 && state.prevPriority != PRIORITY_NOT_ADJUSTED) {
            setThreadPriority(state.tid, state.prevPriority);
            state.prevPriority = PRIORITY_NOT_ADJUSTED;
        }
    }
 
    /**
     * Updates the priority we boost the threads to, and updates the current thread's priority if
     * necessary.
     */
    protected void setBoostToPriority(int priority) {
 
        // We don't care about the other threads here, as long as they see the update of this
        // variable immediately.
        mBoostToPriority = priority;
        final PriorityState state = mThreadState.get();
        if (state.regionCounter != 0) {
            final int prevPriority = getThreadPriority(state.tid);
            if (prevPriority != 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
         * the current thread is currently in. When it drops down to zero, we will no longer boost
         * the thread's priority.
         */
        int regionCounter;
 
        /**
         * The thread's previous priority before boosting.
         */
        int prevPriority = PRIORITY_NOT_ADJUSTED;
    }
}