-[VIP_PROCESS]
-# predefined process list
-PREDEFINE=enlightenment
-PREDEFINE=dbus-daemon
-PREDEFINE=amd
-PREDEFINE=launchpad_preloading_preinitializing_daemon
-PREDEFINE=process_pool_launchpad_preloading_preinitializing_daemon
-
-[OOM_FIXED_APPS]
-# predefined OOM-fixed app list
-# Format : YOUR_APP=SCORE
-# OOMADJ_SERVICE_MIN < SCORE < OOMADJ_BACKGRD_LOCKED
-# NOTICE : do not set the score with the predefined value
-# you can see the predefined value at the procfs.h
-
-# Use the ratio of the available memory to the total memory as vmpressure threshold.
-# If used with [Memory#] section, the last threshold will be applied.
-[Memory]
-NumMaxVictims=10
-#ThresholdRatioDedup=30 # %
-#ThresholdRatioSwap=24 # %
-#ThresholdRatioLow=12 # %
-#ThresholdRatioMedium=10 # %
-#ThresholdRatioLeave=15 # %
-#NumMaxVictims=1
-
-[POPUP]
-oom_popup=no
-
-[BackgroundReclaim]
-# Unset this option if it causes any unexepcted issue (e.g. jerky animation).
-AfterScreenDim=yes
-
-[MemLimit]
-# Control memory limit
-# values for MemLimitTrigger :
-# oom (regiter event using oom_control and kill process in kernel)
-# threshold(regiter event using usage_in_bytes and kill process in resourced)
-# others(don't register any event for memory limit)
-MemLimitTrigger=oom
-
-# Memory limits for each supported application types. Effective only when MemLimitTrigger
-# is set to oom or threshold.
-MemLimitService=128 # MB
-# MemLimitWidget=160 # MB
-# MemLimitGUIApp=1024 # MB
-
-# Following configuration option sets memory limit for background GUI
-# and Widget applications. It's valid to set this option only if
-# both MemLimitWidget and MemLimitGUIApp are set.
-# MemLimitBgApp=768 # MB
-
-[Logging]
-Enable=1
-# memps logpath
-# memps: OOM log
-# memps_memlimit: lowmem limit log
-MaxNumLogfile=50 # default: 50
-LogPath=/var/log # default: /var/log
-# logfile prefix
-PrefixMemps=memps
-PrefixMempsMemLimit=memps_memlimit
-
-[CPU]
-# predefined process list
-LAZY_PREDEFINE=net-config
-PREDEFINE=indicator-win
-PREDEFINE=windicator
-BOOTING_PREDEFINE=quickpanel
-WRT_PREDEFINE=wrt_launchpad_daemon
-BOOTING_PREDEFINE=volume
-BOOTING_PREDEFINE=nvitemd
-# relative cpu share
-# ROOT_CPU_SHARE=100 : fixed
-BACKGROUND_CPU_SHARE=50
-QUOTA_CPU_SHARE=25
-# max relative cpu time (max=100)
-QUOTA_MAX_BANDWIDTH=100
-
-[CPU-SCHED]
-#foreground=1,2,4-6
+[MemoryGroupLimit]
+VipGroupLimit= 100%
+HighGroupLimit= 100%
+MediumGroupLimit= 90%
+LowestGroupLimit= 70%
+
+[MemoryLevelThreshold]
+MediumLevel= 400MB
+LowLevel= 300MB
+CriticalLevel= 200MB
+OomLevel= 160MB
+OomPopup= no
+
+[MemoryAppTypeLimit]
+ServicePerAppLimitAction=128MB,kill
+WidgetPerAppLimitAction=160MB,kill
+GUIPerAppLimitAction=1024MB,kill
+
+[MemoryAppStatusLimit]
+BackgroundPerAppLimitAction=768MB,kill
-[VIP_PROCESS]
-# predefined process list
-PREDEFINE=enlightenment
-PREDEFINE=dbus-daemon
-PREDEFINE=amd
-PREDEFINE=launchpad_preloading_preinitializing_daemon
-PREDEFINE=process_pool_launchpad_preloading_preinitializing_daemon
+[MemoryGroupLimit]
+VipGroupLimit= 100%
+HighGroupLimit= 100%
+MediumGroupLimit= 90%
+LowestGroupLimit= 70%
-[OOM_FIXED_APPS]
-# predefined OOM-fixed app list
-# Format : YOUR_APP=SCORE
-# OOMADJ_SERVICE_MIN < SCORE < OOMADJ_BACKGRD_LOCKED
-# NOTICE : do not set the score with the predefined value
-# you can see the predefined value at the procfs.h
+[MemoryLevelThreshold]
+MediumLevel= 400MB
+LowLevel= 300MB
+CriticalLevel= 200MB
+OomLevel= 160MB
+OomPopup= no
-[Memory]
-NumMaxVictims=10
+[MemoryAppTypeLimit]
+ServicePerAppLimitAction=128MB,kill
+WidgetPerAppLimitAction=160MB,kill
+GUIPerAppLimitAction=1024MB,kill
-[POPUP]
-oom_popup=no
-
-[BackgroundReclaim]
-# Unset this option if it causes any unexepcted issue (e.g. jerky animation).
-AfterScreenDim=yes
-
-[MemLimit]
-# Control memory limit
-# values for MemLimitTrigger :
-# oom (regiter event using oom_control and kill process in kernel)
-# threshold(regiter event using usage_in_bytes and kill process in resourced)
-# others(don't register any event for memory limit)
-MemLimitTrigger=none
-# How long does the resourced allow that each service applications use memory
-# But, it only allows to enable when the MemLimitTrigger option is oom or threshold.
-MemLimitService=128 # MB
-
-[CPU]
-# predefined process list
-LAZY_PREDEFINE=net-config
-PREDEFINE=indicator-win
-PREDEFINE=windicator
-BOOTING_PREDEFINE=quickpanel
-WRT_PREDEFINE=wrt_launchpad_daemon
-BOOTING_PREDEFINE=volume
-BOOTING_PREDEFINE=nvitemd
-# relative cpu share
-# ROOT_CPU_SHARE=100 : fixed
-BACKGROUND_CPU_SHARE=50
-QUOTA_CPU_SHARE=25
-# max relative cpu time (max=100)
-QUOTA_MAX_BANDWIDTH=100
-
-[CPU-SCHED]
-#foreground=1,2,4-6
+[MemoryAppStatusLimit]
+BackgroundPerAppLimitAction=768MB,kill
LowestGroupLimit= 70%
[MemoryLevelThreshold]
-MediumLevel= 400MB
-LowLevel= 300MB
-CriticalLevel= 200MB
-OomLevel= 160MB
+MediumLevel= 20%
+LowLevel= 15%
+CriticalLevel= 10%
+OomLevel= 7%
OomPopup= no
[MemoryAppTypeLimit]
[MemoryDedup]
DedupEnable=1
-DedupAtBoot=yes
+DedupAtBoot=no
ScanOnLowmem=true
[MemoryKsm]
#KsmMode=periodic
PagesToScan=100
-PagesToScanWithBoost=1000
+PagesToScanWithBoost=1500
[MemoryCompaction]
CompactionEnable=1
FragLevel=800
[CpuSched]
-CpuSchedFeature=rt_runtime_share,rt_runtime_greed
-CpuRTRunTime=950ms
+CpuSchedFeature=no_rt_runtime_share
+CpuRTRunTime=915ms
CpuRTPeriod=1000ms
[CpuAffinity]
--- /dev/null
+[PerProcess]
+Service=dbus.service
+CpuSched=fifo
+CpuRTPriority=5
+
+[PerProcess]
+Service=alarm-server.service
+CpuSched=rr
+CpuRTPriority=10
+
+[PerProcess]
+Service=ac.service
+CpuSched=other
+CpuNice=0
+
+[PerProcess]
+Service=scim.service
+CpuNice=1
+CpuPriority=0
+
+[PerProcess]
+Service=launchpad-process-pool.service
+CpuSched=batch
+CpuNice=2
+
+[PerProcess]
+Service=starter.service
+CpuSched=deadline
+
+[PerProcess]
+Service=at-spi-dbus-bus.service
+CpuSched=idle
#define CPUCG_LOW_PATH CPUCG_PATH "/" CGROUP_VIP_NAME "/" CGROUP_HIGH_NAME "/" CGROUP_MEDIUM_NAME "/" CGROUP_LOW_NAME
#define CPUCG_CONTROL_BANDWIDTH "cpu.cfs_quota_us"
#define CPUCG_CONTROL_FULL_BANDWIDTH "cpu.cfs_period_us"
+#define CPUCG_RT_CONTROL_BANDWIDTH "cpu.rt_runtime_us"
+#define CPUCG_RT_CONTROL_FULL_BANDWIDTH "cpu.rt_period_us"
#define CPUCG_SHARE "cpu.shares"
#define CPUCG_VIP_PP_PATH CPUCG_VIP_PATH"/"CGROUP_PER_PROCESS_NAME
#include "cpu-sched-common.h"
#define MAX_SECTION 64
-#define CPU_INIT_PRIO 100
static int config_parse_swap_types(
const char *rvalue,
static int config_parse_cpu_sched_features(const char *value)
{
- int cpu_sched_type = CPU_SCHED_UNINITIALIZED;
+ int cpu_sched_flag = CPU_SCHED_UNINITIALIZED;
char *word, *state;
size_t l;
if (is_empty(value))
- return cpu_sched_type;
+ return cpu_sched_flag;
FOREACH_WORD_SEPARATOR(word, l, value, ",", state) {
- if (strneq(word, RT_RUNTIME_SHARE, l))
- cpu_sched_type |= CPU_SCHED_RUNTIME_SHARE;
- else if (strneq(word, NO_RT_RUNTIME_SHARE, l))
- cpu_sched_type |= CPU_SCHED_NO_RUNTIME_SHARE;
- else if (strneq(word, RT_RUNTIME_GREED, l))
- cpu_sched_type |= CPU_SCHED_RUNTIME_GREED;
+ if (strneq(word, RT_RUNTIME_SHARE_VALUE_CONF, l))
+ cpu_sched_flag |= CPU_SCHED_RUNTIME_SHARE;
+ else if (strneq(word, NO_RT_RUNTIME_SHARE_VALUE_CONF, l))
+ cpu_sched_flag |= CPU_SCHED_NO_RUNTIME_SHARE;
+ else if (strneq(word, RT_RUNTIME_GREED_VALUE_CONF, l))
+ cpu_sched_flag |= CPU_SCHED_RUNTIME_GREED;
else
return CPU_SCHED_UNINITIALIZED;
}
- return cpu_sched_type;
+ return cpu_sched_flag;
}
static int config_parse_time_us(const char *value)
}
else if (!strncmp(result->section, CPU_SCHED_SECTION,
strlen(CPU_SCHED_SECTION)+1)) {
- if (!strncmp(result->name, CPU_SCHED_FEATURE_CONF,
- strlen(CPU_SCHED_FEATURE_CONF) + 1)) {
+ if (!strncmp(result->name, CPU_SCHED_FEATURE_NAME_CONF,
+ strlen(CPU_SCHED_FEATURE_NAME_CONF) + 1)) {
cpu_sched_conf->cpu_sched_flag = config_parse_cpu_sched_features(result->value);
}
- else if (!strncmp(result->name, CPU_RT_RUN_TIME_CONF,
- strlen(CPU_RT_RUN_TIME_CONF) + 1)) {
+ else if (!strncmp(result->name, CPU_RT_RUN_TIME_NAME_CONF,
+ strlen(CPU_RT_RUN_TIME_NAME_CONF) + 1)) {
cpu_sched_conf->rt_runtime_us = config_parse_time_us(result->value);
}
- else if (!strncmp(result->name, CPU_RT_PERIOD_CONF,
- strlen(CPU_RT_PERIOD_CONF) + 1)) {
+ else if (!strncmp(result->name, CPU_RT_PERIOD_NAME_CONF,
+ strlen(CPU_RT_PERIOD_NAME_CONF) + 1)) {
cpu_sched_conf->rt_period_us = config_parse_time_us(result->value);
}
else {
if (strncmp(result->section, PER_PROCESS_SECTION, strlen(PER_PROCESS_SECTION)+1))
return RESOURCED_ERROR_NONE;
+ /* common(App or Service) */
if (!strncmp(result->name, SERVICE_NAME_CONF, strlen(SERVICE_NAME_CONF)+1) ||
!strncmp(result->name, APP_NAME_CONF, strlen(APP_NAME_CONF)+1)) {
pci = fixed_app_and_service_exist_check(result->value,
}
pci->mem_type = CGROUP_TOP;
pci->cpu_type = CGROUP_TOP;
- pci->cpu_priority = CPU_INIT_PRIO;
+ pci->cpu_sched_info.cpu_sched_type = CPU_SCHED_NONE;
+ pci->cpu_sched_info.cpu_rt_priority = CPU_INIT_PRIO;
+ pci->cpu_sched_info.cpu_nice = CPU_INIT_NICE;
pci->watchdog_action = PROC_ACTION_KILL;
pci->fail_action = PROC_ACTION_IGNORE;
strncpy(pci->name, result->value, sizeof(pci->name)-1);
}
}
}
+ /* limiter.conf.d */
else if (!strncmp(result->name, CPU_CGROUP_NAME_CONF, strlen(CPU_CGROUP_NAME_CONF)+1) &&
*config_type == LIMITER_CONFIG) {
if (!pci) {
_E("process configuration information pointer should not be NULL");
return RESOURCED_ERROR_FAIL;
}
-
+
error = set_mem_action_conf(&pci->mem_action, result->value);
- return error;
+ return error;
}
- else if (!strncmp(result->name, CPU_PRIORITY_NAME_CONF, strlen(CPU_PRIORITY_NAME_CONF)+1) &&
- *config_type == LIMITER_CONFIG) {
+ /* optimizer.conf.d */
+ else if (!strncmp(result->name, CPU_SCHED_NAME_CONF, strlen(CPU_SCHED_NAME_CONF)+1) &&
+ *config_type == OPTIMIZER_CONFIG) {
+ if (!pci) {
+ _E("process configuration information pointer should not be NULL");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ if (!strncmp(result->value, CPU_SCHED_IDLE_VALUE_CONF,
+ strlen(CPU_SCHED_IDLE_VALUE_CONF) +1))
+ pci->cpu_sched_info.cpu_sched_type = CPU_SCHED_IDLE;
+ else if (!strncmp(result->value, CPU_SCHED_OTHER_VALUE_CONF,
+ strlen(CPU_SCHED_OTHER_VALUE_CONF) +1))
+ pci->cpu_sched_info.cpu_sched_type = CPU_SCHED_OTHER;
+ else if (!strncmp(result->value, CPU_SCHED_BATCH_VALUE_CONF,
+ strlen(CPU_SCHED_BATCH_VALUE_CONF) +1))
+ pci->cpu_sched_info.cpu_sched_type = CPU_SCHED_BATCH;
+ else if (!strncmp(result->value, CPU_SCHED_FIFO_VALUE_CONF,
+ strlen(CPU_SCHED_FIFO_VALUE_CONF) +1))
+ pci->cpu_sched_info.cpu_sched_type = CPU_SCHED_FIFO;
+ else if (!strncmp(result->value, CPU_SCHED_RR_VALUE_CONF,
+ strlen(CPU_SCHED_RR_VALUE_CONF) +1))
+ pci->cpu_sched_info.cpu_sched_type = CPU_SCHED_RR;
+ else if (!strncmp(result->value, CPU_SCHED_DEADLINE_VALUE_CONF,
+ strlen(CPU_SCHED_DEADLINE_VALUE_CONF) +1))
+ pci->cpu_sched_info.cpu_sched_type = CPU_SCHED_DEADLINE;
+ else {
+ _E("invalid parameter (%s)", result->value);
+ return RESOURCED_ERROR_INVALID_PARAMETER;
+ }
+ }
+ else if (!strncmp(result->name, CPU_NICE_NAME_CONF,
+ strlen(CPU_NICE_NAME_CONF)+1) && *config_type == OPTIMIZER_CONFIG) {
+ if (!pci) {
+ _E("process configuration information pointer should not be NULL");
+ return RESOURCED_ERROR_FAIL;
+ }
+ pci->cpu_sched_info.cpu_nice = atoi(result->value);
+ }
+ else if (!strncmp(result->name, CPU_RT_PRIORITY_NAME_CONF,
+ strlen(CPU_RT_PRIORITY_NAME_CONF)+1) && *config_type == OPTIMIZER_CONFIG) {
+ if (!pci) {
+ _E("process configuration information pointer should not be NULL");
+ return RESOURCED_ERROR_FAIL;
+ }
+ pci->cpu_sched_info.cpu_rt_priority = atoi(result->value);
+ }
+ else if (!strncmp(result->name, CPU_RT_RUN_TIME_NAME_CONF,
+ strlen(CPU_RT_RUN_TIME_NAME_CONF)+1) &&
+ *config_type == OPTIMIZER_CONFIG) {
+ if (!pci) {
+ _E("process configuration information pointer should not be NULL");
+ return RESOURCED_ERROR_FAIL;
+ }
+ pci->cpu_sched_info.rt_runtime_us = config_parse_time_us(result->value);
+ }
+ else if (!strncmp(result->name, CPU_RT_PERIOD_NAME_CONF,
+ strlen(CPU_RT_PERIOD_NAME_CONF)+1) &&
+ *config_type == OPTIMIZER_CONFIG) {
if (!pci) {
_E("process configuration information pointer should not be NULL");
return RESOURCED_ERROR_FAIL;
}
- pci->cpu_priority = atoi(result->value);
+ pci->cpu_sched_info.rt_period_us = config_parse_time_us(result->value);
}
else if (!strncmp(result->name, ACTION_ON_FAILURE_NAME_CONF,
strlen(ACTION_ON_FAILURE_NAME_CONF)+1) && *config_type == PROCESS_CONFIG) {
#define CPU_CGROUP_NAME_CONF "CpuGroup"
#define MEM_CGROUP_NAME_CONF "MemGroup"
#define MEM_LIMIT_ACTION_NAME_CONF "MemLimitAction"
-#define CPU_PRIORITY_NAME_CONF "CpuPriority"
#define ACTION_ON_FAILURE_NAME_CONF "ActionOnFailure"
#define WATCHDOG_ACTION_NAME_CONF "WatchdogAction"
#define VIP_GROUP_LIMIT_CONF "VipGroupLimit"
#define PAGES_TO_SCAN_CONF "PagesToScan"
#define PAGES_TO_SCAN_WITH_BOOST_CONF "PagesToScanWithBoost"
#define COMPACTION_ENABLE_CONF "CompactionEnable"
-#define CPU_SCHED_FEATURE_CONF "CpuSchedFeature"
-#define CPU_RT_RUN_TIME_CONF "CpuRTRunTime"
-#define CPU_RT_PERIOD_CONF "CpuRTPeriod"
+#define CPU_SCHED_FEATURE_NAME_CONF "CpuSchedFeature"
+#define CPU_RT_RUN_TIME_NAME_CONF "CpuRTRunTime"
+#define CPU_RT_PERIOD_NAME_CONF "CpuRTPeriod"
#define FRAG_LEVEL_CONF "FragLevel"
#define FOREGROUND_APPS "ForegroundApps"
+/* optimizer.conf.d */
+#define CPU_SCHED_NAME_CONF "CpuSched"
+#define CPU_RT_PRIORITY_NAME_CONF "CpuRTPriority"
+#define CPU_NICE_NAME_CONF "CpuNice"
/* configuration value */
#define CGROUP_VIP_VALUE_CONF "vip"
#define ACTION_KILL_VALUE_CONF "kill"
#define ACTION_REBOOT_VALUE_CONF "reboot"
#define ACTION_IGNORE_VALUE_CONF "ignore"
-#define RT_RUNTIME_SHARE "rt_runtime_share"
-#define NO_RT_RUNTIME_SHARE "no_rt_runtime_share"
-#define RT_RUNTIME_GREED "rt_runtime_greed"
+#define RT_RUNTIME_SHARE_VALUE_CONF "rt_runtime_share"
+#define NO_RT_RUNTIME_SHARE_VALUE_CONF "no_rt_runtime_share"
+#define RT_RUNTIME_GREED_VALUE_CONF "rt_runtime_greed"
+
+#define CPU_SCHED_DEADLINE_VALUE_CONF "deadline"
+#define CPU_SCHED_FIFO_VALUE_CONF "fifo"
+#define CPU_SCHED_RR_VALUE_CONF "rr"
+#define CPU_SCHED_OTHER_VALUE_CONF "other"
+#define CPU_SCHED_IDLE_VALUE_CONF "idle"
+#define CPU_SCHED_BATCH_VALUE_CONF "batch"
#define MATCH(a, b) (!strncmp(a, b, strlen(a) + 1) ? 1 : 0)
#define SET_CONF(a, b) (a = (b > 0.0 ? b : a))
#ifndef __CPU_SCHED_COMMON_H__
#define __CPU_SCHED_COMMON_H__
-
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
+#define CPU_INIT_NICE 100
+#define CPU_MAX_NICE 19
+#define CPU_MIN_NICE -20
+
+#define CPU_INIT_PRIO 0
+#define CPU_MAX_PRIO 99
+#define CPU_MIN_PRIO 1
+
enum cpu_sched_flag {
CPU_SCHED_UNINITIALIZED = 0,
CPU_SCHED_RUNTIME_SHARE = 1,
CPU_SCHED_RUNTIME_GREED = 4,
};
+enum cpu_sched_type {
+ CPU_SCHED_NONE = 0,
+ CPU_SCHED_IDLE = 1,
+ CPU_SCHED_BATCH,
+ CPU_SCHED_OTHER,
+ CPU_SCHED_FIFO,
+ CPU_SCHED_RR,
+ CPU_SCHED_DEADLINE,
+};
+
+struct cpu_sched_info {
+ enum cpu_sched_type cpu_sched_type;
+ int cpu_nice; /* fixed cpu nice */
+ int cpu_rt_priority; /* fixed cpu priority for rt schedulers */
+ int rt_period_us; /* fixed cpu period */
+ int rt_runtime_us; /* fixed cpu runtime during period */
+};
+
struct cpu_sched_conf {
int rt_period_us;
int rt_runtime_us;
RESOURCED_NOTIFIER_LIMIT_SYSTEM_SERVICE,
/*
+ * real time scheduler
+ */
+ RESOURCED_NOTIFIER_RT_SCHEDULER,
+
+ /*
* receive external event
*/
RESOURCED_NOTIFIER_BOOTING_DONE,
#include "resourced.h"
#include "const.h"
#include "memory-cgroup.h"
+#include "cpu-sched-common.h"
#ifdef __cplusplus
extern "C" {
SERVICE_TYPE,
};
-
struct proc_conf_info {
char name[MAX_NAME_LENGTH];
enum cgroup_type mem_type; /* fixed memory cgroup */
enum cgroup_type cpu_type; /* fixed cpu cgroup */
- int cpu_priority; /* fixed cpu priority */
enum proc_action watchdog_action; /* watchdog action */
enum proc_action fail_action; /* release action */
struct mem_action mem_action;
+ struct cpu_sched_info cpu_sched_info;
pid_t pid;
};
bool app_watchdog_exclude;
bool app_memcg_update_exclude;
bool app_cpucg_update_exclude;
- bool app_cpu_prio_update_exclude;
+ bool app_cpu_nice_update_exclude;
int runtime_exclude;
int flags;
int lru_state;
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include <fcntl.h>
-#include <unistd.h>
#include <stdio.h>
#include <assert.h>
-#include <sys/types.h>
-#include <sys/wait.h>
#include <stdlib.h>
+#include <sched.h>
#include "util.h"
#include "trace.h"
#include "resourced.h"
+#include "cpu-sched-common.h"
#define GIGA_SHIFT 30
#define MEGA_SHIFT 20
#define KILO_SHIFT 10
+#if !defined(SYS_sched_setattr) && defined(__NR_sched_setattr)
+# define SYS_sched_setattr _NR_sched_setattr
+#endif
+
+#if !defined(SYS_sched_getattr) && defined(__NR_sched_getattr)
+# define SYS_sched_getattr _NR_sched_getattr
+#endif
+
+int sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags)
+{
+ int error;
+
+ _I("[DEBUG] policy = %s", attr->sched_policy == SCHED_IDLE ? "SCHED_IDLE" :
+ attr->sched_policy == SCHED_BATCH ? "SCHED_BATCH" :
+ attr->sched_policy == SCHED_OTHER ? "SCHED_OTHER" :
+ attr->sched_policy == SCHED_FIFO ? "SCHED_FIFO" :
+ attr->sched_policy == SCHED_RR ? "SCHED_RR" :
+ attr->sched_policy == SCHED_DEADLINE ? "SCHED_DEADLINE" : "UNKNOWN");
+
+ switch (attr->sched_policy) {
+ case SCHED_IDLE:
+ if (attr->sched_priority != 0) {
+ _E("[DEBUG] priority of SCHED_IDLE should be 0");
+ return RESOURCED_ERROR_FAIL;
+ }
+ break;
+ case SCHED_BATCH:
+ case SCHED_OTHER:
+ if (attr->sched_priority != 0) {
+ _E("[DEBUG] priority of %s should be 0", attr->sched_policy == SCHED_BATCH ? "SCHED_BATCH" : "SCHED_OTHER");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ if (attr->sched_nice == CPU_INIT_NICE) {
+ _W("[DEBUG] nice value should be located between %d and %d",
+ CPU_MIN_NICE, CPU_MAX_NICE);
+ return RESOURCED_ERROR_FAIL;
+ }
+
+#ifndef SYS_sched_setattr
+ setpriority(PRIO_PROCESS, pid, attr->sched_nice);
+#endif
+ break;
+ case SCHED_FIFO:
+ case SCHED_RR:
+ if (attr->sched_priority == CPU_INIT_PRIO) {
+ _E("[DEBUG] priority of %s should be located between %d and %d",
+ attr->sched_policy == SCHED_FIFO ? "SCHED_FIFO" : "SCHED_RR",
+ CPU_MIN_PRIO, CPU_MAX_PRIO);
+ return RESOURCED_ERROR_FAIL;
+ }
+ break;
+ case SCHED_DEADLINE:
+ _W("[DEBUG] we do not support deadline scheulder yet");
+ return RESOURCED_ERROR_NONE;
+ default:
+ _E("[DEBUG] Unknown sched type (%d)", attr->sched_policy);
+ return RESOURCED_ERROR_FAIL;
+ }
+
+#ifdef SYS_sched_setattr
+ error = syscall(SYS_sched_setattr, pid, attr, flags);
+#else
+ {
+ struct sched_param sp = { .sched_priority = attr->sched_priority};
+ error = sched_setscheduler(pid, attr->sched_policy, &sp);
+ }
+#endif
+ if (error) {
+ _E("[DEBUG] Failed to set policy and priority");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ return RESOURCED_ERROR_NONE;
+}
+
+int sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int flags)
+{
+#ifdef SYS_sched_getattr
+ return syscall(SYS_sched_getattr, pid, attr, sizeof(struct sched_attr), flags);
+#else
+ int error;
+ struct sched_param sp;
+
+ attr->sched_policy = sched_getscheduler(pid);
+ attr->sched_nice = getpriority(PRIO_PROCESS, pid);
+
+ error = sched_getparam(pid, &sp);
+ if (!error)
+ attr->sched_priority = sp.sched_priority;
+
+ if (attr->sched_policy >= 0 && !error)
+ return RESOURCED_ERROR_NONE;
+ else
+ return RESOURCED_ERROR_FAIL;
+#endif
+}
+
static int parent(pid_t pid)
{
int status;
#include <unistd.h>
#include <string.h>
#include <dirent.h>
+#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#define _pure_ __attribute__ ((pure))
#define _cleanup_(x) __attribute__((cleanup(x)))
+struct sched_attr {
+ uint32_t size; /* Size of this structure */
+ uint32_t sched_policy; /* Policy (SCHED_*) */
+ uint64_t sched_flags; /* Flags */
+ int32_t sched_nice; /* Nice value (SCHED_OTHER, SCHED_BATCH) */
+ uint32_t sched_priority; /* Static priority (SCHED_FIFO, SCHED_RR) */
+ /* Remaining fields are for SCHED_DEADLINE */
+ uint64_t sched_runtime;
+ uint64_t sched_deadline;
+ uint64_t sched_period;
+};
+
static inline void freep(void *p)
{
free(*(void**) p);
int resourced_restarted(void);
+int sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags);
+int sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int flags);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
#include "procfs.h"
#include "resourced.h"
#include "trace.h"
-
-#define CPU_INIT_PRIO 100
+#include "cpu-sched-common.h"
static GHashTable *fixed_app_list;
static GHashTable *fixed_service_list;
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <sched.h>
#include <glib-object.h>
#include <gio/gio.h>
#include "config-parser.h"
#include "fd-handler.h"
#include "cpu-cgroup.h"
+#include "cpu-sched-common.h"
#ifndef gettid
#include <sys/syscall.h>
#endif
#endif
-#define CPU_INIT_PRIO 100
-
static const struct module_ops *freezer;
static GSList *proc_module; /* proc sub-module list */
pai->memory.memlimit_update_exclude = false;
if (fixed_app_list_get()) {
+ int error;
struct proc_conf_info *pci;
+ struct sched_attr attr;
pci = fixed_app_and_service_exist_check(appid, APP_TYPE);
pai->app_cpucg_update_exclude = true;
}
- if (pci->cpu_priority != CPU_INIT_PRIO) {
- setpriority(PRIO_PROCESS, pid, pci->cpu_priority);
- pai->app_cpu_prio_update_exclude = true;
+ memset(&attr, 0, sizeof(struct sched_attr));
+ attr.size = sizeof(struct sched_attr);
+ if (pci->cpu_sched_info.cpu_nice >= CPU_MIN_NICE &&
+ pci->cpu_sched_info.cpu_nice <= CPU_MAX_NICE) {
+ attr.sched_nice = pci->cpu_sched_info.cpu_nice;
+ pai->app_cpu_nice_update_exclude = true;
+ }
+ else {
+ attr.sched_nice = CPU_INIT_NICE;
+ }
+
+ if (pci->cpu_sched_info.cpu_rt_priority >= CPU_MIN_PRIO &&
+ pci->cpu_sched_info.cpu_rt_priority <= CPU_MAX_PRIO) {
+ attr.sched_priority = pci->cpu_sched_info.cpu_rt_priority;
+ }
+ else {
+ attr.sched_priority = CPU_INIT_PRIO;
+ }
+
+ switch (pci->cpu_sched_info.cpu_sched_type) {
+ case CPU_SCHED_NONE:
+ case CPU_SCHED_OTHER:
+ attr.sched_policy = SCHED_OTHER;
+ sched_setattr(pid, &attr, 0);
+ error = sched_getattr(pid, &attr, 0);
+ if (error)
+ _E("[DEBUG] Failed to get sched attributes");
+
+ if (attr.sched_policy != SCHED_OTHER)
+ _E("[DEBUG] current policy (%d) is different from %d",
+ attr.sched_policy, SCHED_OTHER);
+ break;
+ case CPU_SCHED_IDLE:
+ attr.sched_policy = SCHED_IDLE;
+ sched_setattr(pid, &attr, 0);
+ error = sched_getattr(pid, &attr, 0);
+ if (error)
+ _E("[DEBUG] Failed to get sched attributes");
+
+ if (attr.sched_policy != SCHED_IDLE)
+ _E("[DEBUG] current policy (%d) is different from %d",
+ attr.sched_policy, SCHED_IDLE);
+ break;
+ case CPU_SCHED_BATCH:
+ attr.sched_policy = SCHED_BATCH;
+ sched_setattr(pid, &attr, 0);
+ error = sched_getattr(pid, &attr, 0);
+ if (error)
+ _E("[DEBUG] Failed to get sched attributes");
+
+ if (attr.sched_policy != SCHED_BATCH)
+ _E("[DEBUG] current policy (%d) is different from %d",
+ attr.sched_policy, SCHED_BATCH);
+ break;
+ case CPU_SCHED_FIFO:
+ attr.sched_policy = SCHED_FIFO;
+ sched_setattr(pid, &attr, 0);
+ error = sched_getattr(pid, &attr, 0);
+ if (error)
+ _E("[DEBUG] Failed to get sched attributes");
+
+ if (attr.sched_policy != SCHED_FIFO)
+ _E("[DEBUG] current policy (%d) is different from %d",
+ attr.sched_policy, SCHED_FIFO);
+ break;
+ case CPU_SCHED_RR:
+ attr.sched_policy = SCHED_RR;
+ sched_setattr(pid, &attr, 0);
+ error = sched_getattr(pid, &attr, 0);
+ if (error)
+ _E("[DEBUG] Failed to get sched attributes");
+
+ if (attr.sched_policy != SCHED_RR)
+ _E("[DEBUG] current policy (%d) is different from %d",
+ attr.sched_policy, SCHED_RR);
+ break;
+ case CPU_SCHED_DEADLINE:
+ attr.sched_policy = SCHED_DEADLINE;
+ sched_setattr(pid, &attr, 0);
+ error = sched_getattr(pid, &attr, 0);
+ if (error)
+ _E("[DEBUG] Failed to get sched attributes");
+ break;
+ default:
+ _E("[DEBUG] Unknown CPU sched type");
}
+ _I("[DEBUG] policy = %s", attr.sched_policy == SCHED_IDLE ? "SCHED_IDLE" :
+ attr.sched_policy == SCHED_BATCH ? "SCHED_BATCH" :
+ attr.sched_policy == SCHED_OTHER ? "SCHED_OTHER" :
+ attr.sched_policy == SCHED_FIFO ? "SCHED_FIFO" :
+ attr.sched_policy == SCHED_RR ? "SCHED_RR" :
+ attr.sched_policy == SCHED_DEADLINE ? "SCHED_DEADLINE" : "UNKNOWN");
+ _I("[DEBUG] nice = %d", attr.sched_nice);
+ _I("[DEBUG] priority = %d", attr.sched_priority);
+
if (pci->watchdog_action == PROC_ACTION_IGNORE)
pai->app_watchdog_exclude = true;
+ /* register RT throttling */
+ if (pci->cpu_sched_info.cpu_sched_type == CPU_SCHED_FIFO ||
+ pci->cpu_sched_info.cpu_sched_type == CPU_SCHED_RR ||
+ pci->cpu_sched_info.cpu_sched_type == CPU_SCHED_DEADLINE) {
+ if (pci->cpu_sched_info.rt_period_us > 0 &&
+ pci->cpu_sched_info.rt_runtime_us > 0 &&
+ pci->cpu_sched_info.rt_period_us > pci->cpu_sched_info.rt_runtime_us) {
+ struct proc_status ps = {0, };
+
+ ps.pid = pid;
+ ps.pci = pci;
+ resourced_notify(RESOURCED_NOTIFIER_RT_SCHEDULER, &ps);
+ }
+ }
+
if (pci->mem_action.memory && pci->mem_action.action) {
struct proc_limit_status pls = {0, };
}
pai = find_app_info(pid);
- if (pai && pai->app_cpu_prio_update_exclude)
+ if (pai && pai->app_cpu_nice_update_exclude)
return;
_D("pid (%d) requested to change priority (%s)", pid, str);
static void cpu_priority_update(int which, pid_t pid, int priority, struct proc_app_info *pai)
{
- if (pai && pai->app_cpu_prio_update_exclude)
+ if (pai && pai->app_cpu_nice_update_exclude)
return;
setpriority(which, pid, priority);
return RESOURCED_ERROR_NONE;
}
-static int calculate_threshold_size(double ratio)
+static inline int calculate_threshold_size(double ratio)
{
int size = (double)totalram * ratio / 100.0;
- return size;
+ return BYTE_TO_MBYTE(size);
}
static void load_configs(const char *path)
/* set MemoryLevelThreshold section */
for (int lvl = MEM_LEVEL_MEDIUM; lvl < MEM_LEVEL_MAX; lvl++) {
if (memcg_conf->threshold[lvl].percent &&
- memcg_conf->threshold[lvl].threshold > 0)
+ memcg_conf->threshold[lvl].threshold > 0) {
memcg_set_threshold(CGROUP_ROOT, lvl,
calculate_threshold_size(memcg_conf->threshold[lvl].threshold));
- else if (memcg_conf->threshold[lvl].threshold > 0)
+
+ if (lvl == MEM_LEVEL_OOM)
+ memcg_set_leave_threshold(CGROUP_ROOT,
+ get_memcg_info(CGROUP_ROOT)->threshold[lvl] * 1.5);
+ }
+ else if (memcg_conf->threshold[lvl].threshold > 0) {
memcg_set_threshold(CGROUP_ROOT, lvl,
memcg_conf->threshold[lvl].threshold);
+
+ if (lvl == MEM_LEVEL_OOM)
+ memcg_set_leave_threshold(CGROUP_ROOT,
+ get_memcg_info(CGROUP_ROOT)->threshold[lvl] * 1.5);
+ }
}
oom_popup_enable = memcg_conf->oom_popup;
return cpu_sched_add_pid_to_cpuset(c, ps->pid);
}
+static int cpu_sched_rt_scheduler(void *data)
+{
+ _cleanup_free_ char *path = NULL;
+ int result;
+ int32_t temp;
+ struct proc_status *ps = (struct proc_status *)data;
+
+ assert(ps);
+ assert(ps->pci);
+ assert(ps->pci->name);
+
+ result = cgroup_read_node_int32(MEMCG_HIGH_PP_PATH, CPUCG_RT_CONTROL_BANDWIDTH, &temp);
+ if (result < 0) {
+ _W("[DEBUG] rt_runtime_us is not supported");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ result = asprintf(&path, "%s/%s", MEMCG_HIGH_PP_PATH, ps->pci->name);
+ if (result < 0) {
+ _E("[DEBUG] not enough memory");
+ return RESOURCED_ERROR_OUT_OF_MEMORY;
+ }
+
+ result = cgroup_make_subdir(MEMCG_HIGH_PP_PATH, ps->pci->name, NULL);
+ if (result < 0) {
+ _E("[DEBUG] Failed to create cgroup subdir '%s/%s'",
+ MEMCG_HIGH_PP_PATH, ps->pci->name);
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ cgroup_write_node_int32(path, CPUCG_RT_CONTROL_FULL_BANDWIDTH, ps->pci->cpu_sched_info.rt_period_us);
+ cgroup_write_node_int32(path, CPUCG_RT_CONTROL_BANDWIDTH, ps->pci->cpu_sched_info.rt_runtime_us);
+
+ cgroup_write_pid_fullpath(path, ps->pid);
+
+ return RESOURCED_ERROR_NONE;
+}
+
static void register_notifiers()
{
if (cs.fg) {
register_notifier(RESOURCED_NOTIFIER_WIDGET_BACKGRD, cpu_sched_app_background);
}
+ register_notifier(RESOURCED_NOTIFIER_RT_SCHEDULER, cpu_sched_rt_scheduler);
+
register_notifier(RESOURCED_NOTIFIER_CPU_ON, cpu_sched_cpu_on);
register_notifier(RESOURCED_NOTIFIER_CPU_OFF, cpu_sched_cpu_off);
unregister_notifier(RESOURCED_NOTIFIER_WIDGET_BACKGRD, cpu_sched_app_background);
}
+ unregister_notifier(RESOURCED_NOTIFIER_RT_SCHEDULER, cpu_sched_rt_scheduler);
+
unregister_notifier(RESOURCED_NOTIFIER_CPU_ON, cpu_sched_cpu_on);
unregister_notifier(RESOURCED_NOTIFIER_CPU_OFF, cpu_sched_cpu_off);
*
**/
+#include "util.h"
#include "const.h"
#include "dbus-handler.h"
#include "cgroup.h"
#include "fd-handler.h"
#include "lowmem-handler.h"
#include "notifier.h"
+#include "cpu-sched-common.h"
#include <dirent.h>
#include <dlfcn.h>
g_source_attach(shared_data->darg->mainloop_quit, NULL);
}
-#define CPU_INIT_PRIO 100
-
int fixed_service_list_init(void *data)
{
+ int error;
gpointer key;
gpointer value;
GHashTableIter iter;
+ struct sched_attr attr;
g_hash_table_iter_init(&iter, fixed_service_list_get());
GVariant *variant;
pid_t pid = -1;
-
if (!pci) {
_E("[DEBUG] process configuration information is NULL");
continue;
cpu_move_cgroup_foreach(pid, NULL, CPU_CGROUP_PATH(pci->cpu_type));
}
- /* fixed cpu priority */
- if (pci->cpu_priority != CPU_INIT_PRIO) {
- setpriority(PRIO_PROCESS, pid, pci->cpu_priority);
+ memset(&attr, 0, sizeof(struct sched_attr));
+ attr.size = sizeof(struct sched_attr);
+ if (pci->cpu_sched_info.cpu_nice >= CPU_MIN_NICE &&
+ pci->cpu_sched_info.cpu_nice <= CPU_MAX_NICE) {
+ attr.sched_nice = pci->cpu_sched_info.cpu_nice;
+ }
+ else {
+ attr.sched_nice = CPU_INIT_NICE;
+ }
+
+ if (pci->cpu_sched_info.cpu_rt_priority >= CPU_MIN_PRIO &&
+ pci->cpu_sched_info.cpu_rt_priority <= CPU_MAX_PRIO) {
+ attr.sched_priority = pci->cpu_sched_info.cpu_rt_priority;
+ }
+ else {
+ attr.sched_priority = CPU_INIT_PRIO;
}
+ switch (pci->cpu_sched_info.cpu_sched_type) {
+ case CPU_SCHED_NONE:
+ case CPU_SCHED_OTHER:
+ attr.sched_policy = SCHED_OTHER;
+ sched_setattr(pid, &attr, 0);
+ error = sched_getattr(pid, &attr, 0);
+ if (error)
+ _E("[DEBUG] Failed to get sched attributes");
+
+ if (attr.sched_policy != SCHED_OTHER)
+ _E("[DEBUG] current policy (%d) is different from %d",
+ attr.sched_policy, SCHED_OTHER);
+ break;
+ case CPU_SCHED_IDLE:
+ attr.sched_policy = SCHED_IDLE;
+ sched_setattr(pid, &attr, 0);
+ error = sched_getattr(pid, &attr, 0);
+ if (error)
+ _E("[DEBUG] Failed to get sched attributes");
+
+ if (attr.sched_policy != SCHED_IDLE)
+ _E("[DEBUG] current policy (%d) is different from %d",
+ attr.sched_policy, SCHED_IDLE);
+ break;
+ case CPU_SCHED_BATCH:
+ attr.sched_policy = SCHED_BATCH;
+ sched_setattr(pid, &attr, 0);
+ error = sched_getattr(pid, &attr, 0);
+ if (error)
+ _E("[DEBUG] Failed to get sched attributes");
+
+ if (attr.sched_policy != SCHED_BATCH)
+ _E("[DEBUG] current policy (%d) is different from %d",
+ attr.sched_policy, SCHED_BATCH);
+ break;
+ case CPU_SCHED_FIFO:
+ attr.sched_policy = SCHED_FIFO;
+ sched_setattr(pid, &attr, 0);
+ error = sched_getattr(pid, &attr, 0);
+ if (error)
+ _E("[DEBUG] Failed to get sched attributes");
+
+ if (attr.sched_policy != SCHED_FIFO)
+ _E("[DEBUG] current policy (%d) is different from %d",
+ attr.sched_policy, SCHED_FIFO);
+ break;
+ case CPU_SCHED_RR:
+ attr.sched_policy = SCHED_RR;
+ sched_setattr(pid, &attr, 0);
+ error = sched_getattr(pid, &attr, 0);
+ if (error)
+ _E("[DEBUG] Failed to get sched attributes");
+
+ if (attr.sched_policy != SCHED_RR)
+ _E("[DEBUG] current policy (%d) is different from %d",
+ attr.sched_policy, SCHED_RR);
+ break;
+ case CPU_SCHED_DEADLINE:
+ attr.sched_policy = SCHED_DEADLINE;
+ sched_setattr(pid, &attr, 0);
+ error = sched_getattr(pid, &attr, 0);
+ if (error)
+ _E("[DEBUG] Failed to get sched attributes");
+ break;
+ default:
+ _E("[DEBUG] Unknown CPU sched type");
+ }
+
+ _I("[DEBUG] %s's (pid = %d) policy = %s", pci->name, pid, attr.sched_policy == SCHED_IDLE ? "SCHED_IDLE" :
+ attr.sched_policy == SCHED_BATCH ? "SCHED_BATCH" :
+ attr.sched_policy == SCHED_OTHER ? "SCHED_OTHER" :
+ attr.sched_policy == SCHED_FIFO ? "SCHED_FIFO" :
+ attr.sched_policy == SCHED_RR ? "SCHED_RR" :
+ attr.sched_policy == SCHED_DEADLINE ? "SCHED_DEADLINE" : "UNKNOWN");
+ _I("[DEBUG] %s's nice = %d", pci->name, attr.sched_nice);
+ _I("[DEBUG] %s's priority = %d", pci->name, attr.sched_priority);
+
/* register a notification when this service is released */
switch (pci->fail_action) {
case PROC_ACTION_REBOOT:
proc_watchdog_booting_done(pci->name, pid);
break;
+ case PROC_ACTION_IGNORE:
+ break;
default:
_W("[DEBUG] Currently we support only REBOOT when a service is released");
}
+ /* register RT throttling */
+ if (pci->cpu_sched_info.cpu_sched_type == CPU_SCHED_FIFO ||
+ pci->cpu_sched_info.cpu_sched_type == CPU_SCHED_RR ||
+ pci->cpu_sched_info.cpu_sched_type == CPU_SCHED_DEADLINE) {
+ if (pci->cpu_sched_info.rt_period_us > 0 &&
+ pci->cpu_sched_info.rt_runtime_us > 0 &&
+ pci->cpu_sched_info.rt_period_us > pci->cpu_sched_info.rt_runtime_us) {
+ struct proc_status ps = {0, };
+
+ ps.pid = pid;
+ ps.pci = pci;
+ resourced_notify(RESOURCED_NOTIFIER_RT_SCHEDULER, &ps);
+ }
+ }
+
/* register a notification when this service memory is over a threshold */
if (pci->mem_action.memory && pci->mem_action.action) {
struct proc_limit_status pls = {0, };