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 48 void os_changeThreadPriority(Thread* thread, int newPriority) 49 { 50 if (newPriority < 1 || newPriority > 10) { 51 LOGW("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 LOGI("setPriority(%d) '%s' to prio=%d(n=%d) failed: %s", 67 pid, threadName.c_str(), newPriority, newNice, strerror(errno)); 68 } else { 69 LOGV("setPriority(%d) to prio=%d(n=%d)", pid, newPriority, newNice); 70 } 71 } 72 73 int os_getThreadPriorityFromSystem() 74 { 75 errno = 0; 76 int sysprio = getpriority(PRIO_PROCESS, 0); 77 if (sysprio == -1 && errno != 0) { 78 LOGW("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 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 LOGI("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 LOGI("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 LOGV("Elevating priority from %d to %d", 121 oldThreadPriority, ANDROID_PRIORITY_NORMAL); 122 return oldThreadPriority; 123 } 124 } 125 return INT_MAX; 126 } 127 128 void os_lowerThreadPriority(int oldThreadPriority) 129 { 130 if (setpriority(PRIO_PROCESS, 0, oldThreadPriority) != 0) { 131 LOGW("Unable to reset priority to %d: %s", 132 oldThreadPriority, strerror(errno)); 133 } else { 134 LOGV("Reset priority to %d", oldThreadPriority); 135 } 136 if (oldThreadPriority >= ANDROID_PRIORITY_BACKGROUND) { 137 set_sched_policy(dvmGetSysThreadId(), SP_BACKGROUND); 138 } 139 } 140