Home | History | Annotate | Download | only in os
      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 <system/thread_defs.h>
     27 #include <cutils/sched_policy.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         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 
     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 
     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 
    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