AndroidScheduling

freakingtux edited this page Feb 23, 2012 · 3 revisions

Scheduling in Android

Upfront read the post from Dianne Hackborn about scheduling

Normal scheduling

Android is based on Linux and uses the Linux kernel’s scheduling mechanisms for determining scheduling policies. This is also true for Java code and threads.
The Linux’s time sliced scheduling policy combines static and dynamic priorities. Processes can be given an initial priority from 19 to -20 (very low to very high priority). This priority will assure that higher priority processes will get more CPU time when when needed. These level are however dynamic, low level priority tasks that do not consume their CPU time will fine their dynamic priority increased. This dynamic behaviour results is an overall better responsiveness.

In terms of dynamic priorities it is ensured that lower priority processes will always have a lower dynamic priority than processes with real-time priorities.

Android uses two different mechanisms when scheduling the Linux kernel to perform process level scheduling

real-time scheduling

The standard Linux kernel provides two real-time scheduling policies, SCHED_FIFO and SCHED_RR. The main real-time policy is SCHED_FIFO. It implements a first-in, first-out scheduling algorithm. When a SCHED_FIFO task starts running, it continues to run until it voluntarily yields the processor, blocks or is preempted by a higher-priority real-time task. It has no timeslices. All other tasks of lower priority will not be scheduled until it relinquishes the CPU. Two equal-priority SCHED_FIFO tasks do not preempt each other. SCHED_RR is similar to SCHED_FIFO, except that such tasks are allotted timeslices based on their priority and run until they exhaust their timeslice. Non-real-time tasks use the SCHED_NORMAL scheduling policy (older kernels had a policy named SCHED_OTHER).

see Documentation/cgroups/cgroups.txt

http://www.kernel.org/doc/Documentation/scheduler/sched-rt-group.txt

The default Android kernel is configured to allow group scheduling of real time processes and the file system to control this is mounted under /dev/cpuctl.

Android uses two different scheduling classes (using linux cgroups) bg_non_interactive and default (foreground). The configuration is that bg_non_interactive is low priority and can maximum
utilize ~5% of the cpu (including all background tasks) and foreground ~95%. Forground means either an Activity or a service that is started foregound.
At startup Services are running in bg_non_interactive unless they have been elevated to foreground scheduling group using startForeground (HMI
applications are always set to foreground).

Binder and priorities

The binder mechanism also propagates priorities. That is the binder process called will run with the same priority as the caller.

JVM thread and process scheduling

An Android system will have a set of unix processes running . Some are native processes but many will be processes that run a Java virtual machine. These processes usually will be multi threaded, All android threads are native pthreads (no green threads). There are two ways to change the priority handling one by
Calling Thread.setPriority that is part of the standard Java API and contains a value from MIN_PRIORITY(1) to MAX_PRIORITY(10).As all threads are pthreads these priorities will be mapped to unix process priorities (MIN_PRIORITY being 19 and MAX_PRIORITY -8).

-Combined dalvik/vm/Thread.c and -frameworks/base/include/utils/threads.h
Thread.priority ,   Java name    , Android property name              , Unix priority
1                  MIN_PRIORITY   ANDROID_PRIORITY_LOWEST,               19
2                                 ANDROID_PRIORITY_BACKGROUND + 6        16
3                                 ANDROID_PRIORITY_BACKGROUND + 3        13
4                                 ANDROID_PRIORITY_BACKGROUND            10
5                  NORM_PRIORITY  ANDROID_PRIORITY_NORMAL                 0
6                                 ANDROID_PRIORITY_NORMAL - 2            -2
7                                 ANDROID_PRIORITY_NORMAL - 4            -4
8                                 ANDROID_PRIORITY_URGENT_DISPLAY + 3    -5
9                                 ANDROID_PRIORITY_URGENT_DISPLAY + 2    -6
10                 MAX_PRIORITY   ANDROID_PRIORITY_URGENT_DISPLAY        -8

The second way to set priorities is to call android.os.Process.setThreadPriority(). This allows to set the pririty to higer priorities for that
Declare: in your AndroidManifest and call Process.setThreadPriority(Process.myTid(), Process.THREAD_PRIORITY_URGENT_DISPLAY )

frameworks/base/include/utils/threads.h
    ANDROID_PRIORITY_LOWEST         =  19,

    /* use for background tasks */
    ANDROID_PRIORITY_BACKGROUND     =  10,

    /* most threads run at normal priority */
    ANDROID_PRIORITY_NORMAL         =   0,

    /* threads currently running a UI that the user is interacting with */
    ANDROID_PRIORITY_FOREGROUND     =  -2,

    /* the main UI thread has a slightly more favorable priority */
    ANDROID_PRIORITY_DISPLAY        =  -4,
    /* ui service treads might want to run at a urgent display (uncommon) */
    ANDROID_PRIORITY_URGENT_DISPLAY =  -8,

    /* all normal audio threads */
    ANDROID_PRIORITY_AUDIO          = -16,

    /* service audio threads (uncommon) */
    ANDROID_PRIORITY_URGENT_AUDIO   = -19,

    /* should never be used in practice. regular process might not
     * be allowed to use this level */
    ANDROID_PRIORITY_HIGHEST        = -20,

    ANDROID_PRIORITY_DEFAULT        = ANDROID_PRIORITY_NORMAL,
    ANDROID_PRIORITY_MORE_FAVORABLE = -1,
    ANDROID_PRIORITY_LESS_FAVORABLE = +1,

*The GC runs (per process) whith all the threads suspended.