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 */
35 static 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
os_changeThreadPriority(Thread * thread,int newPriority)48 void 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
os_getThreadPriorityFromSystem()73 int 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
os_raiseThreadPriority()95 int 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
os_lowerThreadPriority(int oldThreadPriority)128 void 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