CPU Cgroup in android N and Huawei Mate 9 Implement

2022-05-13 18:49:43 浏览数 (3)

The Android framework knows a lot about tasks that are running and can help inform scheduler decisions. AOSP uses CPU Cgroup to implement tasks scheduler in framework in android N.

App schedule policy

There are 7 app task schedule policies defined in android N.

typedef enum { SP_DEFAULT = -1, SP_BACKGROUND= 0, SP_FOREGROUND= 1, //Not used in the framework SP_SYSTEM = 2, // can't be used with set_sched_policy() SP_AUDIO_APP = 3, SP_AUDIO_SYS = 4, SP_TOP_APP = 5, SP_CNT, SP_MAX = SP_CNT - 1, SP_SYSTEM_DEFAULT= SP_FOREGROUND, }SchedPolicy;

Thread SP

There are two classification threads in Andorid OS that are Java thread and native thread. Both threads are created by pthread_create in the end.It will set the JAVA thread SP when create .While it does not set the SP for native thread when create it. Framework provides 3 methods to set the thread SP.

  • Process.setThreadPriority() for java thread
  • Threads.androidSetThreadPriority() for native thread
  • set_cpuset_policy() for native thread Note: Framework only sets the threads SP to SP_BACKGROUND or SP_FOREGROUND by calling Process.setThreadPriority() or Threads.androidSetThreadPriority().

Thread::SetNativePriority(int newPriority) { ... if (newNice >= ANDROID_PRIORITY_BACKGROUND){ set_sched_policy(tid, SP_BACKGROUND); }else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND){ set_sched_policy(tid,SP_FOREGROUND); } ... }

int androidSetThreadPriority(pid_t tid, int pri){

... if (pri >= ANDROID_PRIORITY_BACKGROUND) { rc = set_sched_policy(tid, SP_BACKGROUND); }else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND){ rc = set_sched_policy(tid, SP_FOREGROUND); }

....

}

CPU Cgroup

There are 4 cgroups defined cpu, cpuset, cpuboots and cpuschedtune so far in android N.

CPU_CTL

This cgroup uses two different scheduling classes 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 foreground. At startup Services are running in bg_non_interactive unless they have been elevated to foreground scheduling group using startForeground. All the app tasks which belong to THREAD_GROUP_BG_NONINTERACTIVE BP are put into the bg_non_interactive tasks and other tasks to foreground.

int set_sched_policy(int tid, SchedPolicy policy)

{

if (__sys_supports_schedgroups) {

int fd;

switch (policy) {

case SP_BACKGROUND:

fd = bg_cgroup_fd;

break;

case SP_FOREGROUND:

case SP_AUDIO_APP:

case SP_AUDIO_SYS:

fd = fg_cgroup_fd;

break;

default:

fd = -1;

break;

}

if (add_tid_to_cgroup(tid, fd) != 0) {

if (errno != ESRCH && errno != ENOENT)

return -errno;

}

}

}

  • Foreground

/dev/cpuctl/cpu.shares 1024 /dev/cpuctl/cpu.rt_runtime_us 800000 /dev/cpuctl/cpu.rt_period_us 1000000

  • bg_non_interactive

/dev/cpuctl/bg_non_interactive/cpu.shares 52 /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 700000 /dev/cpuctl/bg_non_interactive/cpu.rt_period_us 1000000

CPUSET

Framework use CPUSET implement app tasks run different CPUS according to tasks SP and runtime state in order to get the better UX and power save. There are two scenarios in framework to use CPUSET. One is start app and the other is app runtime.

App start

Framework will migrate all the tasks from foreground group to foreground_boost cgroup when the app start.After 3000ms ,it will migrate back the tasks from foreground_boost cgroup to foreground cgroup.

Note,this feature shall enable the CPUSET and USE_SCHED_BOOST.

App runtime

Framework classifies all the tasks into 4 schedule group according to thread SP. Correspondingly,there are 4 cgroups in CPUSET,the default design as below,

  • Foreground Tasks run all cores.
  • Background Tasks run little cores.
  • System-background Tasks run all little cores for system processes that shouldn’t run on big cores.
  • TOP-APP Tasks run all cores big cores

int set_cpuset_policy(int tid, SchedPolicy policy)

{

// in the absence of cpusets, use the old sched policy

#ifndef USE_CPUSETS

return set_sched_policy(tid, policy);

#else

if (tid == 0) {

tid = gettid();

}

policy = _policy(policy);

pthread_once(&the_once, __initialize);

int fd;

switch (policy) {

case SP_BACKGROUND:

fd = bg_cpuset_fd;

break;

case SP_FOREGROUND:

case SP_AUDIO_APP:

case SP_AUDIO_SYS:

fd = fg_cpuset_fd;

break;

default:

fd = -1;

break;

}

if(add_tid_to_cgroup(tid, fd) != 0) {

if (errno != ESRCH && errno != ENOENT)

return -errno;

}

return 0;

#endif

}

  • Foreground

//CPUS use to boost /dev/cpuset/foreground/cpus /dev/cpuset/foreground/mems //tasksput into this cgroup /dev/cpuset/foreground/tasks

  • Top-app

/dev/cpuset/top-app/cpus /dev/cpuset/top-app/mems //tasks put into this cgroup /dev/cpuset/top-app/tasks

  • Background

/dev/cpuset/background/cpus /dev/cpuset/background/mems //tasks put into this cgroup /dev/cpuset/background/tasks

  • System-background

/dev/cpuset/system-background/cpus /dev/cpuset/system-background/mems //tasksput into this cgroup /dev/cpuset/system-background/tasks

Cpuschedtune

It is for task "performance boosting". While seems that AOSP has not complete implement it.

/dev/stune/foreground /dev/stune/tasks /dev/stune/foreground/tasks /dev/stune/background /dev/stune/background/tasks /dev/stune/top-app /dev/stune/top-app/tasks /dev/stune/system-background /dev/stune/system-background/tasks

Huawei Mate9 Implement

1 人点赞