android.cpp revision e8e1ddccd616e8226b7cc1e4e9fdb327429249e8
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "os.h"
18
19#include "Dalvik.h"
20
21#include <sys/time.h>
22#include <sys/resource.h>
23#include <limits.h>
24#include <errno.h>
25
26#include <cutils/sched_policy.h>
27#include <utils/threads.h>
28
29/*
30 * Conversion map for "nice" values.
31 *
32 * We use Android thread priority constants to be consistent with the rest
33 * of the system.  In some cases adjacent entries may overlap.
34 */
35static const int kNiceValues[10] = {
36    ANDROID_PRIORITY_LOWEST,                /* 1 (MIN_PRIORITY) */
37    ANDROID_PRIORITY_BACKGROUND + 6,
38    ANDROID_PRIORITY_BACKGROUND + 3,
39    ANDROID_PRIORITY_BACKGROUND,
40    ANDROID_PRIORITY_NORMAL,                /* 5 (NORM_PRIORITY) */
41    ANDROID_PRIORITY_NORMAL - 2,
42    ANDROID_PRIORITY_NORMAL - 4,
43    ANDROID_PRIORITY_URGENT_DISPLAY + 3,
44    ANDROID_PRIORITY_URGENT_DISPLAY + 2,
45    ANDROID_PRIORITY_URGENT_DISPLAY         /* 10 (MAX_PRIORITY) */
46};
47
48void os_changeThreadPriority(Thread* thread, int newPriority)
49{
50    if (newPriority < 1 || newPriority > 10) {
51        ALOGW("bad priority %d", newPriority);
52        newPriority = 5;
53    }
54
55    int newNice = kNiceValues[newPriority-1];
56    pid_t pid = thread->systemTid;
57
58    if (newNice >= ANDROID_PRIORITY_BACKGROUND) {
59        set_sched_policy(dvmGetSysThreadId(), SP_BACKGROUND);
60    } else if (getpriority(PRIO_PROCESS, pid) >= ANDROID_PRIORITY_BACKGROUND) {
61        set_sched_policy(dvmGetSysThreadId(), SP_FOREGROUND);
62    }
63
64    if (setpriority(PRIO_PROCESS, pid, newNice) != 0) {
65        std::string threadName(dvmGetThreadName(thread));
66        ALOGI("setPriority(%d) '%s' to prio=%d(n=%d) failed: %s",
67        pid, threadName.c_str(), newPriority, newNice, strerror(errno));
68    } else {
69        ALOGV("setPriority(%d) to prio=%d(n=%d)", pid, newPriority, newNice);
70    }
71}
72
73int os_getThreadPriorityFromSystem()
74{
75    errno = 0;
76    int sysprio = getpriority(PRIO_PROCESS, 0);
77    if (sysprio == -1 && errno != 0) {
78        ALOGW("getpriority() failed: %s", strerror(errno));
79        return THREAD_NORM_PRIORITY;
80    }
81
82    int jprio = THREAD_MIN_PRIORITY;
83    for (int i = 0; i < NELEM(kNiceValues); i++) {
84        if (sysprio >= kNiceValues[i]) {
85            break;
86        }
87        jprio++;
88    }
89    if (jprio > THREAD_MAX_PRIORITY) {
90        jprio = THREAD_MAX_PRIORITY;
91    }
92    return jprio;
93}
94
95int os_raiseThreadPriority()
96{
97    /* Get the priority (the "nice" value) of the current thread.  The
98     * getpriority() call can legitimately return -1, so we have to
99     * explicitly test errno.
100     */
101    errno = 0;
102    int oldThreadPriority = getpriority(PRIO_PROCESS, 0);
103    if (errno != 0) {
104        ALOGI("getpriority(self) failed: %s", strerror(errno));
105    } else if (oldThreadPriority > ANDROID_PRIORITY_NORMAL) {
106        /* Current value is numerically greater than "normal", which
107         * in backward UNIX terms means lower priority.
108         */
109        if (oldThreadPriority >= ANDROID_PRIORITY_BACKGROUND) {
110            set_sched_policy(dvmGetSysThreadId(), SP_FOREGROUND);
111        }
112        if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL) != 0) {
113            ALOGI("Unable to elevate priority from %d to %d",
114                    oldThreadPriority, ANDROID_PRIORITY_NORMAL);
115        } else {
116            /*
117             * The priority has been elevated.  Return the old value
118             * so the caller can restore it later.
119             */
120            ALOGV("Elevating priority from %d to %d",
121                    oldThreadPriority, ANDROID_PRIORITY_NORMAL);
122            return oldThreadPriority;
123        }
124    }
125    return INT_MAX;
126}
127
128void os_lowerThreadPriority(int oldThreadPriority)
129{
130    if (setpriority(PRIO_PROCESS, 0, oldThreadPriority) != 0) {
131        ALOGW("Unable to reset priority to %d: %s",
132                oldThreadPriority, strerror(errno));
133    } else {
134        ALOGV("Reset priority to %d", oldThreadPriority);
135    }
136    if (oldThreadPriority >= ANDROID_PRIORITY_BACKGROUND) {
137        set_sched_policy(dvmGetSysThreadId(), SP_BACKGROUND);
138    }
139}
140