From b34153edcb572c2cc275d79098ab51d671a36777 Mon Sep 17 00:00:00 2001 From: Unsung Lee Date: Fri, 10 Dec 2021 19:17:42 +0900 Subject: [PATCH 01/16] Fix convert_status_to_str Change-Id: I7dd3389e9adbe12a2fb5028dca272ccf9282ab1e Signed-off-by: Unsung Lee --- src/resource-limiter/memory/vmpressure-lowmem-handler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/resource-limiter/memory/vmpressure-lowmem-handler.c b/src/resource-limiter/memory/vmpressure-lowmem-handler.c index 8c81819..36400fd 100644 --- a/src/resource-limiter/memory/vmpressure-lowmem-handler.c +++ b/src/resource-limiter/memory/vmpressure-lowmem-handler.c @@ -400,8 +400,8 @@ static const char *convert_type_to_str(int type) static const char *convert_status_to_str(int status) { static const char *status_table[] = - {"none", "done", "drop", "retry", "next_type", "cont"}; - if(status >= LOWMEM_RECLAIM_NONE && status <= LOWMEM_RECLAIM_CONT) + {"none", "done", "drop", "cont", "retry", "next_type"}; + if(status >= LOWMEM_RECLAIM_NONE && status <= LOWMEM_RECLAIM_NEXT_TYPE) return status_table[status]; return "error status"; } -- 2.7.4 From 1dd4224fa1c03b7031de83e8ea959de3cf2cbc8d Mon Sep 17 00:00:00 2001 From: Mateusz Majewski Date: Wed, 29 Dec 2021 14:14:42 +0100 Subject: [PATCH 02/16] Fix some memory leaks Issues reported by jm0508.kwon@samsung.com and ravi.singh1@samsung.com. Thanks! Change-Id: I9658a23bf9f0960f8b29167c0a28b80c995b706f Co-authored-by: Ravi Singh --- src/process/proc-usage-stats-helper.c | 2 ++ src/process/proc-usage-stats.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/process/proc-usage-stats-helper.c b/src/process/proc-usage-stats-helper.c index 2f44338..5e3ac6d 100644 --- a/src/process/proc-usage-stats-helper.c +++ b/src/process/proc-usage-stats-helper.c @@ -240,6 +240,8 @@ void proc_free_runtime_info_task(struct runtime_info_task *rt_task) if (rt_task->pipe_fds[1] >= 0) close(rt_task->pipe_fds[1]); + free(rt_task->pid_list); + // we assume that rt_task->task_invocation is already freed before calling proc_free_runtime_info_task. free(rt_task); diff --git a/src/process/proc-usage-stats.c b/src/process/proc-usage-stats.c index d4cb9e8..49c6799 100644 --- a/src/process/proc-usage-stats.c +++ b/src/process/proc-usage-stats.c @@ -261,6 +261,8 @@ void proc_runtime_info_request_handler(GDBusMethodInvocation *invocation, while (g_variant_iter_loop(iter, "i", &tmp)) rt_task->pid_list[i++] = tmp; + g_variant_iter_free(iter); + if (rt_task->task_type == RUNTIME_INFO_TASK_MEMORY) rt_task->usage_info_list = (void *)malloc(sizeof(struct process_memory_info_s) * rt_task->task_size); else if (rt_task->task_type == RUNTIME_INFO_TASK_CPU) -- 2.7.4 From 5ca65396db3023eeac48bc07c04997fc69340f09 Mon Sep 17 00:00:00 2001 From: Unsung Lee Date: Mon, 27 Dec 2021 18:59:17 +0900 Subject: [PATCH 03/16] Refactor cgroup components Collect all cgroup-related functions into the src/common/cgroup Change-Id: I4ebc924baae5ace0b933360d8f12e96584a63c22 Signed-off-by: Unsung Lee --- CMakeLists.txt | 6 +- src/CMakeLists.txt | 5 +- .../{ => cgroup}/cgroup-memory-stat-lookup.c | 2 +- .../{ => cgroup}/cgroup-memory-stat-lookup.gperf | 2 +- src/common/{ => cgroup}/cgroup.c | 48 ++++- src/common/{ => cgroup}/cgroup.h | 68 ++---- src/common/cgroup/cpu-cgroup.h | 51 +++++ src/common/cgroup/memory-cgroup.h | 240 +++++++++++++++++++++ src/common/const.h | 2 - src/common/dedup-common.h | 2 +- src/common/memory-common.h | 174 --------------- src/common/proc-common.h | 2 +- src/common/procfs.c | 2 +- src/common/swap-common.h | 2 +- src/process/proc-process.c | 2 +- src/process/vip/vip-process.c | 7 +- src/resource-limiter/cpu/cpu-sched.c | 12 +- src/resource-limiter/cpu/cpu.c | 79 +++---- src/resource-limiter/memory/compaction.c | 2 +- src/resource-limiter/memory/lowmem-dbus.c | 2 +- src/resource-limiter/memory/lowmem-handler.h | 2 +- src/resource-limiter/memory/lowmem-limit.c | 67 +++--- src/resource-limiter/memory/lowmem-system.c | 16 +- src/resource-limiter/memory/memcontrol.c | 2 +- .../memory/vmpressure-lowmem-handler.c | 36 ++-- src/resource-optimizer/memory/dedup/.dedup.c.swp | Bin 0 -> 16384 bytes src/resource-optimizer/memory/dedup/dedup.c | 2 +- src/resource-optimizer/memory/swap/fileswap.c | 2 +- src/resource-optimizer/memory/swap/swap.c | 77 +++---- src/resource-optimizer/memory/swap/zramswap.c | 4 +- src/resource-optimizer/memory/swap/zswap.c | 2 +- tests/CMakeLists.txt | 4 + tests/lowmem-dbus-test.cpp | 2 +- tests/lowmem-limit-env.cpp | 14 +- tests/lowmem-limit-env.hpp | 5 +- tests/lowmem-limit-mock.cpp | 3 + tests/lowmem-limit-test.cpp | 13 +- tests/lowmem-system-test.cpp | 12 +- 38 files changed, 565 insertions(+), 408 deletions(-) rename src/common/{ => cgroup}/cgroup-memory-stat-lookup.c (99%) rename src/common/{ => cgroup}/cgroup-memory-stat-lookup.gperf (99%) rename src/common/{ => cgroup}/cgroup.c (87%) rename src/common/{ => cgroup}/cgroup.h (72%) create mode 100644 src/common/cgroup/cpu-cgroup.h create mode 100644 src/common/cgroup/memory-cgroup.h delete mode 100644 src/common/memory-common.h create mode 100644 src/resource-optimizer/memory/dedup/.dedup.c.swp diff --git a/CMakeLists.txt b/CMakeLists.txt index 965f189..1b2cc84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,14 +40,18 @@ SET(VERSION ${FULLVER}) SET(DATA_DIR ${CMAKE_SOURCE_DIR}/data) SET(CMAKELISTS_DIR ${CMAKE_SOURCE_DIR}/CMakeLists) SET(INCLUDE_COMMON_DIR ${CMAKE_SOURCE_DIR}/src/common) +SET(INCLUDE_CGROUP_DIR ${CMAKE_SOURCE_DIR}/src/common/cgroup) SET(INCLUDE_PUBLIC_DIR ${CMAKE_SOURCE_DIR}/include) -SET(RESOURCED_INCLUDEDIR ${INCLUDE_COMMON_DIR} ${INCLUDE_PUBLIC_DIR}) +SET(RESOURCED_INCLUDEDIR ${INCLUDE_COMMON_DIR} ${INCLUDE_CGROUP_DIR} ${INCLUDE_PUBLIC_DIR}) #misc SET(SOURCE_DIR ${CMAKE_SOURCE_DIR}/src) SET(RESOURCED_SOURCE_DIR ${SOURCE_DIR}/resourced) SET(COMMON_SOURCE_DIR ${SOURCE_DIR}/common) +#cgroup +SET(CGROUP_SOURCE_DIR ${COMMON_SOURCE_DIR}/cgroup) + #resource-optimizer source folders SET(RESOURCE_OPTIMIZER_SOURCE_DIR ${SOURCE_DIR}/resource-optimizer) SET(MEMORY_RESOURCE_OPTIMIZER_SOURCE_DIR ${RESOURCE_OPTIMIZER_SOURCE_DIR}/memory) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9aa8f8d..4fe2721 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,6 +44,9 @@ SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES} ${FILES}) FILE(GLOB FILES "${COMMON_SOURCE_DIR}/*.c") SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES} ${FILES}) +FILE(GLOB FILES "${CGROUP_SOURCE_DIR}/*.c") +SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES} ${FILES}) + SET(CMAKE_EXTRA_INCLUDE_FILES unistd.h) INCLUDE_DIRECTORIES(${RESOURCED_INCLUDEDIR} @@ -111,7 +114,7 @@ CONFIGURE_FILE(${INCLUDE_COMMON_DIR}/config.h.in ${INCLUDE_COMMON_DIR}/config.h) # resourced internal private API -FILE(GLOB FILES "${INCLUDE_COMMON_DIR}/*.h" "${INCLUDE_PUBLIC_DIR}/*.h" "${PROCESS_SOURCE_DIR}/*.h" "${RESOURCED_SOURCE_DIR}/*.h") +FILE(GLOB FILES "${INCLUDE_COMMON_DIR}/*.h" "${INCLUDE_CGROUP_DIR}/*.h" "${INCLUDE_PUBLIC_DIR}/*.h" "${PROCESS_SOURCE_DIR}/*.h" "${RESOURCED_SOURCE_DIR}/*.h") FOREACH(FILE ${FILES}) SET(RESOURCED_HEADERS ${RESOURCED_HEADERS} ${FILE}) ENDFOREACH() diff --git a/src/common/cgroup-memory-stat-lookup.c b/src/common/cgroup/cgroup-memory-stat-lookup.c similarity index 99% rename from src/common/cgroup-memory-stat-lookup.c rename to src/common/cgroup/cgroup-memory-stat-lookup.c index 2301ec2..3da8a20 100644 --- a/src/common/cgroup-memory-stat-lookup.c +++ b/src/common/cgroup/cgroup-memory-stat-lookup.c @@ -35,7 +35,7 @@ error "gperf generated tables don't work with this execution character set. Plea #include #include -#include "cgroup.h" +#include "memory-cgroup.h" struct memory_stat_key { const char* name; diff --git a/src/common/cgroup-memory-stat-lookup.gperf b/src/common/cgroup/cgroup-memory-stat-lookup.gperf similarity index 99% rename from src/common/cgroup-memory-stat-lookup.gperf rename to src/common/cgroup/cgroup-memory-stat-lookup.gperf index 6522b4b..40012c4 100644 --- a/src/common/cgroup-memory-stat-lookup.gperf +++ b/src/common/cgroup/cgroup-memory-stat-lookup.gperf @@ -2,7 +2,7 @@ #include #include -#include "cgroup.h" +#include "memory-cgroup.h" struct memory_stat_key { const char* name; diff --git a/src/common/cgroup.c b/src/common/cgroup/cgroup.c similarity index 87% rename from src/common/cgroup.c rename to src/common/cgroup/cgroup.c index 2ea45a3..16476a6 100644 --- a/src/common/cgroup.c +++ b/src/common/cgroup/cgroup.c @@ -22,6 +22,7 @@ */ #include "cgroup.h" +#include "memory-cgroup.h" #include "const.h" #include "macro.h" #include "util.h" @@ -62,6 +63,29 @@ static int cgroup_create(const char *cgroup_full_path) } /* + * @desc place tid to tasks file + * @return 0 in case of success, errno value in case of failure + */ +resourced_ret_c cgroup_write_tid_fullpath(const char *cgroup_full_path, + const int tid) +{ + int ret; + + if (tid <= 0) { + _E("try to write empty tid to %s", cgroup_full_path); + return RESOURCED_ERROR_NO_DATA; + } + + ret = cgroup_write_node_uint32(cgroup_full_path, TASK_FILE_NAME, + (u_int32_t)tid); + + ret_value_msg_if(ret < 0, RESOURCED_ERROR_FAIL, + "Failed to place a tid (%d) to cgroup %s : %m", tid, + cgroup_full_path); + return RESOURCED_ERROR_NONE; +} + +/* * @desc place pid to cgroup.procs file * @return 0 in case of success, errno value in case of failure */ @@ -79,7 +103,7 @@ resourced_ret_c cgroup_write_pid_fullpath(const char *cgroup_full_path, (u_int32_t)pid); ret_value_msg_if(ret < 0, RESOURCED_ERROR_FAIL, - "Failed place all pid to cgroup %s : %m", + "Failed to place a pid (%d) to cgroup %s : %m", pid, cgroup_full_path); return RESOURCED_ERROR_NONE; } @@ -88,7 +112,11 @@ resourced_ret_c cgroup_write_pid(const char *cgroup_subsystem, const char *cgroup_name, const int pid) { char buf[MAX_PATH_LENGTH]; - snprintf(buf, sizeof(buf), "%s/%s", cgroup_subsystem, cgroup_name); + int size = snprintf(buf, sizeof(buf), "%s/%s", cgroup_subsystem, cgroup_name); + if(size < 0) { + _E("failed to setup path (%s/%s)", cgroup_subsystem, cgroup_name); + return size; + } return cgroup_write_pid_fullpath(buf, pid); } @@ -163,8 +191,8 @@ int cgroup_make_subdir(const char* parentdir, const char* cgroup_name, bool *alr /* FIXME: do something about this mounting, then replace * `is_exists` with checking for -EEXIST in `create`, * as currently this is both duplication AND a race condition */ - if (!strncmp(parentdir, DEFAULT_CGROUP, sizeof(DEFAULT_CGROUP))) { - ret = mount("tmpfs", DEFAULT_CGROUP, "tmpfs", + if (!strncmp(parentdir, CGROUP_PATH, sizeof(CGROUP_PATH))) { + ret = mount("tmpfs", CGROUP_PATH, "tmpfs", MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, "mode=755"); if (ret < 0) { _E("Fail to RW mount cgroup directory. Can't make %s cgroup", cgroup_name); @@ -178,7 +206,7 @@ int cgroup_make_subdir(const char* parentdir, const char* cgroup_name, bool *alr "Fail to create cgroup %s : err %d", cgroup_name, errno); if (cgroup_remount) { - ret = mount("tmpfs", DEFAULT_CGROUP, "tmpfs", + ret = mount("tmpfs", CGROUP_PATH, "tmpfs", MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755"); if (ret < 0) _D("Fail to RO mount"); @@ -202,7 +230,7 @@ int cgroup_set_release_agent(const char *cgroup_subsys, const char *release_agen _cleanup_free_ char *buf = NULL; int r; - r = asprintf(&buf, "%s/%s", DEFAULT_CGROUP, cgroup_subsys); + r = asprintf(&buf, "%s/%s", CGROUP_PATH, cgroup_subsys); if (r < 0) return -ENOMEM; @@ -288,11 +316,11 @@ int cgroup_get_memory_stat(const char *name, struct cgroup_memory_stat **mem_sta int l; int name_len = strlen(name); - if (strneq(name, CGROUP_MEMORY, strlen(CGROUP_MEMORY))) + if (strneq(name, MEMCG_PATH, strlen(MEMCG_PATH))) l = snprintf(p, PATH_MAX, "%s", name); else l = snprintf(p, PATH_MAX, "%s%s%s", - CGROUP_MEMORY, + MEMCG_PATH, name[0] != '/' ? "/" : "", name); @@ -302,7 +330,7 @@ int cgroup_get_memory_stat(const char *name, struct cgroup_memory_stat **mem_sta p[l - 1] != '/' ? "/" : "", memory_stat); } else - snprintf(p, PATH_MAX, "%s/%s", CGROUP_MEMORY, memory_stat); + snprintf(p, PATH_MAX, "%s/%s", MEMCG_PATH, memory_stat); f = fopen(p, "re"); if (!f) @@ -369,7 +397,7 @@ int cgroup_get_pids(const char *name, GArray **pids) assert(pids); assert(!*pids); - if (asprintf(&cg_procs, "%s/cgroup.procs", name) < 0) + if (asprintf(&cg_procs, "%s/%s", name, CGROUP_FILE_NAME) < 0) return -ENOMEM; f = fopen(cg_procs, "r"); diff --git a/src/common/cgroup.h b/src/common/cgroup/cgroup.h similarity index 72% rename from src/common/cgroup.h rename to src/common/cgroup/cgroup.h index f98fc8f..7cec0ca 100644 --- a/src/common/cgroup.h +++ b/src/common/cgroup/cgroup.h @@ -36,8 +36,11 @@ extern "C" { #endif /* __cplusplus */ -#define DEFAULT_CGROUP "/sys/fs/cgroup" -#define CGROUP_MEMORY DEFAULT_CGROUP "/memory" +#define TASK_FILE_NAME "tasks" +#define CGROUP_FILE_NAME "cgroup.procs" + +//#define DEFAULT_CGROUP "/sys/fs/cgroup" +#define CGROUP_PATH "/sys/fs/cgroup" /** * @desc Get one unsigned int32 value from cgroup @@ -107,6 +110,15 @@ int cgroup_make_subdir(const char* parentdir, const char* cgroup_name, bool *alr int cgroup_mount_subsystem(char* source, char* mount_point, char* opts); /** + * @desc write tid into cgroup_subsystem/cgroup_name file, + * @param cgroup_full_path - name in /sys/fs/cgroup/subsystem/ + * @param tid - tid to write to cgroup file + * @return negative value if error + */ +resourced_ret_c cgroup_write_tid_fullpath(const char *cgroup_full_path, + const int tid); + +/** * @desc write pid into cgroup_subsystem/cgroup_name file, * @param cgroup_full_path - name in /sys/fs/cgroup/subsystem/ * @param pid - pid to write to cgroup file @@ -147,58 +159,6 @@ int cgroup_pid_get_path(const char *controller, pid_t pid, char **path); */ int cgroup_get_pids(const char *name, GArray **pids); -enum cgroup_memory_stat_id { - CGROUP_MEMORY_STAT_CACHE = 0, - CGROUP_MEMORY_STAT_RSS, - CGROUP_MEMORY_STAT_RSS_HUGE, - CGROUP_MEMORY_STAT_MAPPED_FILE, - CGROUP_MEMORY_STAT_DIRTY, - CGROUP_MEMORY_STAT_WRITEBACK, - CGROUP_MEMORY_STAT_SWAP, - CGROUP_MEMORY_STAT_PGPGIN, - CGROUP_MEMORY_STAT_PGPGOUT, - CGROUP_MEMORY_STAT_PGFAULT, - CGROUP_MEMORY_STAT_PGMAJFAULT, - CGROUP_MEMORY_STAT_INACTIVE_ANON, - CGROUP_MEMORY_STAT_ACTIVE_ANON, - CGROUP_MEMORY_STAT_INACTIVE_FILE, - CGROUP_MEMORY_STAT_ACTIVE_FILE, - CGROUP_MEMORY_STAT_UNEVICTABLE, - CGROUP_MEMORY_STAT_HIERARCHICAL_MEMORY_LIMIT, - CGROUP_MEMORY_STAT_HIERARCHICAL_MEMSW_LIMIT, - CGROUP_MEMORY_STAT_TOTAL_CACHE, - CGROUP_MEMORY_STAT_TOTAL_RSS, - CGROUP_MEMORY_STAT_TOTAL_RSS_HUGE, - CGROUP_MEMORY_STAT_TOTAL_MAPPED_FILE, - CGROUP_MEMORY_STAT_TOTAL_DIRTY, - CGROUP_MEMORY_STAT_TOTAL_WRITEBACK, - CGROUP_MEMORY_STAT_TOTAL_SWAP, - CGROUP_MEMORY_STAT_TOTAL_PGPGIN, - CGROUP_MEMORY_STAT_TOTAL_PGPGOUT, - CGROUP_MEMORY_STAT_TOTAL_PGFAULT, - CGROUP_MEMORY_STAT_TOTAL_PGMAJFAULT, - CGROUP_MEMORY_STAT_TOTAL_INACTIVE_ANON, - CGROUP_MEMORY_STAT_TOTAL_ACTIVE_ANON, - CGROUP_MEMORY_STAT_TOTAL_INACTIVE_FILE, - CGROUP_MEMORY_STAT_TOTAL_ACTIVE_FILE, - CGROUP_MEMORY_STAT_TOTAL_UNEVICTABLE, - CGROUP_MEMORY_STAT_RECENT_ROTATED_ANON, - CGROUP_MEMORY_STAT_RECENT_ROTATED_FILE, - CGROUP_MEMORY_STAT_RECENT_SCANNED_ANON, - CGROUP_MEMORY_STAT_RECENT_SCANNED_FILE, - CGROUP_MEMORY_STAT_MAX, - CGROUP_MEMORY_STAT_INVALID = -1, -}; - -struct cgroup_memory_stat { - long long value[CGROUP_MEMORY_STAT_MAX]; -}; - -const char *cgroup_memory_stat_id_to_string(enum cgroup_memory_stat_id id); -enum cgroup_memory_stat_id cgroup_memory_stat_string_to_id(const char *str); - -int cgroup_get_memory_stat(const char *name, struct cgroup_memory_stat **mem_stat); - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/common/cgroup/cpu-cgroup.h b/src/common/cgroup/cpu-cgroup.h new file mode 100644 index 0000000..8b36e34 --- /dev/null +++ b/src/common/cgroup/cpu-cgroup.h @@ -0,0 +1,51 @@ +/* + * resourced + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/** + * @file cpu-cgroup.h + * @desc header file for handling memory cgroups + **/ + +#ifndef __CPU_CGROUP_H__ +#define __CPU_CGROUP_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define CPUCG_PATH "/sys/fs/cgroup/cpu" +#define CPUCG_BACKGROUND_PATH CPUCG_PATH"/background" +#define CPUCG_QUOTA_PATH CPUCG_PATH"/quota" +#define CPUCG_CONTROL_BANDWIDTH "cpu.cfs_quota_us" +#define CPUCG_CONTROL_FULL_BANDWIDTH "cpu.cfs_period_us" +#define CPUCG_SHARE "cpu.shares" + +/*#define CPU_DEFAULT_CGROUP "/sys/fs/cgroup/cpu" +#define CPU_BACKGROUND_GROUP CPU_DEFAULT_CGROUP"/background" +#define CPU_CPUQUOTA_GROUP CPU_DEFAULT_CGROUP"/quota" +#define CPU_CONTROL_BANDWIDTH "cpu.cfs_quota_us" +#define CPU_CONTROL_FULL_BANDWIDTH "cpu.cfs_period_us" +#define CPU_SHARE "cpu.shares"*/ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /*__CPU_CGROUP_H__*/ diff --git a/src/common/cgroup/memory-cgroup.h b/src/common/cgroup/memory-cgroup.h new file mode 100644 index 0000000..33032fb --- /dev/null +++ b/src/common/cgroup/memory-cgroup.h @@ -0,0 +1,240 @@ +/* + * resourced + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/** + * @file memory-cgroup.h + * @desc header file for handling memory cgroups + **/ + +#ifndef __MEMORY_CGROUP_H__ +#define __MEMORY_CGROUP_H__ + +#include +#include +#include "cgroup.h" +#include "const.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* number of memory cgroups */ +#define MEMCG_DEFAULT_EVENT_LEVEL "low" +#define MEMCG_DEFAULT_USE_HIERARCHY 0 + +#define MEMCG_LOW_RATIO 0.8 +#define MEMCG_MEDIUM_RATIO 0.96 +#define MEMCG_FOREGROUND_LEAVE_RATIO 0.25 + + +#define MEMCG_PATH CGROUP_PATH"/memory" +#define MEMCG_APPS_PATH MEMCG_PATH"/Apps" +#define MEMCG_BGLOCKED_PATH MEMCG_PATH"/Apps/BgLocked" +#define MEMCG_MEMLIMIT_PATH MEMCG_PATH"/MemLimit" +#define MEMCG_SWAP_PATH MEMCG_PATH"/Swap" +/*#define LOWMEM_ROOT_CGROUP "/sys/fs/cgroup/memory" +#define LOWMEM_APPS_CGROUP LOWMEM_ROOT_CGROUP"/Apps" +#define LOWMEM_BGLOCKED_CGROUP LOWMEM_ROOT_CGROUP"/Apps/BgLocked" +#define LOWMEM_MEMLIMIT_CGROUP LOWMEM_ROOT_CGROUP"/MemLimit" +#define LOWMEM_SWAP_CGROUP LOWMEM_ROOT_CGROUP"/Swap"*/ + +//#define MEMCG_OOM_CONTROL_PATH "memory.oom_control" +#define MEMCG_OOM_CONTROL "memory.oom_control" +#define MEMCG_EVENTFD_CONTROL "cgroup.event_control" +#define MEMCG_EVENTFD_MEMORY_PRESSURE "memory.pressure_level" +#define MEMCG_USAGE "memory.usage_in_bytes" +#define MEMCG_SWAP_USAGE "memory.memsw.usage_in_bytes" +#define MEMCG_LIMIT_BYTE "memory.limit_in_bytes" +#define MEMCG_SWAP_LIMIT_BYTE "memory.memsw.limit_in_bytes" +#define MEMCG_SWAPPINESS "memory.swappiness" +#define MEMCG_FORCE_RECLAIM "memory.force_reclaim" +#define MEMCG_MOVE_CHARGE "memory.move_charge_at_immigrate" +//#define MEMCG_LIMIT_PATH "memory.limit_in_bytes" +//#define MEMCG_SWAP_LIMIT_PATH "memory.memsw.limit_in_bytes" +//#define MEMCG_SWAPPINESS_PATH "memory.swappiness" + +#define DEFAULT_MEMLOG_PATH "/var/log" +#define DEFAULT_MEMLOG_NR_MAX 50 + +/* + * [memory cgroup information] + * MEMCG_MEMORY : root cgroup for system daemons + * MEMCG_APPS : cgroup for general apps + * MEMCG_BGLOCKED : cgroup for background locked and favorite apps + * MEMCG_LIMIT : cgroup for each app with memory limit set if configuration is enabled + * MEMCG_SWAP : cgroup for selected victims from background apps + * + * [memory cgroup hierarchy] + (root) + ├─Apps + │ └─BgLocked + ├─MemLimit + ├─Swap + └─system.slice (not controlled by resourced) + */ +enum memcg_type { + MEMCG_ROOT = -1, + MEMCG_MEMORY, + MEMCG_APPS, + MEMCG_BGLOCKED, + MEMCG_LIMIT, + MEMCG_SWAP, + MEMCG_MAX, +}; + +enum { + LOWMEM_NORMAL, + LOWMEM_DEDUP, + LOWMEM_SWAP, + LOWMEM_LOW, + LOWMEM_MEDIUM, + LOWMEM_MAX_LEVEL, +}; + +enum lowmem_control_type { + LOWMEM_MOVE_CGROUP, + LOWMEM_MANAGE_FOREGROUND, +}; + +enum mem_log { + MEMLOG_MEMPS, + MEMLOG_MEMPS_MEMLIMIT, + MEMLOG_MAX, +}; + + +enum cgroup_memory_stat_id { + CGROUP_MEMORY_STAT_CACHE = 0, + CGROUP_MEMORY_STAT_RSS, + CGROUP_MEMORY_STAT_RSS_HUGE, + CGROUP_MEMORY_STAT_MAPPED_FILE, + CGROUP_MEMORY_STAT_DIRTY, + CGROUP_MEMORY_STAT_WRITEBACK, + CGROUP_MEMORY_STAT_SWAP, + CGROUP_MEMORY_STAT_PGPGIN, + CGROUP_MEMORY_STAT_PGPGOUT, + CGROUP_MEMORY_STAT_PGFAULT, + CGROUP_MEMORY_STAT_PGMAJFAULT, + CGROUP_MEMORY_STAT_INACTIVE_ANON, + CGROUP_MEMORY_STAT_ACTIVE_ANON, + CGROUP_MEMORY_STAT_INACTIVE_FILE, + CGROUP_MEMORY_STAT_ACTIVE_FILE, + CGROUP_MEMORY_STAT_UNEVICTABLE, + CGROUP_MEMORY_STAT_HIERARCHICAL_MEMORY_LIMIT, + CGROUP_MEMORY_STAT_HIERARCHICAL_MEMSW_LIMIT, + CGROUP_MEMORY_STAT_TOTAL_CACHE, + CGROUP_MEMORY_STAT_TOTAL_RSS, + CGROUP_MEMORY_STAT_TOTAL_RSS_HUGE, + CGROUP_MEMORY_STAT_TOTAL_MAPPED_FILE, + CGROUP_MEMORY_STAT_TOTAL_DIRTY, + CGROUP_MEMORY_STAT_TOTAL_WRITEBACK, + CGROUP_MEMORY_STAT_TOTAL_SWAP, + CGROUP_MEMORY_STAT_TOTAL_PGPGIN, + CGROUP_MEMORY_STAT_TOTAL_PGPGOUT, + CGROUP_MEMORY_STAT_TOTAL_PGFAULT, + CGROUP_MEMORY_STAT_TOTAL_PGMAJFAULT, + CGROUP_MEMORY_STAT_TOTAL_INACTIVE_ANON, + CGROUP_MEMORY_STAT_TOTAL_ACTIVE_ANON, + CGROUP_MEMORY_STAT_TOTAL_INACTIVE_FILE, + CGROUP_MEMORY_STAT_TOTAL_ACTIVE_FILE, + CGROUP_MEMORY_STAT_TOTAL_UNEVICTABLE, + CGROUP_MEMORY_STAT_RECENT_ROTATED_ANON, + CGROUP_MEMORY_STAT_RECENT_ROTATED_FILE, + CGROUP_MEMORY_STAT_RECENT_SCANNED_ANON, + CGROUP_MEMORY_STAT_RECENT_SCANNED_FILE, + CGROUP_MEMORY_STAT_MAX, + CGROUP_MEMORY_STAT_INVALID = -1, +}; + +struct memcg_info { + /* name of memory cgroup */ + char name[MAX_PATH_LENGTH]; + /* hashname of memory cgroup for restoring memcg info*/ + char hashname[MAX_NAME_LENGTH]; + /* parent id */ + int parent_memcg; + /* limit ratio, if don't want to set limit, use NO_LIMIT*/ + float limit_ratio; + unsigned int limit; + /* leave memory usage */ + unsigned int oomleave; + /* thresholds, normal, swap, low, medium, and leave */ + unsigned int threshold[LOWMEM_MAX_LEVEL]; + unsigned int threshold_leave; + int evfd; + int swappiness; +}; + +struct memcg { + /* parent cgroup */ + struct memcg_info *info; + /* set when using multiple sub cgroups */ + bool use_hierarchy; + /* list of child cgroups when using multi groups */ + GSList *cgroups; +}; + +struct lowmem_control_data { + enum lowmem_control_type control_type; + int args[2]; +}; + +struct cgroup_memory_stat { + long long value[CGROUP_MEMORY_STAT_MAX]; +}; + +void memcg_info_set_limit(struct memcg_info *memcg_info, float ratio, + unsigned int totalram); +void memcg_info_set_swappiness(struct memcg_info *mi, int swappiness); +void memcg_init(struct memcg *memcg); + +/** + * @desc get anon memory usage of cgroup based on memory.stat + * @return 0 if the value was correctly read + */ +int memcg_get_anon_usage(char *memcg, unsigned int *anon_usage); + +/** + * @desc get swapped memory usage of cgroup mi based on memory.stat + * @return 0 if the value was correctly read + */ +int memcg_get_swap_usage(char *memcg, unsigned int *usage); + +/** + * @desc register eventfd to the memory cgroup with desired value + * @return eventfd if it was registered successfully or -1 on failure + */ +int memcg_set_eventfd(const char *memcg, const char *event, char *value); + +/** + * @desc execute /usr/bin/memps and make log file with pid and process name + */ +void make_memps_log(enum mem_log path, pid_t pid, char *victim_name); + + +const char *cgroup_memory_stat_id_to_string(enum cgroup_memory_stat_id id); +enum cgroup_memory_stat_id cgroup_memory_stat_string_to_id(const char *str); + +int cgroup_get_memory_stat(const char *name, struct cgroup_memory_stat **mem_stat); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /*__MEMORY_CGROUP_H__*/ diff --git a/src/common/const.h b/src/common/const.h index 7148617..c89a6e9 100644 --- a/src/common/const.h +++ b/src/common/const.h @@ -25,8 +25,6 @@ #ifndef _RESOURCED_CONST_H #define _RESOURCED_CONST_H -#define TASK_FILE_NAME "/tasks" -#define CGROUP_FILE_NAME "/cgroup.procs" #define MAX_PATH_LENGTH 512 #define MAX_NAME_LENGTH 256 diff --git a/src/common/dedup-common.h b/src/common/dedup-common.h index 60280ea..5a04c5a 100644 --- a/src/common/dedup-common.h +++ b/src/common/dedup-common.h @@ -27,7 +27,7 @@ #include #include "resourced.h" -#include "memory-common.h" +#include "memory-cgroup.h" #ifdef __cplusplus extern "C" { diff --git a/src/common/memory-common.h b/src/common/memory-common.h deleted file mode 100644 index 15cf27c..0000000 --- a/src/common/memory-common.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * resourced - * - * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/** - * @file memory-common.h - * @desc header file for handling memory cgroups - **/ - -#ifndef __MEMORY_COMMONL_H__ -#define __MEMORY_COMMONL_H__ - -#include -#include -#include "const.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* - * [memory cgroup information] - * MEMCG_MEMORY : root cgroup for system daemons - * MEMCG_APPS : cgroup for general apps - * MEMCG_BGLOCKED : cgroup for background locked and favorite apps - * MEMCG_LIMIT : cgroup for each app with memory limit set if configuration is enabled - * MEMCG_SWAP : cgroup for selected victims from background apps - * - * [memory cgroup hierarchy] - (root) - ├─Apps - │ └─BgLocked - ├─MemLimit - ├─Swap - └─system.slice (not controlled by resourced) - */ -enum memcg_type { - MEMCG_ROOT = -1, - MEMCG_MEMORY, - MEMCG_APPS, - MEMCG_BGLOCKED, - MEMCG_LIMIT, - MEMCG_SWAP, - MEMCG_MAX, -}; - -enum { - LOWMEM_NORMAL, - LOWMEM_DEDUP, - LOWMEM_SWAP, - LOWMEM_LOW, - LOWMEM_MEDIUM, - LOWMEM_MAX_LEVEL, -}; - -enum lowmem_control_type { - LOWMEM_MOVE_CGROUP, - LOWMEM_MANAGE_FOREGROUND, -}; - -enum mem_log { - MEMLOG_MEMPS, - MEMLOG_MEMPS_MEMLIMIT, - MEMLOG_MAX, -}; - -/* number of memory cgroups */ -#define MEMCG_DEFAULT_EVENT_LEVEL "low" -#define MEMCG_DEFAULT_USE_HIERARCHY 0 - -#define MEMCG_LOW_RATIO 0.8 -#define MEMCG_MEDIUM_RATIO 0.96 -#define MEMCG_FOREGROUND_LEAVE_RATIO 0.25 - - -#define LOWMEM_ROOT_CGROUP "/sys/fs/cgroup/memory" -#define LOWMEM_APPS_CGROUP LOWMEM_ROOT_CGROUP"/Apps" -#define LOWMEM_BGLOCKED_CGROUP LOWMEM_ROOT_CGROUP"/Apps/BgLocked" -#define LOWMEM_MEMLIMIT_CGROUP LOWMEM_ROOT_CGROUP"/MemLimit" -#define LOWMEM_SWAP_CGROUP LOWMEM_ROOT_CGROUP"/Swap" - -#define MEMCG_OOM_CONTROL_PATH "memory.oom_control" -#define MEMCG_EVENTFD_CONTROL "cgroup.event_control" -#define MEMCG_EVENTFD_MEMORY_PRESSURE "memory.pressure_level" -#define MEMCG_USAGE "memory.usage_in_bytes" -#define MEMCG_SWAP_USAGE "memory.memsw.usage_in_bytes" -#define MEMCG_LIMIT_PATH "memory.limit_in_bytes" -#define MEMCG_SWAP_LIMIT_PATH "memory.memsw.limit_in_bytes" -#define MEMCG_SWAPPINESS_PATH "memory.swappiness" - -#define DEFAULT_MEMLOG_PATH "/var/log" -#define DEFAULT_MEMLOG_NR_MAX 50 - -struct memcg_info { - /* name of memory cgroup */ - char name[MAX_PATH_LENGTH]; - /* hashname of memory cgroup for restoring memcg info*/ - char hashname[MAX_NAME_LENGTH]; - /* parent id */ - int parent_memcg; - /* limit ratio, if don't want to set limit, use NO_LIMIT*/ - float limit_ratio; - unsigned int limit; - /* leave memory usage */ - unsigned int oomleave; - /* thresholds, normal, swap, low, medium, and leave */ - unsigned int threshold[LOWMEM_MAX_LEVEL]; - unsigned int threshold_leave; - int evfd; - int swappiness; -}; - -struct memcg { - /* parent cgroup */ - struct memcg_info *info; - /* set when using multiple sub cgroups */ - bool use_hierarchy; - /* list of child cgroups when using multi groups */ - GSList *cgroups; -}; - -struct lowmem_control_data { - enum lowmem_control_type control_type; - int args[2]; -}; - -void memcg_info_set_limit(struct memcg_info *memcg_info, float ratio, - unsigned int totalram); -void memcg_info_set_swappiness(struct memcg_info *mi, int swappiness); -void memcg_init(struct memcg *memcg); - -/** - * @desc get anon memory usage of cgroup based on memory.stat - * @return 0 if the value was correctly read - */ -int memcg_get_anon_usage(char *memcg, unsigned int *anon_usage); - -/** - * @desc get swapped memory usage of cgroup mi based on memory.stat - * @return 0 if the value was correctly read - */ -int memcg_get_swap_usage(char *memcg, unsigned int *usage); - -/** - * @desc register eventfd to the memory cgroup with desired value - * @return eventfd if it was registered successfully or -1 on failure - */ -int memcg_set_eventfd(const char *memcg, const char *event, char *value); - -/** - * @desc execute /usr/bin/memps and make log file with pid and process name - */ -void make_memps_log(enum mem_log path, pid_t pid, char *victim_name); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /*__MEMORY_COMMONL_H__*/ diff --git a/src/common/proc-common.h b/src/common/proc-common.h index 283379e..7d9a964 100644 --- a/src/common/proc-common.h +++ b/src/common/proc-common.h @@ -31,7 +31,7 @@ #include "resourced.h" #include "const.h" -#include "memory-common.h" +#include "memory-cgroup.h" #ifdef __cplusplus extern "C" { diff --git a/src/common/procfs.c b/src/common/procfs.c index 9402910..6d57624 100644 --- a/src/common/procfs.c +++ b/src/common/procfs.c @@ -45,7 +45,7 @@ #include "util.h" #include "procfs.h" #include "proc-common.h" -#include "memory-common.h" +#include "memory-cgroup.h" #include "module.h" #include "file-helper.h" #include "swap-common.h" diff --git a/src/common/swap-common.h b/src/common/swap-common.h index 0c28ff7..73f0c48 100644 --- a/src/common/swap-common.h +++ b/src/common/swap-common.h @@ -27,7 +27,7 @@ #include #include "resourced.h" -#include "memory-common.h" +#include "memory-cgroup.h" #ifdef __cplusplus extern "C" { diff --git a/src/process/proc-process.c b/src/process/proc-process.c index 3e5583e..488c9ce 100644 --- a/src/process/proc-process.c +++ b/src/process/proc-process.c @@ -33,7 +33,7 @@ #include "cgroup.h" #include "proc-process.h" #include "procfs.h" -#include "memory-common.h" +#include "memory-cgroup.h" #include "macro.h" #include "notifier.h" #include "proc-appusage.h" diff --git a/src/process/vip/vip-process.c b/src/process/vip/vip-process.c index acda0e3..9435d98 100644 --- a/src/process/vip/vip-process.c +++ b/src/process/vip/vip-process.c @@ -317,12 +317,13 @@ static int vip_create_sub_cgroup(const char *name, pid_t pid) return -ENOMEM; } - r = cgroup_write_node_uint32(cgroup_name, TASK_FILE_NAME, pid); + cgroup_write_tid_fullpath(cgroup_name, pid); +/* r = cgroup_write_node_uint32(cgroup_name, TASK_FILE_NAME, pid); if (r < 0) { _E("failed to write pid '%d' to '%s': %m", pid, cgroup_name); return r; - } + }*/ _D("PID(%d) is registered as VIP sub cgroup(%s)", pid, name); @@ -463,7 +464,7 @@ static int resourced_vip_process_init(void *data) vip_load_configs(); if (!is_mounted(VIP_CGROUP)) { - r = cgroup_make_subdir(DEFAULT_CGROUP, "vip", NULL); + r = cgroup_make_subdir(CGROUP_PATH, "vip", NULL); if (r < 0) { _E("failed to make vip cgroup"); return RESOURCED_ERROR_FAIL; diff --git a/src/resource-limiter/cpu/cpu-sched.c b/src/resource-limiter/cpu/cpu-sched.c index e654030..0cf3cdf 100644 --- a/src/resource-limiter/cpu/cpu-sched.c +++ b/src/resource-limiter/cpu/cpu-sched.c @@ -119,7 +119,7 @@ static int cpu_sched_init_cgroup(struct cpu_sched *cs) _D("cpu-sched: init cgroup subsystem"); if (cpu_sched_is_cpuset_mounted() == false) { - r = cgroup_make_subdir(DEFAULT_CGROUP, "cpuset", NULL); + r = cgroup_make_subdir(CGROUP_PATH, "cpuset", NULL); if (r < 0) { _E("failed to make cpuset cgroup"); return r; @@ -411,7 +411,8 @@ static int cpu_sched_add_pid_to_cpuset(struct coreset *set, pid_t pid) _D("cpu-sched: add pid %d to cpuset %s", pid, set->name); - char path[PATH_MAX]; + cgroup_write_pid(CPUSET_CGROUP, set->name, pid); +/* char path[PATH_MAX]; int r = snprintf(path, sizeof path, "%s/%s", CPUSET_CGROUP, set->name); if (r < 0) { _E("cpu-sched: failed to setup path for cpuset (%s)", set->name); @@ -419,7 +420,7 @@ static int cpu_sched_add_pid_to_cpuset(struct coreset *set, pid_t pid) } r = cgroup_write_node_int32(path, "cgroup.procs", pid); - ret_value_msg_if(r < 0, RESOURCED_ERROR_FAIL, "Failed to attach pid %d to cgroup %s: %m", pid, path); + ret_value_msg_if(r < 0, RESOURCED_ERROR_FAIL, "Failed to attach pid %d to cgroup %s: %m", pid, path);*/ return RESOURCED_ERROR_NONE; } @@ -430,8 +431,9 @@ static int cpu_sched_remove_pid_from_cpuset(struct coreset *set, pid_t pid) _D("cpu-sched: moving pid %d to toplevel cpuset (from %s cpuset)", pid, set->name); - int r = cgroup_write_node_int32(CPUSET_CGROUP, "cgroup.procs", pid); - ret_value_msg_if(r < 0, RESOURCED_ERROR_FAIL, "Failed to attach pid %d to cgroup " CPUSET_CGROUP ": %m", pid); + cgroup_write_pid_fullpath(CPUSET_CGROUP, pid); +/* int r = cgroup_write_node_int32(CPUSET_CGROUP, "cgroup.procs", pid); + ret_value_msg_if(r < 0, RESOURCED_ERROR_FAIL, "Failed to attach pid %d to cgroup " CPUSET_CGROUP ": %m", pid);*/ return RESOURCED_ERROR_NONE; } diff --git a/src/resource-limiter/cpu/cpu.c b/src/resource-limiter/cpu/cpu.c index b7bad09..36c27dd 100644 --- a/src/resource-limiter/cpu/cpu.c +++ b/src/resource-limiter/cpu/cpu.c @@ -45,13 +45,14 @@ #include "config-parser.h" #include "const.h" #include "file-helper.h" +#include "cpu-cgroup.h" -#define CPU_DEFAULT_CGROUP "/sys/fs/cgroup/cpu" -#define CPU_BACKGROUND_GROUP CPU_DEFAULT_CGROUP"/background" -#define CPU_CPUQUOTA_GROUP CPU_DEFAULT_CGROUP"/quota" -#define CPU_CONTROL_BANDWIDTH "cpu.cfs_quota_us" -#define CPU_CONTROL_FULL_BANDWIDTH "cpu.cfs_period_us" -#define CPU_SHARE "cpu.shares" +/*#define CPUCG_PATH "/sys/fs/cgroup/cpu" +#define CPUCG_BACKGROUND_PATH CPUCG_PATH"/background" +#define CPUCG_QUOTA_PATH CPUCG_PATH"/quota" +#define CPUCG_CONTROL_BANDWIDTH "cpu.cfs_quota_us" +#define CPUCG_CONTROL_FULL_BANDWIDTH "cpu.cfs_period_us" +#define CPU_SHARE "cpu.shares"*/ #define CPU_CONF_FILE RD_CONFIG_FILE(cpu) #define CPU_CONF_SECTION "CONTROL" @@ -121,7 +122,8 @@ static int check_predefined(const pid_t pid) static int cpu_move_cgroup(pid_t pid, char *path) { - return cgroup_write_node_uint32(path, CGROUP_FILE_NAME, pid); + return cgroup_write_pid_fullpath(path, pid); + //return cgroup_write_node_uint32(path, CGROUP_FILE_NAME, pid); } static int cpu_move_cgroup_foreach(pid_t pid, struct proc_app_info *pai, char *path) @@ -130,13 +132,16 @@ static int cpu_move_cgroup_foreach(pid_t pid, struct proc_app_info *pai, char *p pid_t child_pid; if (!pai) - return cgroup_write_node_uint32(path, CGROUP_FILE_NAME, pid); + return cgroup_write_pid_fullpath(path, pid); +// return cgroup_write_node_uint32(path, CGROUP_FILE_NAME, pid); - cgroup_write_node_uint32(path, CGROUP_FILE_NAME, pai->main_pid); + cgroup_write_pid_fullpath(path, pai->main_pid); +// cgroup_write_node_uint32(path, CGROUP_FILE_NAME, pai->main_pid); if (pai->childs) { gslist_for_each_item(iter, pai->childs) { child_pid = GPOINTER_TO_PID(iter->data); - cgroup_write_node_uint32(path, CGROUP_FILE_NAME, child_pid); + cgroup_write_pid_fullpath(path, child_pid); +// cgroup_write_node_uint32(path, CGROUP_FILE_NAME, child_pid); } } return RESOURCED_ERROR_NONE; @@ -152,7 +157,7 @@ static void cpu_check_cpuquota(void) int ret, node = 0; char buf[MAX_PATH_LENGTH]; - snprintf(buf, sizeof(buf), "%s/%s", CPU_DEFAULT_CGROUP, CPU_CONTROL_BANDWIDTH); + snprintf(buf, sizeof(buf), "%s/%s", CPUCG_PATH, CPUCG_CONTROL_BANDWIDTH); ret = fread_int(buf, &node); if (!ret) bCPUQuota = true; @@ -182,7 +187,7 @@ static int load_cpu_config(struct parse_result *result, void *user_data) if (!strncmp(result->name, CPU_CONF_PREDEFINE, strlen(CPU_CONF_PREDEFINE)+1)) { pid = find_pid_from_cmdline(result->value); if (pid > 0) { - cpu_move_cgroup(pid, CPU_BACKGROUND_GROUP); + cpu_move_cgroup(pid, CPUCG_BACKGROUND_PATH); def_list.control[def_list.num].pid = pid; def_list.control[def_list.num++].type = SET_DEFAUT; } else { @@ -191,7 +196,7 @@ static int load_cpu_config(struct parse_result *result, void *user_data) } else if (!strncmp(result->name, CPU_CONF_BOOTING, strlen(CPU_CONF_BOOTING)+1)) { pid = find_pid_from_cmdline(result->value); if (pid > 0) { - cpu_move_cgroup(pid, CPU_BACKGROUND_GROUP); + cpu_move_cgroup(pid, CPUCG_BACKGROUND_PATH); def_list.control[def_list.num].pid = pid; def_list.control[def_list.num++].type = SET_BOOTING; setpriority(PRIO_PROCESS, pid, CPU_BACKGROUND_PRI); @@ -199,7 +204,7 @@ static int load_cpu_config(struct parse_result *result, void *user_data) } else if (!strncmp(result->name, CPU_CONF_WRT, strlen(CPU_CONF_WRT)+1)) { pid = find_pid_from_cmdline(result->value); if (pid > 0) { - cpu_move_cgroup(pid, CPU_BACKGROUND_GROUP); + cpu_move_cgroup(pid, CPUCG_BACKGROUND_PATH); def_list.control[def_list.num].pid = pid; def_list.control[def_list.num++].type = SET_WRT; setpriority(PRIO_PROCESS, pid, CPU_CONTROL_PRI); @@ -214,19 +219,19 @@ static int load_cpu_config(struct parse_result *result, void *user_data) } else if (!strncmp(result->name, "BACKGROUND_CPU_SHARE", strlen("BACKGROUND_CPU_SHARE")+1)) { value = atoi(result->value); if (value) - cgroup_write_node_uint32(CPU_BACKGROUND_GROUP, CPU_SHARE, - get_relative_value(CPU_DEFAULT_CGROUP, CPU_SHARE, value)); + cgroup_write_node_uint32(CPUCG_BACKGROUND_PATH, CPUCG_SHARE, + get_relative_value(CPUCG_PATH, CPUCG_SHARE, value)); } else if (!strncmp(result->name, "QUOTA_CPU_SHARE", strlen("QUOTA_CPU_SHARE")+1)) { value = atoi(result->value); if (value && cpu_quota_enabled()) - cgroup_write_node_uint32(CPU_CPUQUOTA_GROUP, CPU_SHARE, - get_relative_value(CPU_DEFAULT_CGROUP, CPU_SHARE, value)); + cgroup_write_node_uint32(CPUCG_QUOTA_PATH, CPUCG_SHARE, + get_relative_value(CPUCG_PATH, CPUCG_SHARE, value)); } else if (!strncmp(result->name, "QUOTA_MAX_BANDWIDTH", strlen("QUOTA_MAX_BANDWIDTH")+1)) { value = atoi(result->value); if (value && cpu_quota_enabled()) - cgroup_write_node_uint32(CPU_CPUQUOTA_GROUP, CPU_CONTROL_BANDWIDTH, - get_relative_value(CPU_CPUQUOTA_GROUP, - CPU_CONTROL_FULL_BANDWIDTH, value)); + cgroup_write_node_uint32(CPUCG_QUOTA_PATH, CPUCG_CONTROL_BANDWIDTH, + get_relative_value(CPUCG_QUOTA_PATH, + CPUCG_CONTROL_FULL_BANDWIDTH, value)); } return RESOURCED_ERROR_NONE; @@ -244,7 +249,7 @@ static int cpu_service_state(void *data) CHECK_BIT(ps->pai->categories, PROC_BG_MEDIA)) return RESOURCED_ERROR_NONE; - cpu_move_cgroup(ps->pid, CPU_BACKGROUND_GROUP); + cpu_move_cgroup(ps->pid, CPUCG_BACKGROUND_PATH); return RESOURCED_ERROR_NONE; } @@ -256,7 +261,7 @@ static int cpu_widget_state(void *data) _D("widget background: pid = %d, appname = %s", ps->pid, ps->pai->appid); if (CHECK_BIT(ps->pai->flags, PROC_DOWNLOADAPP)) - cpu_move_cgroup(ps->pid, CPU_BACKGROUND_GROUP); + cpu_move_cgroup(ps->pid, CPUCG_BACKGROUND_PATH); return RESOURCED_ERROR_NONE; } @@ -271,7 +276,7 @@ static int cpu_foreground_state(void *data) if (pri == -1 || pri > CPU_DEFAULT_PRI) setpriority(PRIO_PGRP, ps->pid, CPU_DEFAULT_PRI); if (check_predefined(ps->pid) != SET_DEFAUT) - cpu_move_cgroup_foreach(ps->pid, ps->pai, CPU_DEFAULT_CGROUP); + cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_PATH); return RESOURCED_ERROR_NONE; } @@ -282,7 +287,7 @@ static int cpu_background_state(void *data) _D("app background: pid = %d", ps->pid); setpriority(PRIO_PGRP, ps->pid, CPU_BACKGROUND_PRI); - cpu_move_cgroup_foreach(ps->pid, ps->pai, CPU_BACKGROUND_GROUP); + cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_BACKGROUND_PATH); return RESOURCED_ERROR_NONE; } @@ -299,7 +304,7 @@ static int cpu_restrict_state(void *data) return RESOURCED_ERROR_NONE; _D("app suspend: pid = %d, appname = %s", ps->pid, ps->pai->appid); - cpu_move_cgroup_foreach(ps->pid, ps->pai, CPU_CPUQUOTA_GROUP); + cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_QUOTA_PATH); return RESOURCED_ERROR_NONE; } @@ -313,7 +318,7 @@ static int cpu_active_state(void *data) ret = proc_get_oom_score_adj(ps->pid, &oom_score_adj); if (ret || oom_score_adj < OOMADJ_PREVIOUS_DEFAULT) return RESOURCED_ERROR_NONE; - cpu_move_cgroup_foreach(ps->pid, ps->pai, CPU_DEFAULT_CGROUP); + cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_PATH); return RESOURCED_ERROR_NONE; } @@ -328,7 +333,7 @@ static int cpu_prelaunch_state(void *data) if (ps->pai->type & PROC_WEBAPP) { for (i = 0; i < def_list.num; i++) { if (def_list.control[i].type == SET_WRT) { - cpu_move_cgroup(def_list.control[i].pid, CPU_DEFAULT_CGROUP); + cpu_move_cgroup(def_list.control[i].pid, CPUCG_PATH); setpriority(PRIO_PGRP, def_list.control[i].pid, 0); ioprio_set(IOPRIO_WHO_PROCESS, def_list.control[i].pid, IOPRIO_CLASS_BE << IOPRIO_CLASS_SHIFT); return RESOURCED_ERROR_NONE; @@ -344,7 +349,7 @@ static int cpu_system_state(void *data) assert(ps); _D("system service : pid = %d", ps->pid); - cpu_move_cgroup(ps->pid, CPU_BACKGROUND_GROUP); + cpu_move_cgroup(ps->pid, CPUCG_BACKGROUND_PATH); return RESOURCED_ERROR_NONE; } @@ -353,7 +358,7 @@ static int cpu_terminatestart_state(void *data) struct proc_status *ps = (struct proc_status *)data; assert(ps); - cpu_move_cgroup_foreach(ps->pid, ps->pai, CPU_DEFAULT_CGROUP); + cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_PATH); return RESOURCED_ERROR_NONE; } @@ -363,9 +368,9 @@ static int cpu_exclude_state(void *data) if (check_predefined(pe->pid) == SET_DEFAUT) return RESOURCED_ERROR_NONE; if (pe->type == PROC_INCLUDE) - cpu_move_cgroup(pe->pid, CPU_BACKGROUND_GROUP); + cpu_move_cgroup(pe->pid, CPUCG_BACKGROUND_PATH); else - cpu_move_cgroup(pe->pid, CPU_DEFAULT_CGROUP); + cpu_move_cgroup(pe->pid, CPUCG_PATH); return RESOURCED_ERROR_NONE; } @@ -375,12 +380,12 @@ static gboolean cpu_predefined_cb(gpointer data) for (i = 0; i < def_list.num; i++) { if (def_list.control[i].type == SET_LAZY) { - cpu_move_cgroup(def_list.control[i].pid, CPU_BACKGROUND_GROUP); + cpu_move_cgroup(def_list.control[i].pid, CPUCG_BACKGROUND_PATH); } else if (def_list.control[i].type == SET_BOOTING) { - cpu_move_cgroup(def_list.control[i].pid, CPU_DEFAULT_CGROUP); + cpu_move_cgroup(def_list.control[i].pid, CPUCG_PATH); setpriority(PRIO_PROCESS, def_list.control[i].pid, 0); } else if (def_list.control[i].type == SET_WRT) { - cpu_move_cgroup(def_list.control[i].pid, CPU_DEFAULT_CGROUP); + cpu_move_cgroup(def_list.control[i].pid, CPUCG_PATH); setpriority(PRIO_PROCESS, def_list.control[i].pid, 0); ioprio_set(IOPRIO_WHO_PROCESS, def_list.control[i].pid, IOPRIO_CLASS_BE << IOPRIO_CLASS_SHIFT); } @@ -395,11 +400,11 @@ static int resourced_cpu_init(void *data) int ret_code; _D("resourced_cpu_init"); - ret_code = cgroup_make_subdir(CPU_DEFAULT_CGROUP, "background", NULL); + ret_code = cgroup_make_subdir(CPUCG_PATH, "background", NULL); ret_value_msg_if(ret_code < 0, ret_code, "cpu init failed\n"); cpu_check_cpuquota(); if (cpu_quota_enabled()) { - ret_code = cgroup_make_subdir(CPU_DEFAULT_CGROUP, "quota", NULL); + ret_code = cgroup_make_subdir(CPUCG_PATH, "quota", NULL); ret_value_msg_if(ret_code < 0, ret_code, "create service cgroup failed\n"); } config_parse(CPU_CONF_FILE, load_cpu_config, NULL); diff --git a/src/resource-limiter/memory/compaction.c b/src/resource-limiter/memory/compaction.c index 9749d02..1126fe4 100644 --- a/src/resource-limiter/memory/compaction.c +++ b/src/resource-limiter/memory/compaction.c @@ -32,7 +32,7 @@ #include "config-parser.h" #include "module.h" #include "macro.h" -#include "memory-common.h" +#include "memory-cgroup.h" #include "notifier.h" #include "procfs.h" #include "resourced.h" diff --git a/src/resource-limiter/memory/lowmem-dbus.c b/src/resource-limiter/memory/lowmem-dbus.c index eaedfe8..8f6561f 100644 --- a/src/resource-limiter/memory/lowmem-dbus.c +++ b/src/resource-limiter/memory/lowmem-dbus.c @@ -30,7 +30,7 @@ #include "dbus-handler.h" #include "resourced.h" #include "macro.h" -#include "memory-common.h" +#include "memory-cgroup.h" #include "procfs.h" #include "util.h" diff --git a/src/resource-limiter/memory/lowmem-handler.h b/src/resource-limiter/memory/lowmem-handler.h index f42106d..6c15d56 100644 --- a/src/resource-limiter/memory/lowmem-handler.h +++ b/src/resource-limiter/memory/lowmem-handler.h @@ -27,7 +27,7 @@ #define __LOWMEM_HANDLER_H__ #include -#include +#include #ifdef __cplusplus extern "C" { diff --git a/src/resource-limiter/memory/lowmem-limit.c b/src/resource-limiter/memory/lowmem-limit.c index a0f70a6..3eb9f4e 100644 --- a/src/resource-limiter/memory/lowmem-limit.c +++ b/src/resource-limiter/memory/lowmem-limit.c @@ -43,7 +43,7 @@ #include "cgroup.h" #include "const.h" #include "proc-common.h" -#include "memory-common.h" +#include "memory-cgroup.h" #include "util.h" #include "smaps.h" #include "config-parser.h" @@ -221,7 +221,7 @@ static void memlimit_finish_cb(void *data, int ret) * since kernel can find and kill victim on cgroup oom. */ else if (mem_limit == MEM_LIMIT_OOM) - cgroup_write_node_uint32(mlog->cgdir, MEMCG_OOM_CONTROL_PATH, 0); + cgroup_write_node_uint32(mlog->cgdir, MEMCG_OOM_CONTROL, 0); free(mlog->appname); free(mlog->cgdir); @@ -412,9 +412,9 @@ void lowmem_reassign_limit(const char *dir, unsigned int limit) } } - ret = cgroup_read_node_uint32(dir, MEMCG_LIMIT_PATH, &prev); + ret = cgroup_read_node_uint32(dir, MEMCG_LIMIT_BYTE, &prev); if (ret) { - _E("Failed to get %s from %s", MEMCG_LIMIT_PATH, dir); + _E("Failed to get %s from %s", MEMCG_LIMIT_BYTE, dir); return; } @@ -430,13 +430,13 @@ void lowmem_reassign_limit(const char *dir, unsigned int limit) * because almost memcg does't have a limitation about swap usage */ if (prev > limit) { - cgroup_write_node_uint32(dir, MEMCG_LIMIT_PATH, limit); - cgroup_write_node_uint32(dir, MEMCG_SWAP_LIMIT_PATH, limit); + cgroup_write_node_uint32(dir, MEMCG_LIMIT_BYTE, limit); + cgroup_write_node_uint32(dir, MEMCG_SWAP_LIMIT_BYTE, limit); } else if (prev < limit) { - cgroup_write_node_uint32(dir, MEMCG_SWAP_LIMIT_PATH, limit); - cgroup_write_node_uint32(dir, MEMCG_LIMIT_PATH, limit); + cgroup_write_node_uint32(dir, MEMCG_SWAP_LIMIT_BYTE, limit); + cgroup_write_node_uint32(dir, MEMCG_LIMIT_BYTE, limit); } else { - cgroup_write_node_uint32(dir, MEMCG_SWAP_LIMIT_PATH, limit); + cgroup_write_node_uint32(dir, MEMCG_SWAP_LIMIT_BYTE, limit); } return; case MEM_LIMIT_OOM: @@ -447,15 +447,15 @@ void lowmem_reassign_limit(const char *dir, unsigned int limit) * and collect log files about problem situation. * Otherwise, MEM_LIMIT_NONE and MEM_LIMIT_OOM will be same. */ - cgroup_write_node_uint32(dir, MEMCG_OOM_CONTROL_PATH, 1); + cgroup_write_node_uint32(dir, MEMCG_OOM_CONTROL, 1); if (prev > limit) { - cgroup_write_node_uint32(dir, MEMCG_LIMIT_PATH, limit); - cgroup_write_node_uint32(dir, MEMCG_SWAP_LIMIT_PATH, limit); + cgroup_write_node_uint32(dir, MEMCG_LIMIT_BYTE, limit); + cgroup_write_node_uint32(dir, MEMCG_SWAP_LIMIT_BYTE, limit); } else if (prev < limit) { - cgroup_write_node_uint32(dir, MEMCG_SWAP_LIMIT_PATH, limit); - cgroup_write_node_uint32(dir, MEMCG_LIMIT_PATH, limit); + cgroup_write_node_uint32(dir, MEMCG_SWAP_LIMIT_BYTE, limit); + cgroup_write_node_uint32(dir, MEMCG_LIMIT_BYTE, limit); } else { - cgroup_write_node_uint32(dir, MEMCG_SWAP_LIMIT_PATH, limit); + cgroup_write_node_uint32(dir, MEMCG_SWAP_LIMIT_BYTE, limit); } break; case MEM_LIMIT_TRHESHOLD: @@ -464,7 +464,7 @@ void lowmem_reassign_limit(const char *dir, unsigned int limit) * need to set limitation value again for preventing kernel OOM * it is larger than original limitation value */ - cgroup_write_node_uint32(dir, MEMCG_LIMIT_PATH, (limit * 1.2)); + cgroup_write_node_uint32(dir, MEMCG_LIMIT_BYTE, (limit * 1.2)); break; default: return; @@ -510,16 +510,18 @@ int lowmem_limit_move_cgroup(struct proc_app_info *pai) if (!pai->memory.use_mem_limit) return RESOURCED_ERROR_NO_DATA; - ret = asprintf(&path, "%s/%s", LOWMEM_MEMLIMIT_CGROUP, pai->appid); + ret = asprintf(&path, "%s/%s", MEMCG_MEMLIMIT_PATH, pai->appid); if (ret < 0) { _E("not enough memory"); return RESOURCED_ERROR_OUT_OF_MEMORY; } - cgroup_write_node_uint32(path, CGROUP_FILE_NAME, pai->main_pid); + cgroup_write_pid_fullpath(path, pai->main_pid); +// cgroup_write_node_uint32(path, CGROUP_FILE_NAME, pai->main_pid); if (pai->childs) { gslist_for_each_item(iter, pai->childs) - cgroup_write_node_uint32(path, CGROUP_FILE_NAME, - GPOINTER_TO_PID(iter->data)); + cgroup_write_pid_fullpath(path, GPOINTER_TO_PID(iter->data)); +/* cgroup_write_node_uint32(path, CGROUP_FILE_NAME, + GPOINTER_TO_PID(iter->data));*/ } return RESOURCED_ERROR_NONE; } @@ -563,7 +565,7 @@ static int memlimit_config_parse(struct parse_result *result, void *user_data) * if kernel is supported. * one of SIGKILL, SIGTRAP, SIGTERM */ - registerpath = MEMCG_OOM_CONTROL_PATH; + registerpath = MEMCG_OOM_CONTROL; } else { /* * check swap status when resourced registers threshold event. @@ -571,7 +573,7 @@ static int memlimit_config_parse(struct parse_result *result, void *user_data) * resourced registers memory.memsw.usage_in_bytes, * otherwise, register memory.limit_in_bytes. */ - ret = cgroup_read_node_uint32(LOWMEM_ROOT_CGROUP, + ret = cgroup_read_node_uint32(MEMCG_PATH, MEMCG_SWAP_USAGE, &usage); if (ret == RESOURCED_ERROR_NONE) registerpath = MEMCG_SWAP_USAGE; @@ -620,28 +622,32 @@ void lowmem_limit_set(pid_t pid, unsigned int limit) cgpath = appname; } - ret = asprintf(&path, "%s/%s", LOWMEM_MEMLIMIT_CGROUP, cgpath); + ret = asprintf(&path, "%s/%s", MEMCG_MEMLIMIT_PATH, cgpath); if (ret < 0) { _E("not enough memory"); return; } - ret = cgroup_make_subdir(LOWMEM_MEMLIMIT_CGROUP, cgpath, NULL); + ret = cgroup_make_subdir(MEMCG_MEMLIMIT_PATH, cgpath, NULL); if (ret < 0) { _E("Failed to create cgroup subdir '%s/%s'", - LOWMEM_MEMLIMIT_CGROUP, cgpath); + MEMCG_MEMLIMIT_PATH, cgpath); return; } lowmem_reassign_limit(path, MBYTE_TO_BYTE(limit)); - ret = cgroup_write_node_uint32(path, CGROUP_FILE_NAME, pid); + ret = cgroup_write_pid_fullpath(path, pid); if (ret < 0) { - _E("Failed to write pid(%d) to '%s/%s'", pid, path, CGROUP_FILE_NAME); return; } +/* ret = cgroup_write_node_uint32(path, CGROUP_FILE_NAME, pid); + if (ret < 0) { + _E("Failed to write pid(%d) to '%s/%s'", pid, path, CGROUP_FILE_NAME); + return; + }*/ - ret = cgroup_write_node_uint32(path, "memory.move_charge_at_immigrate", 3U); + ret = cgroup_write_node_uint32(path, MEMCG_MOVE_CHARGE, 3U); if (ret < 0) _W("Failed to set immigrate mode for %s (non-crucial, continuing)", path); @@ -656,10 +662,11 @@ void lowmem_limit_set(pid_t pid, unsigned int limit) gslist_for_each_item(iter, pai->childs) { pid_t child = GPOINTER_TO_PID(iter->data); - ret = cgroup_write_node_uint32(path, CGROUP_FILE_NAME, child); + cgroup_write_pid_fullpath(path, child); +/* ret = cgroup_write_node_uint32(path, CGROUP_FILE_NAME, child); if (ret < 0) _E("Failed to write pid(%d) to '%s/%s', ignoring for other children", - child, path, CGROUP_FILE_NAME); + child, path, CGROUP_FILE_NAME);*/ } } diff --git a/src/resource-limiter/memory/lowmem-system.c b/src/resource-limiter/memory/lowmem-system.c index f40b0d7..3cabc47 100644 --- a/src/resource-limiter/memory/lowmem-system.c +++ b/src/resource-limiter/memory/lowmem-system.c @@ -42,7 +42,7 @@ #include "cgroup.h" #include "const.h" #include "proc-common.h" -#include "memory-common.h" +#include "memory-cgroup.h" #include "util.h" #include "smaps.h" #include "config-parser.h" @@ -74,12 +74,12 @@ static int search_systemd_cgroup(const char *dir) return -errno; } - ret = cgroup_read_node_int32(LOWMEM_ROOT_CGROUP, MEMCG_SWAPPINESS_PATH, + ret = cgroup_read_node_int32(MEMCG_PATH, MEMCG_SWAPPINESS, &rootswappiness); if (ret != RESOURCED_ERROR_NONE) return -errno; - ret = cgroup_read_node_int32(dir, MEMCG_SWAPPINESS_PATH, + ret = cgroup_read_node_int32(dir, MEMCG_SWAPPINESS, &memcgswappiness); if (ret != RESOURCED_ERROR_NONE) return -errno; @@ -87,10 +87,10 @@ static int search_systemd_cgroup(const char *dir) if ((rootswappiness >=0) && (rootswappiness != memcgswappiness)) { changeswappiness = rootswappiness; ret = cgroup_write_node_uint32(dir, - MEMCG_SWAPPINESS_PATH, changeswappiness); + MEMCG_SWAPPINESS, changeswappiness); if (ret != RESOURCED_ERROR_NONE) { _I("failed to write %s %d to %s the", - MEMCG_SWAPPINESS_PATH, changeswappiness, dir); + MEMCG_SWAPPINESS, changeswappiness, dir); return -errno; } } @@ -113,16 +113,16 @@ static int search_systemd_cgroup(const char *dir) if (ret < 0) return -ENOMEM; - ret = cgroup_read_node_uint32(path, MEMCG_LIMIT_PATH, &limit); + ret = cgroup_read_node_uint32(path, MEMCG_LIMIT_BYTE, &limit); if (ret != RESOURCED_ERROR_NONE ||limit <= 0) continue; if (changeswappiness >= 0) { ret = cgroup_write_node_uint32(path, - MEMCG_SWAPPINESS_PATH, changeswappiness); + MEMCG_SWAPPINESS, changeswappiness); if (ret != RESOURCED_ERROR_NONE) _I("failed to write %s %d to %s the", - MEMCG_SWAPPINESS_PATH, changeswappiness, path); + MEMCG_SWAPPINESS, changeswappiness, path); } lowmem_reassign_limit(path, limit); diff --git a/src/resource-limiter/memory/memcontrol.c b/src/resource-limiter/memory/memcontrol.c index 72eb99f..4e2ae43 100644 --- a/src/resource-limiter/memory/memcontrol.c +++ b/src/resource-limiter/memory/memcontrol.c @@ -36,7 +36,7 @@ #include "resourced.h" #include "trace.h" #include "macro.h" -#include "memory-common.h" +#include "memory-cgroup.h" #include "cgroup.h" #include "module.h" #include "util.h" diff --git a/src/resource-limiter/memory/vmpressure-lowmem-handler.c b/src/resource-limiter/memory/vmpressure-lowmem-handler.c index 36400fd..5944a77 100644 --- a/src/resource-limiter/memory/vmpressure-lowmem-handler.c +++ b/src/resource-limiter/memory/vmpressure-lowmem-handler.c @@ -59,7 +59,7 @@ #include "module.h" #include "swap-common.h" #include "cgroup.h" -#include "memory-common.h" +#include "memory-cgroup.h" #include "heart-common.h" #include "proc-main.h" #include "dbus-handler.h" @@ -73,15 +73,15 @@ #define LOWMEM_THRES_INIT 0 #define MEMPS_EXEC_PATH "usr/bin/memps" -#define MEMCG_MOVE_CHARGE_PATH "memory.move_charge_at_immigrate" -#define MEMCG_EVENTFD_MEMORY_PRESSURE "memory.pressure_level" +//#define MEMCG_MOVE_CHARGE_PATH "memory.move_charge_at_immigrate" +//#define MEMCG_EVENTFD_MEMORY_PRESSURE "memory.pressure_level" #define MEM_CONF_FILE RD_CONFIG_FILE(memory) #define MEM_VIP_SECTION "VIP_PROCESS" #define MEM_VIP_PREDEFINE "PREDEFINE" #define MEM_POPUP_SECTION "POPUP" #define MEM_POPUP_STRING "oom_popup" #define MEM_BG_RECLAIM_SECTION "BackgroundReclaim" -#define MEM_BG_RECLAIM_STRING "AfterScreenDim" +#define MEM_BG_RECLAIM_STRING "AfterScreenDim" #define MEM_LOGGING_SECTION "Logging" #define BUF_MAX 1024 @@ -361,11 +361,11 @@ static bool bg_reclaim; static int fragmentation_size; static struct memcg_info gmi[MEMCG_MAX] = { - {LOWMEM_ROOT_CGROUP, "/", MEMCG_ROOT,}, - {LOWMEM_APPS_CGROUP, "Apps", MEMCG_MEMORY,}, - {LOWMEM_BGLOCKED_CGROUP, "Apps/BgLocked", MEMCG_APPS,}, - {LOWMEM_MEMLIMIT_CGROUP, "MemLimit", MEMCG_MEMORY,}, - {LOWMEM_SWAP_CGROUP, "Swap", MEMCG_MEMORY,}, + {MEMCG_PATH, "/", MEMCG_ROOT,}, + {MEMCG_APPS_PATH, "Apps", MEMCG_MEMORY,}, + {MEMCG_BGLOCKED_PATH, "Apps/BgLocked", MEMCG_APPS,}, + {MEMCG_MEMLIMIT_PATH, "MemLimit", MEMCG_MEMORY,}, + {MEMCG_SWAP_PATH, "Swap", MEMCG_MEMORY,}, }; enum memory_level { @@ -708,7 +708,7 @@ static int lowmem_kill_victim(const struct task_info *tsk, else safe_kill(pid, SIGKILL); - _E("we killed, force(%d), %d (%s) score = %d, size: rss = %u, sigterm = %d\n", + _D("we killed, force(%d), %d (%s) score = %d, size: rss = %u, sigterm = %d\n", flags & OOM_FORCE, pid, appname, tsk->oom_score_adj, tsk->size, sigterm); *victim_size = tsk->size; @@ -1298,7 +1298,8 @@ void lowmem_trigger_swap(pid_t pid, int memcg_idx) mi = memcg_tree[memcg_idx]->info; _D("name : %s, pid : %d", mi->name, pid); - cgroup_write_node_uint32(mi->name, CGROUP_FILE_NAME, pid); + cgroup_write_pid_fullpath(mi->name, pid); + //cgroup_write_node_uint32(mi->name, CGROUP_FILE_NAME, pid); msg.type = memcg_idx; msg.info = mi; resourced_notify(RESOURCED_NOTIFIER_SWAP_START, &msg); @@ -1871,7 +1872,7 @@ static int write_params_memcg_info(struct memcg_info *mi) _I("write memcg param for %s", name); /* enable cgroup move */ ret = cgroup_write_node_uint32(name, - MEMCG_MOVE_CHARGE_PATH, 3); + MEMCG_MOVE_CHARGE, 3); if (ret) return ret; @@ -1887,10 +1888,10 @@ static int write_params_memcg_info(struct memcg_info *mi) if (swappiness >= 0) { ret = cgroup_write_node_uint32(name, - MEMCG_SWAPPINESS_PATH, swappiness); + MEMCG_SWAPPINESS, swappiness); if (ret) _I("failed to write %s %d to %s the", - MEMCG_SWAPPINESS_PATH, swappiness, name); + MEMCG_SWAPPINESS, swappiness, name); } if (mi->limit_ratio == LOWMEM_NO_LIMIT) @@ -1898,7 +1899,7 @@ static int write_params_memcg_info(struct memcg_info *mi) /* write limit_in_bytes */ ret = cgroup_write_node_uint32(name, - MEMCG_LIMIT_PATH, limit); + MEMCG_LIMIT_BYTE, limit); _I("set %s's limit to %u", name, limit); return ret; } @@ -1983,7 +1984,8 @@ static void lowmem_move_memcgroup(int pid, int oom_score_adj) return; } } - cgroup_write_node_uint32(mi->name, CGROUP_FILE_NAME, pid); + cgroup_write_pid_fullpath(mi->name, pid); + //cgroup_write_node_uint32(mi->name, CGROUP_FILE_NAME, pid); proc_set_process_memory_state(pai, memcg_idx, mi, oom_score_adj); /* @@ -2056,7 +2058,7 @@ static int create_memcgs(void) continue; mi = memcg_tree[i]->info; name = mi->hashname; - ret = cgroup_make_subdir(LOWMEM_ROOT_CGROUP, name, NULL); + ret = cgroup_make_subdir(MEMCG_PATH, name, NULL); _D("create memory cgroup for %s, ret = %d", name, ret); } diff --git a/src/resource-optimizer/memory/dedup/.dedup.c.swp b/src/resource-optimizer/memory/dedup/.dedup.c.swp new file mode 100644 index 0000000000000000000000000000000000000000..3cfa9a4e917bea48e93636fdea3648e4f293f855 GIT binary patch literal 16384 zcmeI3U5wmT6~`SKTBaow0nI}M;j(i0Pn1mxS5?Xa%ZNQ6T{m?K^_f(iadFDj-k`{I9>p_RN+P z@r3S3zs%0L=N{ktKiBs7%*{^wg1kZQZMFrx-Yy6y@Bf*;^WMjVcO4gm$O$56WK+u8 zUgwqjHQwKDs~wTODIIa9$0u^fR%jhirxm!7Z_t*f8<+Kw<&0WBO-yDh@QwUa!}UUI zj2?b#OvkRj-!iEgdC9*`W9B&Az!l&M%v0c)aQDh`e5#*ZcprJ^JGSOIaT`~FE5H@t z3UCFu0$c&E09Sx3@PDd6=-n)Q5_5Y~I=_e0_al|}f2FTar}j@(+W(ohe<8KsmIlb; zyq2~_68&`lUz!l&Ma0R#mTmh~CSAZ+P z72pbR1-Jrp6wpmUxEb~)d!EMc|Jn2ZYqtx+%ixdT>)>nPL2v^6>1~4W2k>L?1PDP3 z{O*__Tn7hW0zwb~4`|>VSO?4CJ>VAb=eG*Nufa3m``|iw7>t1e?ga!K1Ao6w5MBbm z2hV}0!1urx!2!@f2Q{AL_C#j}#4sr@)Mb4@2$nwRG5&WKiL z_rS^}a++Kf;z>^Dgu&N^+Vt~ujwSQ#gi6hY36$*R@t!8_xv`#r7Ozqlc7+(&j?*QUCYhrfrdwKUbmE{KiArfTa_SKLm#4~w3< zR$?FKE%n5;u2ga^tfP3ZQgVi5E2%gtcBW)&38_P(EHg`#J0x*$GIq_#rb$j|Nd0N* zDxt7iik7*#tN6?&s^U<}N~JANL&aXwdVX8Qnuv%~DqGV9-I7)PdQ!~jZMqt>E$+FN zd1|$IUMF!`yP-Ra`RT(xY0#O%J99s)#2eJeQqqS7)UXqc`WR*pm!v#y)e*5A>}R_n zXWa;`JzQ32+_O=zi%~8{Xz6x5at&tcW4T}~@rus}Gxd)Ld;@;N$UY=!drnk{fKx8i zOls@u9z+!Hzxn40Su8d8}CUWJ*l&)Ia|7G)dO)Mt@z>di|c1 zcPd2AMnD~X2d70fe8IEoF=v>m{*ECWP`jHW)C$i>x!F19%vzY-Jvis%if@GbbUDA@M7Vi2~H_?l@9up{z zU258i923%{_oqbDKJJO}?J57bE{Ppgz96bnem261o$#g4xKHjYuh)@tGWBZf(6S57oW0iXgDE) z72RyhiLSJ4*Y(QwWJ_+t82N5gX$tm(d=qcE6Kk0>5?Ik)x>9$c*fqt+h>2kv^hir{7zb zRk`28r!z$CZIknIZ@o^ag+uy;Uh%LWJ0LiuHTGfK2#rxjUhbxH>Uh51)o5o%N8#-cMa|wv#AenZWeobkZvZ^+Gl-T2Uu-N6`rYqT4ZMdK7%X|J@2f+sF) z&nJ>ijnH=;%LquvZPrN_>zs(TP2vtrWL$CflI*cr<(ur;Vr0+%XYp+P9AMA?+3)K= z!gKx)!FRy7z&F7j2*D}v8$9oS8FayUPzQH`qu?g+BA)G8J>Yrp1Mn!g1|9^f;2${N z-@sqfV?WD|&tF^tt^iknE5H@t3UCFu0$c&E09W9RDS*=9R#(yn(pg!-k41}j=9R{@ z(snATv^DXtXk6C($YGTTEr>kN^+Qwv^9Ll9IPw3CwYh#MkTvNQYo0&KUZ~<9Q08Je zb6uF3H9Pv4)h`#~11&I%=UXlwby;CGok&)&LOFD>A$IFo4f8*j6cK|J0EL=Q!^n5Y zKvMc!gO0SWNrORukk(g)nkFwMBglSem{@px+@W~ZO=e=UCsCo6$YIi~WQrOzE15&q z#kf6kd^*C@KlQb&K(;tNX0NZxXJly*m*?c(S#2HV-FjLFWff&s0ykZURp4tk7%Hh` zDr$c-3lxN|r==CRHy#L;&O8wNLEyg*q>2MIj}+>DSO|4B%OI=NR~K6*dHl--etAIY RkFD1{he#z$#s5m^e*^nhD=z>5 literal 0 HcmV?d00001 diff --git a/src/resource-optimizer/memory/dedup/dedup.c b/src/resource-optimizer/memory/dedup/dedup.c index 7613473..ebd2363 100644 --- a/src/resource-optimizer/memory/dedup/dedup.c +++ b/src/resource-optimizer/memory/dedup/dedup.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/resource-optimizer/memory/swap/fileswap.c b/src/resource-optimizer/memory/swap/fileswap.c index 9f3f642..2f783c9 100644 --- a/src/resource-optimizer/memory/swap/fileswap.c +++ b/src/resource-optimizer/memory/swap/fileswap.c @@ -24,7 +24,7 @@ #include "file-helper.h" #include "procfs.h" #include "swap-common.h" -#include "memory-common.h" +#include "memory-cgroup.h" #include "config-parser.h" #include "lowmem-handler.h" #include "losetup.h" diff --git a/src/resource-optimizer/memory/swap/swap.c b/src/resource-optimizer/memory/swap/swap.c index 87d67de..e421f43 100644 --- a/src/resource-optimizer/memory/swap/swap.c +++ b/src/resource-optimizer/memory/swap/swap.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include @@ -55,21 +55,21 @@ #include "losetup.h" #include "init.h" -#define MEMCG_PATH "/sys/fs/cgroup/memory/" +/*#define MEMCG_PATH "/sys/fs/cgroup/memory/" #define MEMCG_SIZE_LIMIT "memory.limit_in_bytes" -#define SWAPCG_RECLAIM "memory.force_reclaim" -#define MOVE_CHARGE "memory.move_charge_at_immigrate" - -#define SWAP_PRIORITY 20 -#define SWAP_HARD_LIMIT_DEFAULT 0.5 -#define SWAP_FORCE_RECLAIM_NUM_MAX 5 -#define SWAP_RECLAIM_PAGES_MAX 2560 -#define SWAP_RECLAIM_PAGES_MIN 128 -#define SWAP_MEMCG_SWAPPINESS 60 -#define SWAP_MIN_SWAPPINESS 0 -#define SWAP_EARLYRECLAIM_TIME_DEFAULT 60 -#define SWAP_EARLYRECLAIM_INTERVAL 1 -#define SWAP_EARLYRECLAIM_MAXTRY 2 +#define MEMCG_FORCE_RECLAIM "memory.force_reclaim" +#define MEMCG_MOVE_CHARGE "memory.move_charge_at_immigrate"*/ + +#define SWAP_PRIORITY 20 +#define SWAP_HARD_LIMIT_DEFAULT 0.5 +#define SWAP_FORCE_RECLAIM_NUM_MAX 5 +#define SWAP_RECLAIM_PAGES_MAX 2560 +#define SWAP_RECLAIM_PAGES_MIN 128 +#define SWAP_MEMCG_SWAPPINESS 60 +#define SWAP_MIN_SWAPPINESS 0 +#define SWAP_EARLYRECLAIM_TIME_DEFAULT 60 +#define SWAP_EARLYRECLAIM_INTERVAL 1 +#define SWAP_EARLYRECLAIM_MAXTRY 2 #define SWAP_EARLYRECLAIM_THRESHOLD_DEFAULT MBYTE_TO_BYTE(1024) #define EARLYRECLAIM_WITH_AN_EXPLANATION_FOR_LAYMEN "early memory reclaim (done to retrieve resources used by daemons during system start-up)" @@ -130,6 +130,7 @@ static int swap_sort_func(const struct swap_module_ops *a, void swap_add(const struct swap_module_ops *ops) { + _I("Swap module name: %s", ops->name); swap_module = g_slist_insert_sorted(swap_module, (gpointer)ops, (GCompareFunc) swap_sort_func); @@ -317,10 +318,10 @@ static int swap_use_hard_limit(char *memcg) _D("Swap request: %s cgroup usage is %u, hard limit set to %u (hard limit fraction %f)", memcg, usage, memcg_limit, swap_hard_limit_fraction); if (memcg_limit != 0) - ret = cgroup_write_node_uint32(memcg, MEMCG_SIZE_LIMIT, memcg_limit); + ret = cgroup_write_node_uint32(memcg, MEMCG_LIMIT_BYTE, memcg_limit); else /* If the group is empty don't set the limit to enable adding processes. */ - ret = cgroup_write_node_int32(memcg, MEMCG_SIZE_LIMIT, -1); + ret = cgroup_write_node_int32(memcg, MEMCG_LIMIT_BYTE, -1); if (ret != RESOURCED_ERROR_NONE) _E("Not able to set hard limit of %s memory cgroup", memcg); @@ -337,14 +338,14 @@ static int swap_use_force_reclaim(char *memcg) bool root_memcg = false; /* - * In case of LOWMEM_ROOT_CGROUP, + * In case of MEMCG_PATH, * it is no necessary to check anon usage of memcg * because it doesn't include all memory usage. * But instead, try to swap memory as much as possible. * It will be happend only once after booting done. */ len = strlen(memcg); - if (!strncmp(memcg, LOWMEM_ROOT_CGROUP, len)) + if (!strncmp(memcg, MEMCG_PATH, len)) root_memcg = true; do { @@ -370,7 +371,7 @@ static int swap_use_force_reclaim(char *memcg) nr_to_reclaim = SWAP_RECLAIM_PAGES_MAX; total_reclaim += nr_to_reclaim; - ret = cgroup_write_node_uint32(memcg, SWAPCG_RECLAIM, + ret = cgroup_write_node_uint32(memcg, MEMCG_FORCE_RECLAIM, nr_to_reclaim); if (ret != RESOURCED_ERROR_NONE) break; /* if we can't reclaim don't continue */ @@ -387,7 +388,7 @@ static int swap_start_reclaim(char *memcg) int r; int swappiness; - r = cgroup_read_node_int32(memcg, MEMCG_SWAPPINESS_PATH, + r = cgroup_read_node_int32(memcg, MEMCG_SWAPPINESS, &swappiness); if (r) return r; @@ -401,10 +402,10 @@ static int swap_start_reclaim(char *memcg) */ if (swappiness != SWAP_MEMCG_SWAPPINESS) { r = cgroup_write_node_uint32(memcg, - MEMCG_SWAPPINESS_PATH, SWAP_MEMCG_SWAPPINESS); + MEMCG_SWAPPINESS, SWAP_MEMCG_SWAPPINESS); if (r) { _I("failed to write %s %d to %s the", - MEMCG_SWAPPINESS_PATH, SWAP_MEMCG_SWAPPINESS, memcg); + MEMCG_SWAPPINESS, SWAP_MEMCG_SWAPPINESS, memcg); return -errno; } } @@ -418,10 +419,10 @@ static int swap_start_reclaim(char *memcg) */ if (current_swappiness != SWAP_MEMCG_SWAPPINESS) { r = cgroup_write_node_uint32(memcg, - MEMCG_SWAPPINESS_PATH, current_swappiness); + MEMCG_SWAPPINESS, current_swappiness); if (r) { _I("failed to write %s %d to %s the", - MEMCG_SWAPPINESS_PATH, SWAP_MEMCG_SWAPPINESS, memcg); + MEMCG_SWAPPINESS, SWAP_MEMCG_SWAPPINESS, memcg); return -errno; } } @@ -464,12 +465,12 @@ static int swap_reclaim_memcg(struct swap_status_msg msg) * swap will be blocked with minimum swappiness. */ r = cgroup_read_node_int32(info->name, - MEMCG_SWAPPINESS_PATH, ¤t_swappiness); + MEMCG_SWAPPINESS, ¤t_swappiness); if (r) return r; r = cgroup_write_node_uint32(info->name, - MEMCG_SWAPPINESS_PATH, SWAP_MIN_SWAPPINESS); + MEMCG_SWAPPINESS, SWAP_MIN_SWAPPINESS); } return r; } @@ -652,8 +653,8 @@ static void swap_activate_in_module(void) struct swap_module_ops *swaps; static bool early_reclaim; - r = cgroup_read_node_int32(LOWMEM_ROOT_CGROUP, - MEMCG_SWAPPINESS_PATH, ¤t_swappiness); + r = cgroup_read_node_int32(MEMCG_PATH, + MEMCG_SWAPPINESS, ¤t_swappiness); if (r) return; @@ -702,16 +703,16 @@ static void swap_activate_in_module(void) int try = arg_swap_at_boot_maxtry; unsigned int usage, prev_usage = 0; - r = cgroup_read_node_uint32(LOWMEM_ROOT_CGROUP, + r = cgroup_read_node_uint32(MEMCG_PATH, MEMCG_SWAP_USAGE, &prev_usage); if (r) prev_usage = UINT_MAX; for (;;) { try--; - swap_start_reclaim(LOWMEM_ROOT_CGROUP); + swap_start_reclaim(MEMCG_PATH); - r = cgroup_read_node_uint32(LOWMEM_ROOT_CGROUP, + r = cgroup_read_node_uint32(MEMCG_PATH, MEMCG_SWAP_USAGE, &usage); if (r) { _E("Early reclaimed is aborted"); @@ -919,7 +920,7 @@ static int swap_cgroup_reset_limit(void *data) return RESOURCED_ERROR_NONE; limit = -1; - ret = cgroup_write_node_int32(msg->info->name, MEMCG_SIZE_LIMIT, limit); + ret = cgroup_write_node_int32(msg->info->name, MEMCG_LIMIT_BYTE, limit); if (ret != RESOURCED_ERROR_NONE) _E("Failed to change hard limit of %s cgroup to -1", msg->info->name); else @@ -1140,7 +1141,7 @@ static int resourced_swap_check_runtime_support(void *data) /* * Check whether kernel is supporting MEMCG_SWAP. */ - r = cgroup_read_node_uint32(LOWMEM_ROOT_CGROUP, + r = cgroup_read_node_uint32(MEMCG_PATH, MEMCG_SWAP_USAGE, &usage); if (r) return -ENOENT; @@ -1189,15 +1190,15 @@ static void resourced_swap_change_memcg_settings(enum memcg_type type) if (ret != RESOURCED_ERROR_NONE) return; - cgroup_write_node_uint32(memcg_swap->info->name, MOVE_CHARGE, 1); - snprintf(buf, sizeof(buf), "%s/%s", MEMCG_PATH, SWAPCG_RECLAIM); + cgroup_write_node_uint32(memcg_swap->info->name, MEMCG_MOVE_CHARGE, 1); + snprintf(buf, sizeof(buf), "%s/%s", MEMCG_PATH, MEMCG_FORCE_RECLAIM); ret = swap_check_node(buf); if (ret == RESOURCED_ERROR_NONE) { swap_node = SWAP_NODE_FORCE_RECLAIM; - _I("use %s node for swapping memory", SWAPCG_RECLAIM); + _I("use %s node for swapping memory", MEMCG_FORCE_RECLAIM); } else { swap_node = SWAP_NODE_HARD_LIMIT; - _I("use %s node for swapping memory", MEMCG_SIZE_LIMIT); + _I("use %s node for swapping memory", MEMCG_LIMIT_BYTE); } } diff --git a/src/resource-optimizer/memory/swap/zramswap.c b/src/resource-optimizer/memory/swap/zramswap.c index e179713..7fb188c 100644 --- a/src/resource-optimizer/memory/swap/zramswap.c +++ b/src/resource-optimizer/memory/swap/zramswap.c @@ -24,7 +24,7 @@ #include "file-helper.h" #include "procfs.h" #include "swap-common.h" -#include "memory-common.h" +#include "memory-cgroup.h" #include "config-parser.h" #include "lowmem-handler.h" @@ -226,7 +226,7 @@ static int swap_zram_reclaim(void *data) if (!swap_total) swap_total = proc_get_swap_total(); - r = memcg_get_swap_usage(LOWMEM_SWAP_CGROUP, &swap_usage); + r = memcg_get_swap_usage(MEMCG_SWAP_PATH, &swap_usage); if (r) return r; swapcg_usage_ratio = (float)(swap_usage / (swap_total - swap_available) *100); diff --git a/src/resource-optimizer/memory/swap/zswap.c b/src/resource-optimizer/memory/swap/zswap.c index daf183d..bae4dab 100644 --- a/src/resource-optimizer/memory/swap/zswap.c +++ b/src/resource-optimizer/memory/swap/zswap.c @@ -24,7 +24,7 @@ #include "file-helper.h" #include "procfs.h" #include "swap-common.h" -#include "memory-common.h" +#include "memory-cgroup.h" #include "config-parser.h" #include "lowmem-handler.h" #include "losetup.h" diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7e103b4..c7394c3 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -38,7 +38,9 @@ SET(CMAKE_LDFLAGS_RELEASE "") SET(UNIT_TESTS_CFLAGS "-O0 -D_UNIT_TEST -D_GNU_SOURCE ${GLIB2_CFLAGS}") SET(UNIT_TESTS_CFLAGS "${UNIT_TESTS_CFLAGS} -I${COMMON_SOURCE_DIR}") +SET(UNIT_TESTS_CFLAGS "${UNIT_TESTS_CFLAGS} -I${CGROUP_SOURCE_DIR}") SET(UNIT_TESTS_CFLAGS "${UNIT_TESTS_CFLAGS} -I${INCLUDE_COMMON_DIR}") +SET(UNIT_TESTS_CFLAGS "${UNIT_TESTS_CFLAGS} -I${INCLUDE_CGROUP_DIR}") SET(UNIT_TESTS_CFLAGS "${UNIT_TESTS_CFLAGS} -I${INCLUDE_PUBLIC_DIR}") SET(UNIT_TESTS_CFLAGS "${UNIT_TESTS_CFLAGS} -I${BLOCK_SOURCE_DIR}") SET(UNIT_TESTS_CFLAGS "${UNIT_TESTS_CFLAGS} -I${FREEZER_SOURCE_DIR}") @@ -116,10 +118,12 @@ function(ADD_MEMORY_TESTS name libs wraps sources) PRIVATE RD_CONFIG_PATH="." SYSTEM_LIB_PATH="/usr/lib" SWAP_SUPPORT RD_SYS_DB="." RD_SYS_DATA="." _UNIT_TEST) TARGET_INCLUDE_DIRECTORIES(${name} PRIVATE ${COMMON_SOURCE_DIR} + PRIVATE ${CGROUP_SOURCE_DIR} ../include ../src/resource-limiter/memory ../src/resourced ../src/common + ../src/common/cgroup PUBLIC ${RESOURCED_REQUIRE_PKGS_INCLUDE_DIRS}) TARGET_LINK_LIBRARIES(${name} cmocka pthread dl m gcov dlog ${libs}) ADD_TEST(${name} ${name}) diff --git a/tests/lowmem-dbus-test.cpp b/tests/lowmem-dbus-test.cpp index 70a190c..2d0e2e8 100644 --- a/tests/lowmem-dbus-test.cpp +++ b/tests/lowmem-dbus-test.cpp @@ -21,7 +21,7 @@ #include "cmocka-wrap.hpp" #include "lowmem-handler.h" -#include "memory-common.h" +#include "memory-cgroup.h" #include "procfs.h" #include diff --git a/tests/lowmem-limit-env.cpp b/tests/lowmem-limit-env.cpp index e8580ce..070247d 100644 --- a/tests/lowmem-limit-env.cpp +++ b/tests/lowmem-limit-env.cpp @@ -292,7 +292,7 @@ int LowmemLimitEnv::cgroup_write_node_uint32(const char *cgroup_name, const char const std::string fname = file_name; - if (fname == "/cgroup.procs") { + if (fname == "cgroup.procs") { cgroup_memory[std::string(cgroup_name)].pids.push_back(value); } else { cgroup_memory[std::string(cgroup_name)].files[fname] = std::to_string(value); @@ -300,6 +300,16 @@ int LowmemLimitEnv::cgroup_write_node_uint32(const char *cgroup_name, const char return 0; } +resourced_ret_c LowmemLimitEnv::cgroup_write_pid_fullpath(const char *cgroup_full_path, const int pid) +{ + std::cerr << " cgroup_full_path=" << cgroup_full_path << ", pid=" << pid << std::endl; + check_expected(cgroup_full_path); + check_expected(pid); + + cgroup_memory[std::string(cgroup_full_path)].pids.push_back(pid); + return RESOURCED_ERROR_NONE; +} + int LowmemLimitEnv::cgroup_read_node_uint32(const char *cgroup_name, const char *file_name, uint32_t *value) { std::cerr << " cgroup_name=" << cgroup_name << ", file_name=" << file_name << std::endl; @@ -350,7 +360,7 @@ int LowmemLimitEnv::cgroup_make_subdir(const char* parentdir, const char* cgroup {"memory.oom_control", "0"}, {"memory.memsw.limit_in_bytes", "0"}, {"memory.limit_in_bytes", "0"}, - {"/cgroup.procs", ""}, + {"cgroup.procs", ""}, {"memory.usage_in_bytes", "0"}, {"memory.memsw.usage_in_bytes", "0"} }}; diff --git a/tests/lowmem-limit-env.hpp b/tests/lowmem-limit-env.hpp index 8c34557..60d9c38 100644 --- a/tests/lowmem-limit-env.hpp +++ b/tests/lowmem-limit-env.hpp @@ -27,7 +27,7 @@ #include "config-parser.h" #include "fd-handler.h" #include "proc-common.h" -#include "memory-common.h" +#include "memory-cgroup.h" #include "resourced.h" #include "resourced-helper-worker.h" @@ -111,6 +111,9 @@ public: void make_memps_log(enum mem_log path, pid_t pid, char *victim_name); + resourced_ret_c cgroup_write_pid_fullpath(const char *cgroup_full_path, + const int pid); + int cgroup_get_pids(const char *name, GArray **pids); int cgroup_write_node_uint32(const char *cgroup_name, const char *file_name, uint32_t value); int cgroup_read_node_uint32(const char *cgroup_name, const char *file_name, uint32_t *value); diff --git a/tests/lowmem-limit-mock.cpp b/tests/lowmem-limit-mock.cpp index e03d1b0..d248c95 100644 --- a/tests/lowmem-limit-mock.cpp +++ b/tests/lowmem-limit-mock.cpp @@ -39,6 +39,9 @@ MOCK_LIMIT(proc_app_info *, find_app_info, (const pid_t pid), (pid)) MOCK_LIMIT(int, exec_cmd, (int argc, const char *argv[]), (argc, argv)) MOCK_LIMIT(void, make_memps_log, (enum mem_log path, pid_t pid, char *victim_name), (path, pid, victim_name)) +MOCK_LIMIT(resourced_ret_c, cgroup_write_pid_fullpath, + (const char *cgroup_full_path, const int pid), + (cgroup_full_path, pid)) MOCK_LIMIT(int, cgroup_get_pids, (const char *name, GArray **pids), (name, pids)) MOCK_LIMIT(int, cgroup_write_node_uint32, (const char *cgroup_name, const char *file_name, uint32_t value), diff --git a/tests/lowmem-limit-test.cpp b/tests/lowmem-limit-test.cpp index a4eade9..ab08a39 100644 --- a/tests/lowmem-limit-test.cpp +++ b/tests/lowmem-limit-test.cpp @@ -29,6 +29,13 @@ #include "lowmem-limit-env.hpp" +void expect_cgroup_write_pid_fullpath(const char *cgroup_full_path, const int pid) +{ + std::cerr << "expecting cgroup: " << cgroup_full_path << " " << " pid: " << pid << std::endl; + expect_string(cgroup_write_pid_fullpath, cgroup_full_path, cgroup_full_path); + expect_value(cgroup_write_pid_fullpath, pid, pid); +} + void expect_cgroup_write_uint32(const char *cgroup_name, const char *file_name, uint32_t val) { std::cerr << "expecting cgroup write: " << cgroup_name << " " << file_name << " " << val << std::endl; @@ -89,11 +96,13 @@ void app_test_prepare( } else { expect_cgroup_write_uint32(cg_name, "memory.limit_in_bytes", MEM_LIMIT*1.2); // increased by resourced } - expect_cgroup_write_uint32(cg_name, "/cgroup.procs", APP_PID); +// expect_cgroup_write_uint32(cg_name, "cgroup.procs", APP_PID); + expect_cgroup_write_pid_fullpath(cg_name, APP_PID); expect_cgroup_write_uint32(cg_name, "memory.move_charge_at_immigrate", 3U); for (const auto &u: usages) { if (u.first != APP_PID) - expect_cgroup_write_uint32(cg_name, "/cgroup.procs", u.first); + expect_cgroup_write_pid_fullpath(cg_name, u.first); + //expect_cgroup_write_uint32(cg_name, "cgroup.procs", u.first); } test_lowmem_limit_env.event_service_launch(APP_PID); diff --git a/tests/lowmem-system-test.cpp b/tests/lowmem-system-test.cpp index 7d434c4..18ad113 100644 --- a/tests/lowmem-system-test.cpp +++ b/tests/lowmem-system-test.cpp @@ -21,7 +21,7 @@ #include "cmocka-wrap.hpp" #include "lowmem-handler.h" -#include "memory-common.h" +#include "memory-cgroup.h" #include @@ -72,11 +72,11 @@ void expect_cgroup_write_node_uint32(const char *cgroup_name, const char *file_n void mock_search_systemd_cgroup(const char *dir, int32_t root_swappiness, int32_t dir_swappiness, const Subdirs &subdirs = Subdirs()) { - mock_cgroup_read_node_int32(LOWMEM_ROOT_CGROUP, MEMCG_SWAPPINESS_PATH, root_swappiness); - mock_cgroup_read_node_int32(dir, MEMCG_SWAPPINESS_PATH, dir_swappiness); + mock_cgroup_read_node_int32(MEMCG_PATH, MEMCG_SWAPPINESS, root_swappiness); + mock_cgroup_read_node_int32(dir, MEMCG_SWAPPINESS, dir_swappiness); if (root_swappiness >= 0 && root_swappiness != dir_swappiness) { - expect_cgroup_write_node_uint32(dir, MEMCG_SWAPPINESS_PATH, root_swappiness); + expect_cgroup_write_node_uint32(dir, MEMCG_SWAPPINESS, root_swappiness); } // subdirs @@ -85,9 +85,9 @@ void mock_search_systemd_cgroup(const char *dir, int32_t root_swappiness, int32_ // mock subdir will_return(readdir, subdir.get_subdir()); - mock_cgroup_read_node_uint32(subdir.get_subdir_full(), MEMCG_LIMIT_PATH, subdir.get_limit()); + mock_cgroup_read_node_uint32(subdir.get_subdir_full(), MEMCG_LIMIT_BYTE, subdir.get_limit()); if (subdir.get_limit() > 0) { - expect_cgroup_write_node_uint32(subdir.get_subdir_full(), MEMCG_SWAPPINESS_PATH, root_swappiness); + expect_cgroup_write_node_uint32(subdir.get_subdir_full(), MEMCG_SWAPPINESS, root_swappiness); expect_string(lowmem_reassign_limit, dir, subdir.get_subdir_full()); expect_value(lowmem_reassign_limit, limit, subdir.get_limit()); -- 2.7.4 From 31e6d320e7f05f5368ddc5fd2d05c26801322961 Mon Sep 17 00:00:00 2001 From: Unsung Lee Date: Tue, 28 Dec 2021 18:15:51 +0900 Subject: [PATCH 04/16] Separate notifiers Change-Id: Idb97d63a168a4026eb71c9d1b44977b09c2030bc Signed-off-by: Unsung Lee --- src/common/notifier.c | 57 ++++++++++++++++++++++++++++++++++----------------- tests/cmocka-core.c | 4 ++-- 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/common/notifier.c b/src/common/notifier.c index 61b85ee..d5e82b2 100644 --- a/src/common/notifier.c +++ b/src/common/notifier.c @@ -28,29 +28,34 @@ #include struct resourced_notifier { - enum notifier_type status; +// enum notifier_type status; int (*func)(void *data); }; -static GSList *resourced_notifier_list; +static GSList *resourced_notifier_list[RESOURCED_NOTIFIER_MAX]; -#define FIND_NOTIFIER(a, b, d, e, f) \ +#define FIND_NOTIFIER(a, b, d, f) \ gslist_for_each(a, b, d) \ - if (e == d->e && f == (d->f)) + if (f == (d->f)) int register_notifier(enum notifier_type status, int (*func)(void *data)) { GSList *n; struct resourced_notifier *notifier; - _D("%d, %p", status, func); if (!func) { _E("invalid func address!"); return -EINVAL; } - FIND_NOTIFIER(resourced_notifier_list, n, notifier, status, func) { + if(status >= RESOURCED_NOTIFIER_MAX || + status < RESOURCED_NOTIFIER_APP_LAUNCH) { + _E("invalid status!"); + return -EINVAL; + } + + FIND_NOTIFIER(resourced_notifier_list[status], n, notifier, func) { _E("function is already registered! [%d, %p]", status, func); return -EINVAL; @@ -62,11 +67,12 @@ int register_notifier(enum notifier_type status, int (*func)(void *data)) return -ENOMEM; } - notifier->status = status; +// notifier->status = status; notifier->func = func; - resourced_notifier_list = g_slist_append(resourced_notifier_list, notifier); + resourced_notifier_list[status] = g_slist_append(resourced_notifier_list[status], notifier); + _D("[status: %d] %p is registered", status, func); return 0; } @@ -80,13 +86,21 @@ int unregister_notifier(enum notifier_type status, int (*func)(void *data)) return -EINVAL; } - FIND_NOTIFIER(resourced_notifier_list, n, notifier, status, func) { + if(status >= RESOURCED_NOTIFIER_MAX || + status < RESOURCED_NOTIFIER_APP_LAUNCH) { + _E("invalid status!"); + return -EINVAL; + } + + FIND_NOTIFIER(resourced_notifier_list[status], n, notifier, func) { _I("[%d, %p]", status, func); - resourced_notifier_list = g_slist_remove(resourced_notifier_list, notifier); + resourced_notifier_list[status] = g_slist_remove(resourced_notifier_list[status], notifier); free(notifier); + return 0; } - return 0; + _E("[%d, %p] is not registered!", status, func); + return -EINVAL; } void resourced_notify(enum notifier_type status, void *data) @@ -94,12 +108,12 @@ void resourced_notify(enum notifier_type status, void *data) GSList *iter; struct resourced_notifier *notifier; - gslist_for_each_item(iter, resourced_notifier_list) { + gslist_for_each_item(iter, resourced_notifier_list[status]) { notifier = (struct resourced_notifier *)iter->data; - if (status == notifier->status) { +// if (status == notifier->status) { if (notifier->func) notifier->func(data); - } +// } } } @@ -107,14 +121,19 @@ static int notifier_exit(void *data) { GSList *iter; /* Deinitialize in reverse order */ - GSList *reverse_list = g_slist_reverse(resourced_notifier_list); struct resourced_notifier *notifier; - gslist_for_each_item(iter, reverse_list) { - notifier = (struct resourced_notifier *)iter->data; - resourced_notifier_list = g_slist_remove(resourced_notifier_list, notifier); - free(notifier); + for(int status = RESOURCED_NOTIFIER_APP_LAUNCH; + status < RESOURCED_NOTIFIER_MAX; status++) { + GSList *reverse_list = g_slist_reverse(resourced_notifier_list[status]); + gslist_for_each_item(iter, reverse_list) { + notifier = (struct resourced_notifier *)iter->data; + resourced_notifier_list[status] = + g_slist_remove(resourced_notifier_list[status], notifier); + free(notifier); + } } + return RESOURCED_ERROR_NONE; } diff --git a/tests/cmocka-core.c b/tests/cmocka-core.c index 71105fe..08826a1 100644 --- a/tests/cmocka-core.c +++ b/tests/cmocka-core.c @@ -42,7 +42,7 @@ GSList *__real_g_slist_append(GSList *list, gpointer data); GSList *__real_g_slist_remove(GSList *list, gconstpointer data); struct resourced_notifier { - enum notifier_type status; +// enum notifier_type status; noti_cb func; }; @@ -123,7 +123,7 @@ GSList *__wrap_g_slist_append(GSList *list, gpointer data) int t = mock_type(int); void *f = mock_ptr_type(void *); - assert(t == (int) notifier->status); +// assert(t == (int) notifier->status); assert(f == (void*) notifier->func); (void) t; -- 2.7.4 From f7badfe8d5bcbe7047586fc1ed783d1ba1e339e5 Mon Sep 17 00:00:00 2001 From: Unsung Lee Date: Fri, 31 Dec 2021 15:22:30 +0900 Subject: [PATCH 05/16] Modify CPU cgroup hierarchy /sys/fs/cgroup/cpu/high/medium/low /tizendocker Change-Id: I67160165e21149353f0f3acda9048e214df1c8f2 Signed-off-by: Unsung Lee --- src/common/cgroup/cgroup.c | 67 ++++++++++++++++++++++++++++++++++++- src/common/cgroup/cgroup.h | 26 ++++++++++++++- src/common/cgroup/cpu-cgroup.h | 24 ++++++++----- src/process/proc-main.c | 16 +++++++++ src/resource-limiter/cpu/cpu.c | 76 +++++++++++++++++++----------------------- 5 files changed, 157 insertions(+), 52 deletions(-) diff --git a/src/common/cgroup/cgroup.c b/src/common/cgroup/cgroup.c index 16476a6..f597fe8 100644 --- a/src/common/cgroup/cgroup.c +++ b/src/common/cgroup/cgroup.c @@ -44,9 +44,32 @@ #include #include -#define RELEASE_AGENT "release_agent" +#define RELEASE_AGENT "release_agent" #define NOTIFY_ON_RELEASE "notify_on_release" +#define MAKE_NAME(name) CGROUP_##name##_NAME +#define cgroup_name_cpy(dst, src, length) \ + do { \ + bool success = sizeof(dst) >= length ? true : false; \ + if(success) { \ + strncpy(dst, src, sizeof(dst) - 1); \ + } \ + else { \ + return RESOURCED_ERROR_OUT_OF_MEMORY; \ + } \ + } while(0) + +#define cgroup_name_cat(dst, src, length) \ + do { \ + bool success = sizeof(dst) >= strlen(dst) + length ? true : false; \ + if(success) { \ + strncat(dst, src, sizeof(dst) - strlen(dst) - 1); \ + } \ + else { \ + return RESOURCED_ERROR_OUT_OF_MEMORY; \ + } \ + } while(0) + static bool cgroup_is_exists(const char *cgroup_full_path) { struct stat stat_buf; @@ -169,6 +192,48 @@ int cgroup_read_node_int32(const char *cgroup_name, return ret; } +int cgroup_make_full_subdir(const char* parentdir) +{ + int result; + char path[MAX_PATH_LENGTH] = {0, }; + + cgroup_name_cpy(path, parentdir, strlen(parentdir) + 1); + + for(int i = CGROUP_VIP; i < CGROUP_END; i++) { + char name[MAX_NAME_LENGTH] = {0, }; + + if(i == CGROUP_VIP) { + cgroup_name_cpy(name, MAKE_NAME(VIP), strlen(MAKE_NAME(VIP))+ 1); + } + else if(i == CGROUP_HIGH) { + cgroup_name_cpy(name, MAKE_NAME(HIGH), strlen(MAKE_NAME(HIGH))+ 1); + } + else if(i == CGROUP_MEDIUM) { + cgroup_name_cpy(name, MAKE_NAME(MEDIUM), strlen(MAKE_NAME(MEDIUM))+ 1); + } + else if(i == CGROUP_LOW) { + cgroup_name_cpy(name, MAKE_NAME(LOW), strlen(MAKE_NAME(LOW))+ 1); + } + + result = cgroup_make_subdir(path, name, NULL); + ret_value_msg_if(result < 0, result, "%s/%s init failed\n", path, name); + + cgroup_name_cat(path, "/", 2); + cgroup_name_cat(path, name, strlen(name) + 1); + + // ../../perprocess + result = cgroup_make_subdir(path, MAKE_NAME(PER_PROCESS), NULL); + ret_value_msg_if(result < 0, result, "%s/%s init failed\n", + path, MAKE_NAME(PER_PROCESS)); + // ../../group + result = cgroup_make_subdir(path, MAKE_NAME(GROUP), NULL); + ret_value_msg_if(result < 0, result, "%s/%s init failed\n", + path, MAKE_NAME(GROUP)); + } + + return RESOURCED_ERROR_NONE; +} + int cgroup_make_subdir(const char* parentdir, const char* cgroup_name, bool *already) { char buf[MAX_PATH_LENGTH]; diff --git a/src/common/cgroup/cgroup.h b/src/common/cgroup/cgroup.h index 7cec0ca..8991553 100644 --- a/src/common/cgroup/cgroup.h +++ b/src/common/cgroup/cgroup.h @@ -39,9 +39,26 @@ extern "C" { #define TASK_FILE_NAME "tasks" #define CGROUP_FILE_NAME "cgroup.procs" -//#define DEFAULT_CGROUP "/sys/fs/cgroup" #define CGROUP_PATH "/sys/fs/cgroup" +#define CGROUP_VIP_NAME "" +#define CGROUP_HIGH_NAME "High" +#define CGROUP_MEDIUM_NAME "Medium" +#define CGROUP_LOW_NAME "Lowest" + +#define CGROUP_PER_PROCESS_NAME "" +#define CGROUP_GROUP_NAME "" + +enum cgroup_type { + CGROUP_TOP = -1, + CGROUP_ROOT, + CGROUP_VIP, + CGROUP_HIGH, + CGROUP_MEDIUM, + CGROUP_LOW, + CGROUP_END, +}; + /** * @desc Get one unsigned int32 value from cgroup * @param cgroup_name - cgroup path @@ -91,6 +108,13 @@ int cgroup_write_node_str(const char *cgroup_name, const char *file_name, const char *string); /** + * @desc make full cgroup, + * @param parentdir - parent cgroup path + * @return negative value if error + */ +int cgroup_make_full_subdir(const char* parentdir); + +/** * @desc make cgroup, * @param parentdir - parent cgroup path * @param cgroup_name - cgroup subdirectory to write diff --git a/src/common/cgroup/cpu-cgroup.h b/src/common/cgroup/cpu-cgroup.h index 8b36e34..53a7ffa 100644 --- a/src/common/cgroup/cpu-cgroup.h +++ b/src/common/cgroup/cpu-cgroup.h @@ -29,20 +29,26 @@ extern "C" { #endif /* __cplusplus */ -#define CPUCG_PATH "/sys/fs/cgroup/cpu" -#define CPUCG_BACKGROUND_PATH CPUCG_PATH"/background" -#define CPUCG_QUOTA_PATH CPUCG_PATH"/quota" +#define CPUCG_PATH CGROUP_PATH "/cpu" +#define CPUCG_VIP_PATH CPUCG_PATH "/" CGROUP_VIP_NAME +#define CPUCG_HIGH_PATH CPUCG_PATH "/" CGROUP_VIP_NAME "/" CGROUP_HIGH_NAME +#define CPUCG_MEDIUM_PATH CPUCG_PATH "/" CGROUP_VIP_NAME "/" CGROUP_HIGH_NAME "/" CGROUP_MEDIUM_NAME +#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_SHARE "cpu.shares" -/*#define CPU_DEFAULT_CGROUP "/sys/fs/cgroup/cpu" -#define CPU_BACKGROUND_GROUP CPU_DEFAULT_CGROUP"/background" -#define CPU_CPUQUOTA_GROUP CPU_DEFAULT_CGROUP"/quota" -#define CPU_CONTROL_BANDWIDTH "cpu.cfs_quota_us" -#define CPU_CONTROL_FULL_BANDWIDTH "cpu.cfs_period_us" -#define CPU_SHARE "cpu.shares"*/ +#define CPUCG_VIP_PP_PATH CPUCG_VIP_PATH"/"CGROUP_PER_PROCESS_NAME +#define CPUCG_VIP_GROUP_PATH CPUCG_VIP_PATH"/"CGROUP_GROUP_NAME +#define CPUCG_HIGH_PP_PATH CPUCG_HIGH_PATH"/"CGROUP_PER_PROCESS_NAME +#define CPUCG_HIGH_GROUP_PATH CPUCG_HIGH_PATH"/"CGROUP_GROUP_NAME + +#define CPUCG_MEDIUM_PP_PATH CPUCG_MEDIUM_PATH"/"CGROUP_PER_PROCESS_NAME +#define CPUCG_MEDIUM_GROUP_PATH CPUCG_MEDIUM_PATH"/"CGROUP_GROUP_NAME + +#define CPUCG_LOW_PP_PATH CPUCG_LOW_PATH"/"CGROUP_PER_PROCESS_NAME +#define CPUCG_LOW_GROUP_PATH CPUCG_LOW_PATH"/"CGROUP_GROUP_NAME #ifdef __cplusplus } diff --git a/src/process/proc-main.c b/src/process/proc-main.c index 1845a26..6121d52 100644 --- a/src/process/proc-main.c +++ b/src/process/proc-main.c @@ -1452,6 +1452,19 @@ enum proc_state proc_check_suspend_state(struct proc_app_info *pai) return PROC_STATE_DEFAULT; } +/*static const char *convert_status_to_str(int status) +{ + static const char *set[] = {"foreground", "active", "backround", + "inactive", "launch", "resume", "terminate", + "service", "noti", "exclude", "memsweep", "terminated", + "system_service", "cmdline", "exe", "stat", "status", + "oomscore", "pgid_cmdline"}; + if(status < PROC_CGROUP_SET_FOREGRD || status > PROC_CGROUP_GET_PGID_CMDLINE) + return "error status"; + else + return set[status]; +}*/ + int resourced_proc_status_change(int status, pid_t pid, char *app_name, char *pkg_name, int apptype) { @@ -1475,6 +1488,9 @@ int resourced_proc_status_change(int status, pid_t pid, char *app_name, char *pk ps.pid = pid; ps.pai = NULL; + + //_E("status: %s, app_name: %s, pid: %d, oom_score: %d", convert_status_to_str(status), app_name, pid, oom_score_adj); + switch (status) { case PROC_CGROUP_SET_FOREGRD: if (app_name) diff --git a/src/resource-limiter/cpu/cpu.c b/src/resource-limiter/cpu/cpu.c index 36c27dd..680c87e 100644 --- a/src/resource-limiter/cpu/cpu.c +++ b/src/resource-limiter/cpu/cpu.c @@ -47,24 +47,17 @@ #include "file-helper.h" #include "cpu-cgroup.h" -/*#define CPUCG_PATH "/sys/fs/cgroup/cpu" -#define CPUCG_BACKGROUND_PATH CPUCG_PATH"/background" -#define CPUCG_QUOTA_PATH CPUCG_PATH"/quota" -#define CPUCG_CONTROL_BANDWIDTH "cpu.cfs_quota_us" -#define CPUCG_CONTROL_FULL_BANDWIDTH "cpu.cfs_period_us" -#define CPU_SHARE "cpu.shares"*/ - -#define CPU_CONF_FILE RD_CONFIG_FILE(cpu) -#define CPU_CONF_SECTION "CONTROL" -#define CPU_CONF_PREDEFINE "PREDEFINE" -#define CPU_CONF_BOOTING "BOOTING_PREDEFINE" -#define CPU_CONF_WRT "WRT_PREDEFINE" -#define CPU_CONF_LAZY "LAZY_PREDEFINE" -#define MAX_PREDEFINED_TASKS 10 +#define CPU_CONF_FILE RD_CONFIG_FILE(cpu) +#define CPU_CONF_SECTION "CONTROL" +#define CPU_CONF_PREDEFINE "PREDEFINE" +#define CPU_CONF_BOOTING "BOOTING_PREDEFINE" +#define CPU_CONF_WRT "WRT_PREDEFINE" +#define CPU_CONF_LAZY "LAZY_PREDEFINE" +#define MAX_PREDEFINED_TASKS 10 #define CPU_TIMER_INTERVAL 30 -#define CPU_DEFAULT_PRI 0 -#define CPU_BACKGROUND_PRI 1 -#define CPU_CONTROL_PRI 10 +#define CPU_DEFAULT_PRI 0 +#define CPU_BACKGROUND_PRI 1 +#define CPU_CONTROL_PRI 10 static GSource *cpu_predefined_timer; static bool bCPUQuota; @@ -187,7 +180,7 @@ static int load_cpu_config(struct parse_result *result, void *user_data) if (!strncmp(result->name, CPU_CONF_PREDEFINE, strlen(CPU_CONF_PREDEFINE)+1)) { pid = find_pid_from_cmdline(result->value); if (pid > 0) { - cpu_move_cgroup(pid, CPUCG_BACKGROUND_PATH); + cpu_move_cgroup(pid, CPUCG_MEDIUM_GROUP_PATH); def_list.control[def_list.num].pid = pid; def_list.control[def_list.num++].type = SET_DEFAUT; } else { @@ -196,7 +189,7 @@ static int load_cpu_config(struct parse_result *result, void *user_data) } else if (!strncmp(result->name, CPU_CONF_BOOTING, strlen(CPU_CONF_BOOTING)+1)) { pid = find_pid_from_cmdline(result->value); if (pid > 0) { - cpu_move_cgroup(pid, CPUCG_BACKGROUND_PATH); + cpu_move_cgroup(pid, CPUCG_MEDIUM_GROUP_PATH); def_list.control[def_list.num].pid = pid; def_list.control[def_list.num++].type = SET_BOOTING; setpriority(PRIO_PROCESS, pid, CPU_BACKGROUND_PRI); @@ -204,7 +197,7 @@ static int load_cpu_config(struct parse_result *result, void *user_data) } else if (!strncmp(result->name, CPU_CONF_WRT, strlen(CPU_CONF_WRT)+1)) { pid = find_pid_from_cmdline(result->value); if (pid > 0) { - cpu_move_cgroup(pid, CPUCG_BACKGROUND_PATH); + cpu_move_cgroup(pid, CPUCG_MEDIUM_GROUP_PATH); def_list.control[def_list.num].pid = pid; def_list.control[def_list.num++].type = SET_WRT; setpriority(PRIO_PROCESS, pid, CPU_CONTROL_PRI); @@ -219,18 +212,18 @@ static int load_cpu_config(struct parse_result *result, void *user_data) } else if (!strncmp(result->name, "BACKGROUND_CPU_SHARE", strlen("BACKGROUND_CPU_SHARE")+1)) { value = atoi(result->value); if (value) - cgroup_write_node_uint32(CPUCG_BACKGROUND_PATH, CPUCG_SHARE, + cgroup_write_node_uint32(CPUCG_MEDIUM_PATH, CPUCG_SHARE, get_relative_value(CPUCG_PATH, CPUCG_SHARE, value)); } else if (!strncmp(result->name, "QUOTA_CPU_SHARE", strlen("QUOTA_CPU_SHARE")+1)) { value = atoi(result->value); if (value && cpu_quota_enabled()) - cgroup_write_node_uint32(CPUCG_QUOTA_PATH, CPUCG_SHARE, + cgroup_write_node_uint32(CPUCG_LOW_PATH, CPUCG_SHARE, get_relative_value(CPUCG_PATH, CPUCG_SHARE, value)); } else if (!strncmp(result->name, "QUOTA_MAX_BANDWIDTH", strlen("QUOTA_MAX_BANDWIDTH")+1)) { value = atoi(result->value); if (value && cpu_quota_enabled()) - cgroup_write_node_uint32(CPUCG_QUOTA_PATH, CPUCG_CONTROL_BANDWIDTH, - get_relative_value(CPUCG_QUOTA_PATH, + cgroup_write_node_uint32(CPUCG_LOW_PATH, CPUCG_CONTROL_BANDWIDTH, + get_relative_value(CPUCG_LOW_PATH, CPUCG_CONTROL_FULL_BANDWIDTH, value)); } @@ -249,7 +242,7 @@ static int cpu_service_state(void *data) CHECK_BIT(ps->pai->categories, PROC_BG_MEDIA)) return RESOURCED_ERROR_NONE; - cpu_move_cgroup(ps->pid, CPUCG_BACKGROUND_PATH); + cpu_move_cgroup(ps->pid, CPUCG_MEDIUM_GROUP_PATH); return RESOURCED_ERROR_NONE; } @@ -261,7 +254,7 @@ static int cpu_widget_state(void *data) _D("widget background: pid = %d, appname = %s", ps->pid, ps->pai->appid); if (CHECK_BIT(ps->pai->flags, PROC_DOWNLOADAPP)) - cpu_move_cgroup(ps->pid, CPUCG_BACKGROUND_PATH); + cpu_move_cgroup(ps->pid, CPUCG_MEDIUM_GROUP_PATH); return RESOURCED_ERROR_NONE; } @@ -276,7 +269,7 @@ static int cpu_foreground_state(void *data) if (pri == -1 || pri > CPU_DEFAULT_PRI) setpriority(PRIO_PGRP, ps->pid, CPU_DEFAULT_PRI); if (check_predefined(ps->pid) != SET_DEFAUT) - cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_PATH); + cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_HIGH_GROUP_PATH); return RESOURCED_ERROR_NONE; } @@ -287,7 +280,7 @@ static int cpu_background_state(void *data) _D("app background: pid = %d", ps->pid); setpriority(PRIO_PGRP, ps->pid, CPU_BACKGROUND_PRI); - cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_BACKGROUND_PATH); + cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_MEDIUM_GROUP_PATH); return RESOURCED_ERROR_NONE; } @@ -304,7 +297,7 @@ static int cpu_restrict_state(void *data) return RESOURCED_ERROR_NONE; _D("app suspend: pid = %d, appname = %s", ps->pid, ps->pai->appid); - cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_QUOTA_PATH); + cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_LOW_GROUP_PATH); return RESOURCED_ERROR_NONE; } @@ -318,7 +311,7 @@ static int cpu_active_state(void *data) ret = proc_get_oom_score_adj(ps->pid, &oom_score_adj); if (ret || oom_score_adj < OOMADJ_PREVIOUS_DEFAULT) return RESOURCED_ERROR_NONE; - cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_PATH); + cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_HIGH_GROUP_PATH); return RESOURCED_ERROR_NONE; } @@ -333,7 +326,7 @@ static int cpu_prelaunch_state(void *data) if (ps->pai->type & PROC_WEBAPP) { for (i = 0; i < def_list.num; i++) { if (def_list.control[i].type == SET_WRT) { - cpu_move_cgroup(def_list.control[i].pid, CPUCG_PATH); + cpu_move_cgroup(def_list.control[i].pid, CPUCG_HIGH_GROUP_PATH); setpriority(PRIO_PGRP, def_list.control[i].pid, 0); ioprio_set(IOPRIO_WHO_PROCESS, def_list.control[i].pid, IOPRIO_CLASS_BE << IOPRIO_CLASS_SHIFT); return RESOURCED_ERROR_NONE; @@ -349,7 +342,7 @@ static int cpu_system_state(void *data) assert(ps); _D("system service : pid = %d", ps->pid); - cpu_move_cgroup(ps->pid, CPUCG_BACKGROUND_PATH); + cpu_move_cgroup(ps->pid, CPUCG_MEDIUM_GROUP_PATH); return RESOURCED_ERROR_NONE; } @@ -358,7 +351,7 @@ static int cpu_terminatestart_state(void *data) struct proc_status *ps = (struct proc_status *)data; assert(ps); - cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_PATH); + cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_HIGH_GROUP_PATH); return RESOURCED_ERROR_NONE; } @@ -368,9 +361,9 @@ static int cpu_exclude_state(void *data) if (check_predefined(pe->pid) == SET_DEFAUT) return RESOURCED_ERROR_NONE; if (pe->type == PROC_INCLUDE) - cpu_move_cgroup(pe->pid, CPUCG_BACKGROUND_PATH); + cpu_move_cgroup(pe->pid, CPUCG_MEDIUM_GROUP_PATH); else - cpu_move_cgroup(pe->pid, CPUCG_PATH); + cpu_move_cgroup(pe->pid, CPUCG_HIGH_GROUP_PATH); return RESOURCED_ERROR_NONE; } @@ -380,12 +373,12 @@ static gboolean cpu_predefined_cb(gpointer data) for (i = 0; i < def_list.num; i++) { if (def_list.control[i].type == SET_LAZY) { - cpu_move_cgroup(def_list.control[i].pid, CPUCG_BACKGROUND_PATH); + cpu_move_cgroup(def_list.control[i].pid, CPUCG_MEDIUM_GROUP_PATH); } else if (def_list.control[i].type == SET_BOOTING) { - cpu_move_cgroup(def_list.control[i].pid, CPUCG_PATH); + cpu_move_cgroup(def_list.control[i].pid, CPUCG_HIGH_GROUP_PATH); setpriority(PRIO_PROCESS, def_list.control[i].pid, 0); } else if (def_list.control[i].type == SET_WRT) { - cpu_move_cgroup(def_list.control[i].pid, CPUCG_PATH); + cpu_move_cgroup(def_list.control[i].pid, CPUCG_HIGH_GROUP_PATH); setpriority(PRIO_PROCESS, def_list.control[i].pid, 0); ioprio_set(IOPRIO_WHO_PROCESS, def_list.control[i].pid, IOPRIO_CLASS_BE << IOPRIO_CLASS_SHIFT); } @@ -400,13 +393,14 @@ static int resourced_cpu_init(void *data) int ret_code; _D("resourced_cpu_init"); - ret_code = cgroup_make_subdir(CPUCG_PATH, "background", NULL); + //ret_code = cgroup_make_subdir(CPUCG_PATH, "background", NULL); + ret_code = cgroup_make_full_subdir(CPUCG_PATH); ret_value_msg_if(ret_code < 0, ret_code, "cpu init failed\n"); cpu_check_cpuquota(); - if (cpu_quota_enabled()) { +/* if (cpu_quota_enabled()) { ret_code = cgroup_make_subdir(CPUCG_PATH, "quota", NULL); ret_value_msg_if(ret_code < 0, ret_code, "create service cgroup failed\n"); - } + }*/ config_parse(CPU_CONF_FILE, load_cpu_config, NULL); if (def_list.num) { -- 2.7.4 From 059373c68200811e93963d9313ca3b043a57d465 Mon Sep 17 00:00:00 2001 From: Unsung Lee Date: Fri, 7 Jan 2022 15:12:39 +0900 Subject: [PATCH 06/16] Modify cgroup structure Modify memory cgroup hierarchy and memory cgroup structure Add cgroup(common) structure Change-Id: I4fb03e9e52ef700069ed0d3102d04b0d5cd59205 Signed-off-by: Unsung Lee --- src/common/cgroup/cgroup.c | 172 ++++---- src/common/cgroup/cgroup.h | 52 +++ src/common/cgroup/memory-cgroup.c | 389 +++++++++++++++++ src/common/cgroup/memory-cgroup.h | 93 ++-- src/common/swap-common.h | 4 +- src/resource-limiter/cpu/cpu.c | 4 +- src/resource-limiter/memory/lowmem-dbus.c | 8 +- src/resource-limiter/memory/lowmem-handler.h | 11 +- src/resource-limiter/memory/lowmem-limit.c | 10 +- src/resource-limiter/memory/memcontrol.c | 162 ------- .../memory/vmpressure-lowmem-handler.c | 474 ++++++++++----------- src/resource-optimizer/memory/swap/swap.c | 79 ++-- src/resource-optimizer/memory/swap/zramswap.c | 2 +- tests/CMakeLists.txt | 10 +- tests/lowmem-dbus-env.cpp | 4 +- tests/lowmem-dbus-env.hpp | 4 +- tests/lowmem-dbus-mock.cpp | 4 +- tests/lowmem-dbus-test.cpp | 38 +- tests/lowmem-limit-env.cpp | 4 +- tests/lowmem-limit-env.hpp | 2 +- tests/lowmem-limit-test.cpp | 4 +- 21 files changed, 899 insertions(+), 631 deletions(-) create mode 100644 src/common/cgroup/memory-cgroup.c delete mode 100644 src/resource-limiter/memory/memcontrol.c diff --git a/src/common/cgroup/cgroup.c b/src/common/cgroup/cgroup.c index f597fe8..64d99f2 100644 --- a/src/common/cgroup/cgroup.c +++ b/src/common/cgroup/cgroup.c @@ -47,6 +47,7 @@ #define RELEASE_AGENT "release_agent" #define NOTIFY_ON_RELEASE "notify_on_release" + #define MAKE_NAME(name) CGROUP_##name##_NAME #define cgroup_name_cpy(dst, src, length) \ do { \ @@ -70,6 +71,98 @@ } \ } while(0) +/* + * This structure has full hierarchy of cgroups on running system. + * It is exported through lowmem-handler.h file. + **/ +static struct cgroup cgroup_tree[CGROUP_END] = { + {"/", CGROUP_TOP, CGROUP_DEFAULT_USE_HIERARCHY, NULL, NULL}, + {CGROUP_VIP_NAME, CGROUP_ROOT, CGROUP_DEFAULT_USE_HIERARCHY, NULL, NULL}, + {CGROUP_HIGH_NAME, CGROUP_VIP, CGROUP_DEFAULT_USE_HIERARCHY, NULL, NULL}, + {CGROUP_MEDIUM_NAME, CGROUP_HIGH, CGROUP_DEFAULT_USE_HIERARCHY, NULL, NULL}, + {CGROUP_LOW_NAME, CGROUP_MEDIUM, CGROUP_DEFAULT_USE_HIERARCHY, NULL, NULL}, +}; + +//static struct cgroup **cgroup_tree; + +/*static void cgroup_init(struct cgroup *cgroup) +{ + cgroup->use_hierarchy = MEMCG_DEFAULT_USE_HIERARCHY; + cgroup->memcg_info = NULL; + cgroup->cgroups = NULL; +}*/ + +struct cgroup *get_cgroup_tree(int idx) +{ + if(idx < CGROUP_ROOT || idx >= CGROUP_END) { + _E("(%d) cgroup tree is NULL", idx); + return NULL; + } + else + return &cgroup_tree[idx]; +} + +void set_memcg_info(int idx, struct memcg_info *mi) +{ + if(idx < CGROUP_ROOT || idx >= CGROUP_END) { + _E("(%d) index is out of scope", idx); + } + else + cgroup_tree[idx].memcg_info = mi; +} + +struct memcg_info *get_memcg_info(int idx) +{ + if(idx < CGROUP_ROOT || idx >= CGROUP_END) { + _E("(%d) cgroup tree's memcg info is NULL", idx); + return NULL; + } + else + return cgroup_tree[idx].memcg_info; +} + +GSList *get_child_cgroups(int idx) +{ + if(idx < CGROUP_ROOT || idx >= CGROUP_END) { + _E("(%d) cgroup tree's child is NULL", idx); + return NULL; + } + else + return cgroup_tree[idx].child_cgroups; +} + +int get_parent_cgroup(int idx) +{ + if(idx < CGROUP_ROOT || idx >= CGROUP_END) { + _E("(%d) cgroup range is out of scope", idx); + return CGROUP_TOP; + } + else { + return cgroup_tree[idx].parent_cgroup; + } +} + +void set_use_hierarchy(int idx, bool use_hierarchy) +{ + if(idx < CGROUP_ROOT || idx >= CGROUP_END) { + _E("(%d) cgroup range is out of scope", idx); + } + else { + cgroup_tree[idx].use_hierarchy = use_hierarchy; + } +} + +bool get_use_hierarchy(int idx) +{ + if(idx < CGROUP_ROOT || idx >= CGROUP_END) { + _E("(%d) cgroup range is out of scope", idx); + return CGROUP_DEFAULT_USE_HIERARCHY; + } + else { + return cgroup_tree[idx].use_hierarchy; + } +} + static bool cgroup_is_exists(const char *cgroup_full_path) { struct stat stat_buf; @@ -358,85 +451,6 @@ int cgroup_pid_get_path(const char *controller, pid_t pid, char **path) return 0; } -static void cgroup_memory_stat_init(struct cgroup_memory_stat *mem_stat, long long val) -{ - enum cgroup_memory_stat_id id; - - assert(mem_stat); - - for (id = 0; id < CGROUP_MEMORY_STAT_MAX; id++) - mem_stat->value[id] = val; -} - -int cgroup_get_memory_stat(const char *name, struct cgroup_memory_stat **mem_stat) -{ - _cleanup_fclose_ FILE *f = NULL; - struct cgroup_memory_stat *st; - char p[PATH_MAX] = ""; - char buf[LINE_MAX]; - const char *memory_stat = "memory.stat"; - const int memory_stat_len = strlen(memory_stat); - - if (name) { - int l; - int name_len = strlen(name); - - if (strneq(name, MEMCG_PATH, strlen(MEMCG_PATH))) - l = snprintf(p, PATH_MAX, "%s", name); - else - l = snprintf(p, PATH_MAX, "%s%s%s", - MEMCG_PATH, - name[0] != '/' ? "/" : "", - name); - - if (name_len >= memory_stat_len && - memcmp(name + name_len - memory_stat_len, memory_stat, memory_stat_len)) - snprintf(p + l, PATH_MAX - l, "%s%s", - p[l - 1] != '/' ? "/" : "", - memory_stat); - } else - snprintf(p, PATH_MAX, "%s/%s", MEMCG_PATH, memory_stat); - - f = fopen(p, "re"); - if (!f) - return -errno; - - st = (struct cgroup_memory_stat *)malloc(sizeof(struct cgroup_memory_stat)); - if (!st) - return -ENOMEM; - - cgroup_memory_stat_init(st, -1); - - for (;;) { - enum cgroup_memory_stat_id id; - size_t l; - - if (!fgets(buf, sizeof(buf), f)) { - if (ferror(f)) { - free(st); - return -errno; - } - break; - } - - l = strcspn(buf, " "); - if (!l) - break; - - buf[l] = 0; - - id = cgroup_memory_stat_string_to_id(buf); - if (id < 0 || id >= CGROUP_MEMORY_STAT_MAX) - continue; - - st->value[id] = atoll(buf + l + 1); - } - - *mem_stat = st; - - return 0; -} - /* * Usage example: * int i; diff --git a/src/common/cgroup/cgroup.h b/src/common/cgroup/cgroup.h index 8991553..25ec742 100644 --- a/src/common/cgroup/cgroup.h +++ b/src/common/cgroup/cgroup.h @@ -23,6 +23,7 @@ #include #include #include +#include "const.h" #include "macro.h" /* @@ -49,6 +50,32 @@ extern "C" { #define CGROUP_PER_PROCESS_NAME "" #define CGROUP_GROUP_NAME "" +#define CGROUP_DEFAULT_USE_HIERARCHY false +/* + * [cgroup information] + * CGROUP_ROOT : root cgroup + * CGROUP_VIP : cgroup for vip apps(or daemons) + * CGROUP_HIGH : cgroup for foreground apps + * CGROUP_MEDIUM : cgroup for background apps + * CGROUP_LOW : cgroup for apps of the lowest privilege + * + * [cgroup hierarchy] + * (normal mode) + root(cpu, memory, io) + * ├─high─(tizendocker) + * │ └─medium + * │ └─low + * └─system.slice/user.slice (not controlled by resourced) + * + * (vip mode) + root(cpu, memory, io) + * │ + * vip + * ├─high─(tizendocker) + * │ └─medium + * │ └─low + * └─system.slice/user.slice (not controlled by resourced) + */ enum cgroup_type { CGROUP_TOP = -1, CGROUP_ROOT, @@ -59,6 +86,19 @@ enum cgroup_type { CGROUP_END, }; +struct cgroup { + /* hashname of memory cgroup for restoring memcg info*/ + char hashname[MAX_NAME_LENGTH]; + /* parent cgroup index */ + int parent_cgroup; + /* set when using multiple sub cgroups */ + bool use_hierarchy; + /* memory cgroup information */ + struct memcg_info *memcg_info; + /* list of child cgroups when using multi groups */ + GSList *child_cgroups; +}; + /** * @desc Get one unsigned int32 value from cgroup * @param cgroup_name - cgroup path @@ -183,6 +223,18 @@ int cgroup_pid_get_path(const char *controller, pid_t pid, char **path); */ int cgroup_get_pids(const char *name, GArray **pids); + +struct cgroup *get_cgroup_tree(int idx); +void set_memcg_info(int idx, struct memcg_info *mi); +struct memcg_info *get_memcg_info(int idx); +GSList *get_child_cgroups(int idx); +int get_parent_cgroup(int idx); +void set_use_hierarchy(int idx, bool use_hierarchy); +bool get_use_hierarchy(int idx); + +//void cgroup_params_exit(void); +void cgroup_params_init(void); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/common/cgroup/memory-cgroup.c b/src/common/cgroup/memory-cgroup.c new file mode 100644 index 0000000..ae1d946 --- /dev/null +++ b/src/common/cgroup/memory-cgroup.c @@ -0,0 +1,389 @@ +/* + * resourced + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file memcontrol.c + * + * @desc structure and operation for memory cgroups + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "resourced.h" +#include "trace.h" +#include "macro.h" +#include "memory-cgroup.h" +#include "cgroup.h" +#include "module.h" +#include "util.h" + +#include + +#define BUF_MAX 1023 +#define MEMCG_NO_LIMIT 0 + +static int default_swappiness = -1; + +/* + * Special node that point's to /sys/fs/cgroup/memory - root of memcg group. + * This is the same as memcg_tree[CGROUP_ROOT]->info. + */ +static struct memcg_info *memcg_root; + +static struct memcg_info gmemcg_info[CGROUP_END] = { + {MEMCG_PATH,}, + {MEMCG_VIP_PATH,}, + {MEMCG_HIGH_PATH,}, + {MEMCG_MEDIUM_PATH,}, + {MEMCG_LOW_PATH,}, +}; + +static int memcg_write_params_info(struct memcg_info *mi) +{ + unsigned int limit = mi->limit; + const char *name = mi->name; + int ret = RESOURCED_ERROR_NONE; + int swappiness = -1; + _I("write memcg param for %s", name); + /* enable cgroup move */ + ret = cgroup_write_node_uint32(name, + MEMCG_MOVE_CHARGE, 3); + if (ret) + return ret; + + /* + * write swapness if it has a meaningful value. + * if it has own swappiness value, set it to memcg at first. + * otherwise, check default_swappiness value and use it. + */ + if (mi->swappiness >= 0) + swappiness = mi->swappiness; + else if (default_swappiness >= 0) + swappiness = default_swappiness; + + if (swappiness >= 0) { + ret = cgroup_write_node_uint32(name, + MEMCG_SWAPPINESS, swappiness); + if (ret) + _I("failed to write %s %d to %s the", + MEMCG_SWAPPINESS, swappiness, name); + } + + if (mi->limit_ratio == MEMCG_NO_LIMIT) + return ret; + + /* write limit_in_bytes */ + ret = cgroup_write_node_uint32(name, + MEMCG_LIMIT_BYTE, limit); + _I("set %s's limit to %u", name, limit); + return ret; +} + +int memcg_write_params(void) +{ + unsigned int i; + + for (i = CGROUP_ROOT; i < CGROUP_END; i++) { +// struct memcg_info *mi = memcg_tree[i]->info; + struct memcg_info *mi = get_memcg_info(i); + memcg_write_params_info(mi); + } + + return RESOURCED_ERROR_NONE; +} + +void memcg_set_threshold(int type, int level, int value) +{ +// cgroup_tree[type]->memcg_info->threshold[level] = value; + struct memcg_info *mi = get_memcg_info(type); + if(!mi) + _E("memory cgroup of %d is NULL", type); + else + mi->threshold[level] = value; +} + +void memcg_set_leave_threshold(int type, int value) +{ + struct memcg_info *mi = get_memcg_info(type); + if(!mi) + _E("memory cgroup of %d is NULL", type); + else + mi->threshold_leave = value; + +// cgroup_tree[type]->memcg_info->threshold_leave = value; +} + +void memcg_info_set_limit(struct memcg_info *mi, float ratio, + unsigned int totalram) +{ + if (!mi) + return; + + mi->limit = (float)totalram * ratio; + mi->limit_ratio = ratio; + mi->threshold[LOWMEM_LOW] = (unsigned int)(mi->limit * MEMCG_LOW_RATIO); + mi->threshold[LOWMEM_MEDIUM] = (unsigned int)(mi->limit * MEMCG_MEDIUM_RATIO); + mi->threshold_leave = (float)mi->limit * MEMCG_FOREGROUND_LEAVE_RATIO; + mi->oomleave = mi->limit - mi->threshold_leave; +} + +void memcg_set_default_swappiness(int swappiness) +{ + default_swappiness = swappiness; +} + +void memcg_info_set_swappiness(struct memcg_info *mi, int swappiness) +{ + if (!mi) + return; + + mi->swappiness = swappiness; +} + +static void memcg_memory_stat_init(struct cgroup_memory_stat *mem_stat, long long val) +{ + enum cgroup_memory_stat_id id; + + assert(mem_stat); + + for (id = 0; id < CGROUP_MEMORY_STAT_MAX; id++) + mem_stat->value[id] = val; +} + +int memcg_get_memory_stat(const char *name, struct cgroup_memory_stat **mem_stat) +{ + _cleanup_fclose_ FILE *f = NULL; + struct cgroup_memory_stat *st; + char p[PATH_MAX] = ""; + char buf[LINE_MAX]; + const char *memory_stat = "memory.stat"; + const int memory_stat_len = strlen(memory_stat); + + if (name) { + int l; + int name_len = strlen(name); + + if (strneq(name, MEMCG_PATH, strlen(MEMCG_PATH))) + l = snprintf(p, PATH_MAX, "%s", name); + else + l = snprintf(p, PATH_MAX, "%s%s%s", + MEMCG_PATH, + name[0] != '/' ? "/" : "", + name); + + if (name_len >= memory_stat_len && + memcmp(name + name_len - memory_stat_len, memory_stat, memory_stat_len)) + snprintf(p + l, PATH_MAX - l, "%s%s", + p[l - 1] != '/' ? "/" : "", + memory_stat); + } else + snprintf(p, PATH_MAX, "%s/%s", MEMCG_PATH, memory_stat); + + f = fopen(p, "re"); + if (!f) + return -errno; + + st = (struct cgroup_memory_stat *)malloc(sizeof(struct cgroup_memory_stat)); + if (!st) + return -ENOMEM; + + memcg_memory_stat_init(st, -1); + + for (;;) { + enum cgroup_memory_stat_id id; + size_t l; + + if (!fgets(buf, sizeof(buf), f)) { + if (ferror(f)) { + free(st); + return -errno; + } + break; + } + + l = strcspn(buf, " "); + if (!l) + break; + + buf[l] = 0; + + id = cgroup_memory_stat_string_to_id(buf); + if (id < 0 || id >= CGROUP_MEMORY_STAT_MAX) + continue; + + st->value[id] = atoll(buf + l + 1); + } + + *mem_stat = st; + + return 0; +} + +/*void memcg_init(struct memcg *memcg) +{ + memcg->use_hierarchy = MEMCG_DEFAULT_USE_HIERARCHY; + memcg->info = NULL; + memcg->cgroups = NULL; +}*/ + +int memcg_get_anon_usage(char *memcg, unsigned int *anon_usage) +{ + int r; + _cleanup_free_ struct cgroup_memory_stat *mem_stat = NULL; + + r = memcg_get_memory_stat(memcg, &mem_stat); + if (r) { + _D("fail to get memory status : %s", memcg); + return r; + } + + *anon_usage = mem_stat->value[CGROUP_MEMORY_STAT_INACTIVE_ANON] + + mem_stat->value[CGROUP_MEMORY_STAT_ACTIVE_ANON]; + return 0; +} + +int memcg_get_swap_usage(char *memcg, unsigned int *usage) +{ + int r; + _cleanup_free_ struct cgroup_memory_stat *mem_stat = NULL; + + r = memcg_get_memory_stat(memcg, &mem_stat); + if (r) { + _D("fail to get memory status : %s", memcg); + return r; + } + + *usage = mem_stat->value[CGROUP_MEMORY_STAT_SWAP]; + return 0; +} + +/* + * From memory.txt kernel document, + * To register a event for memcg, an application must: + * - create an eventfd using eventfd(2); + * - open a node of memory cgroup + * - write string like " " to cgroup.event_control + * + * Current memory cgroup supports eventfd about only + * usage_in_byte, oom_control and pressure_level. + */ +int memcg_set_eventfd(const char *memcg, const char *event, char *value) +{ + _cleanup_close_ int mcgfd = -1; + _cleanup_close_ int cgfd = -1; + int evfd, res = 0, sz, ret = -1; + char buf[PATH_MAX] = {0,}; + + /* create an eventfd using eventfd(2)*/ + evfd = eventfd(0, 0); + ret = fcntl(evfd, F_SETFL, O_NONBLOCK); + if (ret < 0) + return RESOURCED_ERROR_FAIL; + + /* open a node of memory cgroup */ + snprintf(buf, PATH_MAX, "%s/%s", memcg, MEMCG_EVENTFD_CONTROL); + cgfd = open(buf, O_WRONLY); + if (cgfd < 0) { + const int saved_errno = errno; + _E("open event_control failed"); + errno = saved_errno; + return RESOURCED_ERROR_FAIL; + } + + snprintf(buf, PATH_MAX, "%s/%s", memcg, event); + mcgfd = open(buf, O_RDONLY); + if (mcgfd < 0) { + const int saved_errno = errno; + _E("open memory control failed"); + errno = saved_errno; + return RESOURCED_ERROR_FAIL; + } + + _D("%s %s %s registerd", memcg, event, value); + /* write string like " " to cgroup.event_control */ + sz = snprintf(buf, PATH_MAX, "%d %d %s", evfd, mcgfd, value); + sz += 1; + res = write(cgfd, buf, sz); + if (res != sz) { + int saved_errno = errno; + _E("write cgfd failed : %d", res); + errno = saved_errno; + return RESOURCED_ERROR_FAIL; + } + return evfd; +} + +struct memcg_info *get_root_memcg_info(void) +{ + return memcg_root; +} + +/*void memcg_params_exit(void) +{ + for (int i = CGROUP_ROOT; i < CGROUP_END; i++) { + g_slist_free_full(cgroup_tree[i].cgroups, free); + free(cgroup_tree[i]); + } + free(cgroup_tree); +}*/ + +void memcg_params_init(void) +{ + int idx = 0; + GSList *child_cgroups; + +/* cgroup_tree = (struct cgroup **)malloc(sizeof(struct cgroup *) * CGROUP_END); + assert(cgroup_tree);*/ + + for (idx = CGROUP_ROOT; idx < CGROUP_END; idx++) { + struct memcg_info *mi = &gmemcg_info[idx]; +/* cgroup_tree[idx] = (struct cgroup *)malloc(sizeof(struct cgroup)); + assert(cgroup_tree[idx]);*/ + +// cgroup_init(cgroup_tree[idx]); + set_memcg_info(idx, mi); + if(idx == CGROUP_ROOT) + memcg_root = mi; + else { + int parent_idx = get_parent_cgroup(idx); + child_cgroups = get_child_cgroups(parent_idx); + child_cgroups = g_slist_prepend(child_cgroups, get_cgroup_tree(idx)); + set_use_hierarchy(parent_idx, true); + } + +// cgroup_tree[idx]->memcg_info = mi; + _I("init memory cgroup for %s", mi->name); +/* if (mi->parent_memcg == CGROUP_TOP) { + memcg_root = cgroup_tree[idx]->memcg_info; + } else { + int parent_idx = mi->parent_memcg; + cgroups = cgroup_tree[parent_idx]->cgroups; + cgroups = g_slist_prepend(cgroups, mi); + cgroup_tree[parent_idx]->use_hierarchy = true; + }*/ + } +} diff --git a/src/common/cgroup/memory-cgroup.h b/src/common/cgroup/memory-cgroup.h index 33032fb..ee19655 100644 --- a/src/common/cgroup/memory-cgroup.h +++ b/src/common/cgroup/memory-cgroup.h @@ -36,18 +36,34 @@ extern "C" { /* number of memory cgroups */ #define MEMCG_DEFAULT_EVENT_LEVEL "low" -#define MEMCG_DEFAULT_USE_HIERARCHY 0 #define MEMCG_LOW_RATIO 0.8 #define MEMCG_MEDIUM_RATIO 0.96 #define MEMCG_FOREGROUND_LEAVE_RATIO 0.25 +#define MEMCG_PATH CGROUP_PATH "/memory" +#define MEMCG_VIP_PATH MEMCG_PATH "/" CGROUP_VIP_NAME +#define MEMCG_HIGH_PATH MEMCG_PATH "/" CGROUP_VIP_NAME "/" CGROUP_HIGH_NAME +#define MEMCG_MEDIUM_PATH MEMCG_PATH "/" CGROUP_VIP_NAME "/" CGROUP_HIGH_NAME "/" CGROUP_MEDIUM_NAME +#define MEMCG_LOW_PATH MEMCG_PATH "/" CGROUP_VIP_NAME "/" CGROUP_HIGH_NAME "/" CGROUP_MEDIUM_NAME "/" CGROUP_LOW_NAME -#define MEMCG_PATH CGROUP_PATH"/memory" -#define MEMCG_APPS_PATH MEMCG_PATH"/Apps" +/*#define MEMCG_APPS_PATH MEMCG_PATH"/Apps" #define MEMCG_BGLOCKED_PATH MEMCG_PATH"/Apps/BgLocked" -#define MEMCG_MEMLIMIT_PATH MEMCG_PATH"/MemLimit" -#define MEMCG_SWAP_PATH MEMCG_PATH"/Swap" +#define MEMCG_SWAP_PATH MEMCG_PATH"/Swap"*/ + +#define MEMCG_VIP_PP_PATH MEMCG_VIP_PATH "/" CGROUP_PER_PROCESS_NAME +#define MEMCG_VIP_GROUP_PATH MEMCG_VIP_PATH "/" CGROUP_GROUP_NAME + +#define MEMCG_HIGH_PP_PATH MEMCG_HIGH_PATH "/" CGROUP_PER_PROCESS_NAME +#define MEMCG_HIGH_GROUP_PATH MEMCG_HIGH_PATH "/" CGROUP_GROUP_NAME + +#define MEMCG_MEDIUM_PP_PATH MEMCG_MEDIUM_PATH "/" CGROUP_PER_PROCESS_NAME +#define MEMCG_MEDIUM_GROUP_PATH MEMCG_MEDIUM_PATH "/" CGROUP_GROUP_NAME + +#define MEMCG_LOW_PP_PATH MEMCG_LOW_PATH "/" CGROUP_PER_PROCESS_NAME +#define MEMCG_LOW_GROUP_PATH MEMCG_LOW_PATH "/" CGROUP_GROUP_NAME + + /*#define LOWMEM_ROOT_CGROUP "/sys/fs/cgroup/memory" #define LOWMEM_APPS_CGROUP LOWMEM_ROOT_CGROUP"/Apps" #define LOWMEM_BGLOCKED_CGROUP LOWMEM_ROOT_CGROUP"/Apps/BgLocked" @@ -72,32 +88,6 @@ extern "C" { #define DEFAULT_MEMLOG_PATH "/var/log" #define DEFAULT_MEMLOG_NR_MAX 50 -/* - * [memory cgroup information] - * MEMCG_MEMORY : root cgroup for system daemons - * MEMCG_APPS : cgroup for general apps - * MEMCG_BGLOCKED : cgroup for background locked and favorite apps - * MEMCG_LIMIT : cgroup for each app with memory limit set if configuration is enabled - * MEMCG_SWAP : cgroup for selected victims from background apps - * - * [memory cgroup hierarchy] - (root) - ├─Apps - │ └─BgLocked - ├─MemLimit - ├─Swap - └─system.slice (not controlled by resourced) - */ -enum memcg_type { - MEMCG_ROOT = -1, - MEMCG_MEMORY, - MEMCG_APPS, - MEMCG_BGLOCKED, - MEMCG_LIMIT, - MEMCG_SWAP, - MEMCG_MAX, -}; - enum { LOWMEM_NORMAL, LOWMEM_DEDUP, @@ -162,13 +152,15 @@ enum cgroup_memory_stat_id { CGROUP_MEMORY_STAT_INVALID = -1, }; + +//separate memcg_info and cgroup_info struct memcg_info { /* name of memory cgroup */ char name[MAX_PATH_LENGTH]; /* hashname of memory cgroup for restoring memcg info*/ - char hashname[MAX_NAME_LENGTH]; +// char hashname[MAX_NAME_LENGTH]; /* parent id */ - int parent_memcg; +// int parent_memcg; /* limit ratio, if don't want to set limit, use NO_LIMIT*/ float limit_ratio; unsigned int limit; @@ -181,14 +173,14 @@ struct memcg_info { int swappiness; }; -struct memcg { - /* parent cgroup */ +/*struct memcg { + // parent cgroup struct memcg_info *info; - /* set when using multiple sub cgroups */ + // set when using multiple sub cgroups bool use_hierarchy; - /* list of child cgroups when using multi groups */ + // list of child cgroups when using multi groups GSList *cgroups; -}; +};*/ struct lowmem_control_data { enum lowmem_control_type control_type; @@ -199,10 +191,22 @@ struct cgroup_memory_stat { long long value[CGROUP_MEMORY_STAT_MAX]; }; +//void memcg_init(struct memcg *memcg); + + +const char *cgroup_memory_stat_id_to_string(enum cgroup_memory_stat_id id); +enum cgroup_memory_stat_id cgroup_memory_stat_string_to_id(const char *str); + +int memcg_write_params(void); + +void memcg_set_threshold(int type, int level, int value); +void memcg_set_leave_threshold(int type, int value); + void memcg_info_set_limit(struct memcg_info *memcg_info, float ratio, unsigned int totalram); +void memcg_set_default_swappiness(int swappiness); void memcg_info_set_swappiness(struct memcg_info *mi, int swappiness); -void memcg_init(struct memcg *memcg); +int memcg_get_memory_stat(const char *name, struct cgroup_memory_stat **mem_stat); /** * @desc get anon memory usage of cgroup based on memory.stat @@ -222,16 +226,9 @@ int memcg_get_swap_usage(char *memcg, unsigned int *usage); */ int memcg_set_eventfd(const char *memcg, const char *event, char *value); -/** - * @desc execute /usr/bin/memps and make log file with pid and process name - */ -void make_memps_log(enum mem_log path, pid_t pid, char *victim_name); - - -const char *cgroup_memory_stat_id_to_string(enum cgroup_memory_stat_id id); -enum cgroup_memory_stat_id cgroup_memory_stat_string_to_id(const char *str); -int cgroup_get_memory_stat(const char *name, struct cgroup_memory_stat **mem_stat); +struct memcg_info *get_root_memcg_info(void); +void memcg_params_init(void); #ifdef __cplusplus } diff --git a/src/common/swap-common.h b/src/common/swap-common.h index 73f0c48..d7b25bd 100644 --- a/src/common/swap-common.h +++ b/src/common/swap-common.h @@ -53,8 +53,8 @@ enum swap_type { }; struct swap_status_msg { - enum memcg_type type; - struct memcg_info *info; + enum cgroup_type type; + struct memcg_info *memcg_info; pid_t pid; }; diff --git a/src/resource-limiter/cpu/cpu.c b/src/resource-limiter/cpu/cpu.c index 680c87e..9ae15fb 100644 --- a/src/resource-limiter/cpu/cpu.c +++ b/src/resource-limiter/cpu/cpu.c @@ -392,10 +392,10 @@ static int resourced_cpu_init(void *data) { int ret_code; - _D("resourced_cpu_init"); + _D("resourced cpu init start"); //ret_code = cgroup_make_subdir(CPUCG_PATH, "background", NULL); ret_code = cgroup_make_full_subdir(CPUCG_PATH); - ret_value_msg_if(ret_code < 0, ret_code, "cpu init failed\n"); + ret_value_msg_if(ret_code < 0, ret_code, "cpu cgroup init failed\n"); cpu_check_cpuquota(); /* if (cpu_quota_enabled()) { ret_code = cgroup_make_subdir(CPUCG_PATH, "quota", NULL); diff --git a/src/resource-limiter/memory/lowmem-dbus.c b/src/resource-limiter/memory/lowmem-dbus.c index 8f6561f..32d8668 100644 --- a/src/resource-limiter/memory/lowmem-dbus.c +++ b/src/resource-limiter/memory/lowmem-dbus.c @@ -44,7 +44,8 @@ static void lowmem_dbus_oom_set_threshold(GVariant *params) ret_unless(level >= 0); ret_unless(thres >= 0); - lowmem_memcg_set_threshold(MEMCG_MEMORY, level, thres); +// lowmem_memcg_set_threshold(CGROUP_ROOT, level, thres); + memcg_set_threshold(CGROUP_ROOT, level, thres); } static void lowmem_dbus_oom_set_leave_threshold(GVariant *params) @@ -56,7 +57,8 @@ static void lowmem_dbus_oom_set_leave_threshold(GVariant *params) g_variant_get(params, gtype, &thres); ret_unless(thres >= 0); - lowmem_memcg_set_leave_threshold(MEMCG_MEMORY, thres); +// lowmem_memcg_set_leave_threshold(CGROUP_ROOT, thres); + memcg_set_leave_threshold(CGROUP_ROOT, thres); } static void lowmem_dbus_oom_trigger(GVariant *params) @@ -86,7 +88,7 @@ static void lowmem_dbus_set_platform(GVariant *params) g_variant_get(params, gtype, &pid); ret_unless(pid > 0); - lowmem_trigger_swap(pid, MEMCG_SWAP); + lowmem_trigger_swap(pid, CGROUP_LOW); } static void lowmem_dbus_set_memlimit(GVariant *params) diff --git a/src/resource-limiter/memory/lowmem-handler.h b/src/resource-limiter/memory/lowmem-handler.h index 6c15d56..4130a42 100644 --- a/src/resource-limiter/memory/lowmem-handler.h +++ b/src/resource-limiter/memory/lowmem-handler.h @@ -64,12 +64,17 @@ struct task_info { int size; }; +/** + * @desc execute /usr/bin/memps and make log file with pid and process name + */ +void make_memps_log(enum mem_log path, pid_t pid, char *victim_name); + void lowmem_dbus_init(void); int lowmem_trigger_reclaim(int flags, int victims, enum lmk_type type, int threshold); void lowmem_trigger_swap_reclaim(enum lmk_type type, int swap_size); void lowmem_change_memory_state(int state, int force); -void lowmem_memcg_set_threshold(int idx, int level, int value); -void lowmem_memcg_set_leave_threshold(int idx, int value); +//void lowmem_memcg_set_threshold(int idx, int level, int value); +//void lowmem_memcg_set_leave_threshold(int idx, int value); unsigned long lowmem_get_ktotalram(void); void lowmem_trigger_swap(pid_t pid, int memcg_idx); void lowmem_limit_init(void); @@ -92,7 +97,7 @@ void lowmem_restore_memcg(struct proc_app_info *pai); /* * Return memcg pointer to selected cgroup. */ -int lowmem_get_memcg(enum memcg_type type, struct memcg **memcg_ptr); +//int lowmem_get_memcg(enum cgroup_type type, struct memcg **memcg_ptr); enum oom_killer_cb_flags { OOM_NONE = 0x0, /* for main oom killer thread */ diff --git a/src/resource-limiter/memory/lowmem-limit.c b/src/resource-limiter/memory/lowmem-limit.c index 3eb9f4e..1c99131 100644 --- a/src/resource-limiter/memory/lowmem-limit.c +++ b/src/resource-limiter/memory/lowmem-limit.c @@ -313,7 +313,7 @@ static bool lowmem_limit_cb(int fd, void *data) cg_dir, usage, mle->threshold); return true; } - ret = cgroup_get_memory_stat(cg_dir, &mem_stat); + ret = memcg_get_memory_stat(cg_dir, &mem_stat); if (ret) { _D("fail to get memory status : %s", cg_dir); goto remove_mle; @@ -510,7 +510,7 @@ int lowmem_limit_move_cgroup(struct proc_app_info *pai) if (!pai->memory.use_mem_limit) return RESOURCED_ERROR_NO_DATA; - ret = asprintf(&path, "%s/%s", MEMCG_MEMLIMIT_PATH, pai->appid); + ret = asprintf(&path, "%s/%s", MEMCG_HIGH_PP_PATH, pai->appid); if (ret < 0) { _E("not enough memory"); return RESOURCED_ERROR_OUT_OF_MEMORY; @@ -622,16 +622,16 @@ void lowmem_limit_set(pid_t pid, unsigned int limit) cgpath = appname; } - ret = asprintf(&path, "%s/%s", MEMCG_MEMLIMIT_PATH, cgpath); + ret = asprintf(&path, "%s/%s", MEMCG_HIGH_PP_PATH, cgpath); if (ret < 0) { _E("not enough memory"); return; } - ret = cgroup_make_subdir(MEMCG_MEMLIMIT_PATH, cgpath, NULL); + ret = cgroup_make_subdir(MEMCG_HIGH_PP_PATH, cgpath, NULL); if (ret < 0) { _E("Failed to create cgroup subdir '%s/%s'", - MEMCG_MEMLIMIT_PATH, cgpath); + MEMCG_HIGH_PP_PATH, cgpath); return; } diff --git a/src/resource-limiter/memory/memcontrol.c b/src/resource-limiter/memory/memcontrol.c deleted file mode 100644 index 4e2ae43..0000000 --- a/src/resource-limiter/memory/memcontrol.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * resourced - * - * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * @file memcontrol.c - * - * @desc structure and operation for memory cgroups - * - * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "resourced.h" -#include "trace.h" -#include "macro.h" -#include "memory-cgroup.h" -#include "cgroup.h" -#include "module.h" -#include "util.h" - -#include - -#define BUF_MAX 1023 - -void memcg_info_set_limit(struct memcg_info *mi, float ratio, - unsigned int totalram) -{ - if (!mi) - return; - - mi->limit = (float)totalram * ratio; - mi->limit_ratio = ratio; - mi->threshold[LOWMEM_LOW] = (unsigned int)(mi->limit * MEMCG_LOW_RATIO); - mi->threshold[LOWMEM_MEDIUM] = (unsigned int)(mi->limit * MEMCG_MEDIUM_RATIO); - mi->threshold_leave = (float)mi->limit * MEMCG_FOREGROUND_LEAVE_RATIO; - mi->oomleave = mi->limit - mi->threshold_leave; -} - -void memcg_info_set_swappiness(struct memcg_info *mi, int swappiness) -{ - if (!mi) - return; - - mi->swappiness = swappiness; -} - -void memcg_init(struct memcg *memcg) -{ - memcg->use_hierarchy = MEMCG_DEFAULT_USE_HIERARCHY; - memcg->info = NULL; - memcg->cgroups = NULL; -} - -int memcg_get_anon_usage(char *memcg, unsigned int *anon_usage) -{ - int r; - _cleanup_free_ struct cgroup_memory_stat *mem_stat = NULL; - - r = cgroup_get_memory_stat(memcg, &mem_stat); - if (r) { - _D("fail to get memory status : %s", memcg); - return r; - } - - *anon_usage = mem_stat->value[CGROUP_MEMORY_STAT_INACTIVE_ANON] + - mem_stat->value[CGROUP_MEMORY_STAT_ACTIVE_ANON]; - return 0; -} - -int memcg_get_swap_usage(char *memcg, unsigned int *usage) -{ - int r; - _cleanup_free_ struct cgroup_memory_stat *mem_stat = NULL; - - r = cgroup_get_memory_stat(memcg, &mem_stat); - if (r) { - _D("fail to get memory status : %s", memcg); - return r; - } - - *usage = mem_stat->value[CGROUP_MEMORY_STAT_SWAP]; - return 0; -} - -/* - * From memory.txt kernel document, - * To register a event for memcg, an application must: - * - create an eventfd using eventfd(2); - * - open a node of memory cgroup - * - write string like " " to cgroup.event_control - * - * Current memory cgroup supports eventfd about only - * usage_in_byte, oom_control and pressure_level. - */ -int memcg_set_eventfd(const char *memcg, const char *event, char *value) -{ - _cleanup_close_ int mcgfd = -1; - _cleanup_close_ int cgfd = -1; - int evfd, res = 0, sz, ret = -1; - char buf[PATH_MAX] = {0,}; - - /* create an eventfd using eventfd(2)*/ - evfd = eventfd(0, 0); - ret = fcntl(evfd, F_SETFL, O_NONBLOCK); - if (ret < 0) - return RESOURCED_ERROR_FAIL; - - /* open a node of memory cgroup */ - snprintf(buf, PATH_MAX, "%s/%s", memcg, MEMCG_EVENTFD_CONTROL); - cgfd = open(buf, O_WRONLY); - if (cgfd < 0) { - const int saved_errno = errno; - _E("open event_control failed"); - errno = saved_errno; - return RESOURCED_ERROR_FAIL; - } - - snprintf(buf, PATH_MAX, "%s/%s", memcg, event); - mcgfd = open(buf, O_RDONLY); - if (mcgfd < 0) { - const int saved_errno = errno; - _E("open memory control failed"); - errno = saved_errno; - return RESOURCED_ERROR_FAIL; - } - - _D("%s %s %s registerd", memcg, event, value); - /* write string like " " to cgroup.event_control */ - sz = snprintf(buf, PATH_MAX, "%d %d %s", evfd, mcgfd, value); - sz += 1; - res = write(cgfd, buf, sz); - if (res != sz) { - int saved_errno = errno; - _E("write cgfd failed : %d", res); - errno = saved_errno; - return RESOURCED_ERROR_FAIL; - } - return evfd; -} diff --git a/src/resource-limiter/memory/vmpressure-lowmem-handler.c b/src/resource-limiter/memory/vmpressure-lowmem-handler.c index 5944a77..7182937 100644 --- a/src/resource-limiter/memory/vmpressure-lowmem-handler.c +++ b/src/resource-limiter/memory/vmpressure-lowmem-handler.c @@ -69,7 +69,6 @@ #include "safe-kill.h" #include "dedup-common.h" -#define LOWMEM_NO_LIMIT 0 #define LOWMEM_THRES_INIT 0 #define MEMPS_EXEC_PATH "usr/bin/memps" @@ -104,74 +103,74 @@ /* thresholds for 64M RAM*/ #define PROACTIVE_64_THRES 10 /* MB */ #define PROACTIVE_64_LEAVE 30 /* MB */ -#define MEMCG_MEMORY_64_THRES_DEDUP 16 /* MB */ -#define MEMCG_MEMORY_64_THRES_SWAP 15 /* MB */ -#define MEMCG_MEMORY_64_THRES_LOW 8 /* MB */ -#define MEMCG_MEMORY_64_THRES_MEDIUM 5 /* MB */ -#define MEMCG_MEMORY_64_THRES_LEAVE 8 /* MB */ +#define CGROUP_ROOT_64_THRES_DEDUP 16 /* MB */ +#define CGROUP_ROOT_64_THRES_SWAP 15 /* MB */ +#define CGROUP_ROOT_64_THRES_LOW 8 /* MB */ +#define CGROUP_ROOT_64_THRES_MEDIUM 5 /* MB */ +#define CGROUP_ROOT_64_THRES_LEAVE 8 /* MB */ /* thresholds for 256M RAM */ #define PROACTIVE_256_THRES 50 /* MB */ #define PROACTIVE_256_LEAVE 80 /* MB */ -#define MEMCG_MEMORY_256_THRES_DEDUP 60 /* MB */ -#define MEMCG_MEMORY_256_THRES_SWAP 40 /* MB */ -#define MEMCG_MEMORY_256_THRES_LOW 20 /* MB */ -#define MEMCG_MEMORY_256_THRES_MEDIUM 10 /* MB */ -#define MEMCG_MEMORY_256_THRES_LEAVE 20 /* MB */ +#define CGROUP_ROOT_256_THRES_DEDUP 60 /* MB */ +#define CGROUP_ROOT_256_THRES_SWAP 40 /* MB */ +#define CGROUP_ROOT_256_THRES_LOW 20 /* MB */ +#define CGROUP_ROOT_256_THRES_MEDIUM 10 /* MB */ +#define CGROUP_ROOT_256_THRES_LEAVE 20 /* MB */ /* threshold for 448M RAM */ #define PROACTIVE_448_THRES 120 /* MB */ #define PROACTIVE_448_LEAVE 100 /* MB */ -#define MEMCG_MEMORY_448_THRES_DEDUP 60 /* MB */ -#define MEMCG_MEMORY_448_THRES_SWAP 100 /* MB */ -#define MEMCG_MEMORY_448_THRES_LOW 50 /* MB */ -#define MEMCG_MEMORY_448_THRES_MEDIUM 40 /* MB */ -#define MEMCG_MEMORY_448_THRES_LEAVE 60 /* MB */ +#define CGROUP_ROOT_448_THRES_DEDUP 60 /* MB */ +#define CGROUP_ROOT_448_THRES_SWAP 100 /* MB */ +#define CGROUP_ROOT_448_THRES_LOW 50 /* MB */ +#define CGROUP_ROOT_448_THRES_MEDIUM 40 /* MB */ +#define CGROUP_ROOT_448_THRES_LEAVE 60 /* MB */ /* threshold for 512M RAM */ #define PROACTIVE_512_THRES 80 /* MB */ #define PROACTIVE_512_LEAVE 100 /* MB */ -#define MEMCG_MEMORY_512_THRES_DEDUP 140 /* MB */ -#define MEMCG_MEMORY_512_THRES_SWAP 100 /* MB */ -#define MEMCG_MEMORY_512_THRES_LOW 50 /* MB */ -#define MEMCG_MEMORY_512_THRES_MEDIUM 40 /* MB */ -#define MEMCG_MEMORY_512_THRES_LEAVE 60 /* MB */ +#define CGROUP_ROOT_512_THRES_DEDUP 140 /* MB */ +#define CGROUP_ROOT_512_THRES_SWAP 100 /* MB */ +#define CGROUP_ROOT_512_THRES_LOW 50 /* MB */ +#define CGROUP_ROOT_512_THRES_MEDIUM 40 /* MB */ +#define CGROUP_ROOT_512_THRES_LEAVE 60 /* MB */ /* threshold for 768 RAM */ #define PROACTIVE_768_THRES 100 /* MB */ #define PROACTIVE_768_LEAVE 120 /* MB */ -#define MEMCG_MEMORY_768_THRES_DEDUP 180 /* MB */ -#define MEMCG_MEMORY_768_THRES_SWAP 150 /* MB */ -#define MEMCG_MEMORY_768_THRES_LOW 100 /* MB */ -#define MEMCG_MEMORY_768_THRES_MEDIUM 60 /* MB */ -#define MEMCG_MEMORY_768_THRES_LEAVE 100 /* MB */ +#define CGROUP_ROOT_768_THRES_DEDUP 180 /* MB */ +#define CGROUP_ROOT_768_THRES_SWAP 150 /* MB */ +#define CGROUP_ROOT_768_THRES_LOW 100 /* MB */ +#define CGROUP_ROOT_768_THRES_MEDIUM 60 /* MB */ +#define CGROUP_ROOT_768_THRES_LEAVE 100 /* MB */ /* threshold for more than 1024M RAM */ #define PROACTIVE_1024_THRES 150 /* MB */ #define PROACTIVE_1024_LEAVE 300 /* MB */ -#define MEMCG_MEMORY_1024_THRES_DEDUP 400 /* MB */ -#define MEMCG_MEMORY_1024_THRES_SWAP 300 /* MB */ -#define MEMCG_MEMORY_1024_THRES_LOW 200 /* MB */ -#define MEMCG_MEMORY_1024_THRES_MEDIUM 100 /* MB */ -#define MEMCG_MEMORY_1024_THRES_LEAVE 150 /* MB */ +#define CGROUP_ROOT_1024_THRES_DEDUP 400 /* MB */ +#define CGROUP_ROOT_1024_THRES_SWAP 300 /* MB */ +#define CGROUP_ROOT_1024_THRES_LOW 200 /* MB */ +#define CGROUP_ROOT_1024_THRES_MEDIUM 100 /* MB */ +#define CGROUP_ROOT_1024_THRES_LEAVE 150 /* MB */ /* threshold for more than 2048M RAM */ #define PROACTIVE_2048_THRES 200 /* MB */ #define PROACTIVE_2048_LEAVE 500 /* MB */ -#define MEMCG_MEMORY_2048_THRES_DEDUP 400 /* MB */ -#define MEMCG_MEMORY_2048_THRES_SWAP 300 /* MB */ -#define MEMCG_MEMORY_2048_THRES_LOW 200 /* MB */ -#define MEMCG_MEMORY_2048_THRES_MEDIUM 160 /* MB */ -#define MEMCG_MEMORY_2048_THRES_LEAVE 300 /* MB */ +#define CGROUP_ROOT_2048_THRES_DEDUP 400 /* MB */ +#define CGROUP_ROOT_2048_THRES_SWAP 300 /* MB */ +#define CGROUP_ROOT_2048_THRES_LOW 200 /* MB */ +#define CGROUP_ROOT_2048_THRES_MEDIUM 160 /* MB */ +#define CGROUP_ROOT_2048_THRES_LEAVE 300 /* MB */ /* threshold for more than 3072M RAM */ #define PROACTIVE_3072_THRES 300 /* MB */ #define PROACTIVE_3072_LEAVE 700 /* MB */ -#define MEMCG_MEMORY_3072_THRES_DEDUP 500 /* MB */ -#define MEMCG_MEMORY_3072_THRES_SWAP 400 /* MB */ -#define MEMCG_MEMORY_3072_THRES_LOW 300 /* MB */ -#define MEMCG_MEMORY_3072_THRES_MEDIUM 250 /* MB */ -#define MEMCG_MEMORY_3072_THRES_LEAVE 400 /* MB */ +#define CGROUP_ROOT_3072_THRES_DEDUP 500 /* MB */ +#define CGROUP_ROOT_3072_THRES_SWAP 400 /* MB */ +#define CGROUP_ROOT_3072_THRES_LOW 300 /* MB */ +#define CGROUP_ROOT_3072_THRES_MEDIUM 250 /* MB */ +#define CGROUP_ROOT_3072_THRES_LEAVE 400 /* MB */ static unsigned proactive_threshold; static unsigned proactive_leave; @@ -347,7 +346,7 @@ static void medium_act(void); static size_t cur_mem_state = LOWMEM_NORMAL; static int num_max_victims = MAX_MEMORY_CGROUP_VICTIMS; static int num_vict_between_check = MAX_VICTIMS_BETWEEN_CHECK; -static int default_swappiness = -1; +//static int default_swappiness = -1; static unsigned long totalram; static unsigned long ktotalram; @@ -360,32 +359,12 @@ static bool memcg_swap_status; static bool bg_reclaim; static int fragmentation_size; -static struct memcg_info gmi[MEMCG_MAX] = { - {MEMCG_PATH, "/", MEMCG_ROOT,}, - {MEMCG_APPS_PATH, "Apps", MEMCG_MEMORY,}, - {MEMCG_BGLOCKED_PATH, "Apps/BgLocked", MEMCG_APPS,}, - {MEMCG_MEMLIMIT_PATH, "MemLimit", MEMCG_MEMORY,}, - {MEMCG_SWAP_PATH, "Swap", MEMCG_MEMORY,}, -}; - enum memory_level { MEMORY_LEVEL_NORMAL, MEMORY_LEVEL_LOW, MEMORY_LEVEL_CRITICAL, }; -/* - * This structure has full hierarchy of memory cgroups on running system. - * It is exported through lowmem-handler.h file. - **/ -static struct memcg **memcg_tree; - -/* - * Special node that point's to /sys/fs/cgroup/memory - root of memcg group. - * This is the same as memcg_tree[MEMCG_MEMORY]->info. - */ -static struct memcg_info *memcg_root; - static GPtrArray *vip_apps; static const char *convert_type_to_str(int type) @@ -1099,7 +1078,7 @@ static void lowmem_handle_request(struct lowmem_control *ctl) retry: /* Prepare LMK to start doing it's job. Check preconditions. */ calualate_range_of_oom(lmk_type, &start_oom, &end_oom); - lmk_start_threshold = memcg_root->threshold[LOWMEM_MEDIUM]; + lmk_start_threshold = get_root_memcg_info()->threshold[LOWMEM_MEDIUM]; shortfall = is_memory_recovered(&available, ctl->size); if (!shortfall || !reclaim_size) { @@ -1263,13 +1242,13 @@ static void change_lowmem_state(unsigned int mem_state) _I("[LOW MEM STATE] %s ==> %s", convert_memstate_to_str(cur_mem_state), convert_memstate_to_str(mem_state)); cur_mem_state = mem_state; - lmk_start_threshold = memcg_root->threshold[LOWMEM_MEDIUM]; + lmk_start_threshold = get_root_memcg_info()->threshold[LOWMEM_MEDIUM]; resourced_notify(RESOURCED_NOTIFIER_MEM_STATE_CHANGED, (void *)&cur_mem_state); } -static void lowmem_swap_memory(enum memcg_type type, struct memcg_info *mi) +static void lowmem_swap_memory(enum cgroup_type type, struct memcg_info *mi) { unsigned int available; struct swap_status_msg msg; @@ -1282,11 +1261,11 @@ static void lowmem_swap_memory(enum memcg_type type, struct memcg_info *mi) available = proc_get_mem_available(); if (cur_mem_state != LOWMEM_SWAP && - available <= memcg_root->threshold[LOWMEM_SWAP]) + available <= get_root_memcg_info()->threshold[LOWMEM_SWAP]) swap_act(); msg.type = type; - msg.info = mi; + msg.memcg_info = mi; resourced_notify(RESOURCED_NOTIFIER_SWAP_START, &msg); memcg_swap_status = true; } @@ -1296,12 +1275,13 @@ void lowmem_trigger_swap(pid_t pid, int memcg_idx) struct memcg_info *mi; struct swap_status_msg msg; - mi = memcg_tree[memcg_idx]->info; + mi = get_memcg_info(memcg_idx); +// mi = memcg_tree[memcg_idx]->info; _D("name : %s, pid : %d", mi->name, pid); cgroup_write_pid_fullpath(mi->name, pid); //cgroup_write_node_uint32(mi->name, CGROUP_FILE_NAME, pid); msg.type = memcg_idx; - msg.info = mi; + msg.memcg_info = mi; resourced_notify(RESOURCED_NOTIFIER_SWAP_START, &msg); } @@ -1353,8 +1333,9 @@ static void normal_act(void) change_lowmem_state(LOWMEM_NORMAL); if (swap_get_state() == SWAP_ON && memcg_swap_status) { - msg.type = MEMCG_SWAP; - msg.info = memcg_tree[msg.type]->info; + msg.type = CGROUP_LOW; + msg.memcg_info = get_memcg_info(msg.type); +// msg.info = memcg_tree[msg.type]->info; resourced_notify(RESOURCED_NOTIFIER_SWAP_UNSET_LIMIT, &msg); memcg_swap_status = false; } @@ -1460,12 +1441,12 @@ static void medium_act(void) change_lowmem_state(LOWMEM_MEDIUM); - if (available < memcg_root->threshold_leave) { + if (available < get_root_memcg_info()->threshold_leave) { struct lowmem_control *ctl = LOWMEM_NEW_REQUEST(); if (ctl) { LOWMEM_SET_REQUEST(ctl, OOM_IN_DEPTH, - LMK_OLDEST, memcg_root->threshold_leave, + LMK_OLDEST, get_root_memcg_info()->threshold_leave, num_max_victims, medium_cb); lowmem_queue_request(&lmw, ctl); } @@ -1553,7 +1534,7 @@ static unsigned int check_mem_state(unsigned int available) { int mem_state; for (mem_state = LOWMEM_MAX_LEVEL - 1; mem_state > LOWMEM_NORMAL; mem_state--) { - if (mem_state != LOWMEM_MEDIUM && available <= memcg_root->threshold[mem_state]) + if (mem_state != LOWMEM_MEDIUM && available <= get_root_memcg_info()->threshold[mem_state]) break; else if (mem_state == LOWMEM_MEDIUM && available <= lmk_start_threshold) break; @@ -1655,42 +1636,51 @@ static int set_memory_config(const char *section_name, const struct parse_result if (!strncmp(result->name, "ThresholdDedup", strlen("ThresholdDedup")+1)) { int value = atoi(result->value); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_DEDUP, value); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_DEDUP, value); } else if (!strncmp(result->name, "ThresholdSwap", strlen("ThresholdSwap")+1)) { int value = atoi(result->value); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_SWAP, value); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_SWAP, value); } else if (!strncmp(result->name, "ThresholdLow", strlen("ThresholdLow")+1)) { int value = atoi(result->value); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_LOW, value); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_LOW, value); } else if (!strncmp(result->name, "ThresholdMedium", strlen("ThresholdMedium")+1)) { int value = atoi(result->value); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_MEDIUM, value); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_MEDIUM, value); } else if (!strncmp(result->name, "ThresholdLeave", strlen("ThresholdLeave")+1)) { int value = atoi(result->value); - lowmem_memcg_set_leave_threshold(MEMCG_MEMORY, value); + memcg_set_leave_threshold(CGROUP_ROOT, value); } else if (!strncmp(result->name, "ThresholdRatioDedup", strlen("ThresholdRatioDedup")+1)) { double ratio = atoi(result->value); int value = (double)totalram * ratio / 100.0; - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_DEDUP, BYTE_TO_MBYTE(value)); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_DEDUP, BYTE_TO_MBYTE(value)); } else if (!strncmp(result->name, "ThresholdRatioSwap", strlen("ThresholdRatioSwap")+1)) { double ratio = atoi(result->value); int value = (double)totalram * ratio / 100.0; - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_SWAP, BYTE_TO_MBYTE(value)); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_SWAP, BYTE_TO_MBYTE(value)); } else if (!strncmp(result->name, "ThresholdRatioLow", strlen("ThresholdRatioLow")+1)) { double ratio = atoi(result->value); int value = (double)totalram * ratio / 100.0; - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_LOW, BYTE_TO_MBYTE(value)); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_LOW, BYTE_TO_MBYTE(value)); } else if (!strncmp(result->name, "ThresholdRatioMedium", strlen("ThresholdRatioMedium")+1)) { double ratio = atoi(result->value); int value = (double)totalram * ratio / 100.0; - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_MEDIUM, BYTE_TO_MBYTE(value)); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_MEDIUM, BYTE_TO_MBYTE(value)); } else if (!strncmp(result->name, "ThresholdRatioLeave", strlen("ThresholdRatioLeave")+1)) { double ratio = atoi(result->value); int value = (double)totalram * ratio / 100.0; - lowmem_memcg_set_leave_threshold(MEMCG_MEMORY, BYTE_TO_MBYTE(value)); + memcg_set_leave_threshold(CGROUP_ROOT, BYTE_TO_MBYTE(value)); } else if (!strncmp(result->name, "ForegroundRatio", strlen("ForegroundRatio")+1)) { float ratio = atof(result->value); - memcg_info_set_limit(memcg_tree[MEMCG_APPS]->info, ratio, totalram); + memcg_info_set_limit(get_memcg_info(CGROUP_HIGH), ratio, totalram); +// memcg_info_set_limit(memcg_tree[CGROUP_HIGH]->info, ratio, totalram); + } else if (!strncmp(result->name, "BackgroundRatio", strlen("BackgroundRatio")+1)) { + float ratio = atof(result->value); + memcg_info_set_limit(get_memcg_info(CGROUP_MEDIUM), ratio, totalram); +// memcg_info_set_limit(memcg_tree[CGROUP_MEDIUM]->info, ratio, totalram); + } else if (!strncmp(result->name, "LowRatio", strlen("LowRatio")+1)) { + float ratio = atof(result->value); + memcg_info_set_limit(get_memcg_info(CGROUP_LOW), ratio, totalram); +// memcg_info_set_limit(memcg_tree[CGROUP_LOW]->info, ratio, totalram); } else if (!strncmp(result->name, "NumMaxVictims", strlen("NumMaxVictims")+1)) { int value = atoi(result->value); num_max_victims = value; @@ -1714,14 +1704,22 @@ static int set_memory_config(const char *section_name, const struct parse_result return RESOURCED_ERROR_OUT_OF_MEMORY; } else if (!strncmp(result->name, "SWAPPINESS", strlen("SWAPPINESS")+1)) { int value = atoi(result->value); - default_swappiness = value; - memcg_info_set_swappiness(memcg_tree[MEMCG_MEMORY]->info, value); - } else if (!strncmp(result->name, "APPCG_SWAPPINESS", strlen("APPCG_SWAPPINESS")+1)) { +// default_swappiness = value; + memcg_set_default_swappiness(value); + memcg_info_set_swappiness(get_memcg_info(CGROUP_ROOT), value); +// memcg_info_set_swappiness(memcg_tree[CGROUP_ROOT]->info, value); + } else if (!strncmp(result->name, "FOREGROUND_SWAPPINESS", strlen("FOREGROUND_SWAPPINESS")+1)) { int value = atoi(result->value); - memcg_info_set_swappiness(memcg_tree[MEMCG_APPS]->info, value); - } else if (!strncmp(result->name, "SWAPCG_SWAPPINESS", strlen("SWAPCG_SWAPPINESS")+1)) { + memcg_info_set_swappiness(get_memcg_info(CGROUP_HIGH), value); +// memcg_info_set_swappiness(memcg_tree[CGROUP_HIGH]->info, value); + } else if (!strncmp(result->name, "BACKGROUND_SWAPPINESS", strlen("BACKGROUND_SWAPPINESS")+1)) { int value = atoi(result->value); - memcg_info_set_swappiness(memcg_tree[MEMCG_SWAP]->info, value); + memcg_info_set_swappiness(get_memcg_info(CGROUP_MEDIUM), value); +// memcg_info_set_swappiness(memcg_tree[CGROUP_MEDIUM]->info, value); + } else if (!strncmp(result->name, "LOW_SWAPPINESS", strlen("LOW_SWAPPINESS")+1)) { + int value = atoi(result->value); + memcg_info_set_swappiness(get_memcg_info(CGROUP_LOW), value); +// memcg_info_set_swappiness(memcg_tree[CGROUP_LOW]->info, value); } else if (!strncmp(result->name, "NumFragSize", strlen("NumFragSize")+1)) { fragmentation_size = atoi(result->value); } @@ -1748,104 +1746,104 @@ static void setup_memcg_params(void) /* set thresholds for ram size 64M */ proactive_threshold = PROACTIVE_64_THRES; proactive_leave = PROACTIVE_64_LEAVE; - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_DEDUP, MEMCG_MEMORY_64_THRES_DEDUP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_SWAP, MEMCG_MEMORY_64_THRES_SWAP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_LOW, MEMCG_MEMORY_64_THRES_LOW); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_MEDIUM, MEMCG_MEMORY_64_THRES_MEDIUM); - lowmem_memcg_set_leave_threshold(MEMCG_MEMORY, MEMCG_MEMORY_64_THRES_LEAVE); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_DEDUP, CGROUP_ROOT_64_THRES_DEDUP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_SWAP, CGROUP_ROOT_64_THRES_SWAP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_LOW, CGROUP_ROOT_64_THRES_LOW); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_MEDIUM, CGROUP_ROOT_64_THRES_MEDIUM); + memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_64_THRES_LEAVE); section = "Memory64"; } else if (total_ramsize <= MEM_SIZE_256) { /* set thresholds for ram size 256M */ proactive_threshold = PROACTIVE_256_THRES; proactive_leave = PROACTIVE_256_LEAVE; - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_DEDUP, MEMCG_MEMORY_256_THRES_DEDUP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_SWAP, MEMCG_MEMORY_256_THRES_SWAP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_LOW, MEMCG_MEMORY_256_THRES_LOW); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_MEDIUM, MEMCG_MEMORY_256_THRES_MEDIUM); - lowmem_memcg_set_leave_threshold(MEMCG_MEMORY, MEMCG_MEMORY_256_THRES_LEAVE); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_DEDUP, CGROUP_ROOT_256_THRES_DEDUP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_SWAP, CGROUP_ROOT_256_THRES_SWAP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_LOW, CGROUP_ROOT_256_THRES_LOW); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_MEDIUM, CGROUP_ROOT_256_THRES_MEDIUM); + memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_256_THRES_LEAVE); section = "Memory256"; } else if (total_ramsize <= MEM_SIZE_448) { /* set thresholds for ram size 448M */ proactive_threshold = PROACTIVE_448_THRES; proactive_leave = PROACTIVE_448_LEAVE; - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_DEDUP, MEMCG_MEMORY_448_THRES_DEDUP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_SWAP, MEMCG_MEMORY_448_THRES_SWAP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_LOW, MEMCG_MEMORY_448_THRES_LOW); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_MEDIUM, MEMCG_MEMORY_448_THRES_MEDIUM); - lowmem_memcg_set_leave_threshold(MEMCG_MEMORY, MEMCG_MEMORY_448_THRES_LEAVE); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_DEDUP, CGROUP_ROOT_448_THRES_DEDUP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_SWAP, CGROUP_ROOT_448_THRES_SWAP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_LOW, CGROUP_ROOT_448_THRES_LOW); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_MEDIUM, CGROUP_ROOT_448_THRES_MEDIUM); + memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_448_THRES_LEAVE); section = "Memory448"; } else if (total_ramsize <= MEM_SIZE_512) { /* set thresholds for ram size 512M */ proactive_threshold = PROACTIVE_512_THRES; proactive_leave = PROACTIVE_512_LEAVE; - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_DEDUP, MEMCG_MEMORY_512_THRES_DEDUP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_SWAP, MEMCG_MEMORY_512_THRES_SWAP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_LOW, MEMCG_MEMORY_512_THRES_LOW); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_MEDIUM, MEMCG_MEMORY_512_THRES_MEDIUM); - lowmem_memcg_set_leave_threshold(MEMCG_MEMORY, MEMCG_MEMORY_512_THRES_LEAVE); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_DEDUP, CGROUP_ROOT_512_THRES_DEDUP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_SWAP, CGROUP_ROOT_512_THRES_SWAP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_LOW, CGROUP_ROOT_512_THRES_LOW); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_MEDIUM, CGROUP_ROOT_512_THRES_MEDIUM); + memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_512_THRES_LEAVE); section = "Memory512"; } else if (total_ramsize <= MEM_SIZE_768) { /* set thresholds for ram size 512M */ proactive_threshold = PROACTIVE_768_THRES; proactive_leave = PROACTIVE_768_LEAVE; - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_DEDUP, MEMCG_MEMORY_768_THRES_DEDUP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_SWAP, MEMCG_MEMORY_768_THRES_SWAP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_LOW, MEMCG_MEMORY_768_THRES_LOW); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_MEDIUM, MEMCG_MEMORY_768_THRES_MEDIUM); - lowmem_memcg_set_leave_threshold(MEMCG_MEMORY, MEMCG_MEMORY_768_THRES_LEAVE); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_DEDUP, CGROUP_ROOT_768_THRES_DEDUP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_SWAP, CGROUP_ROOT_768_THRES_SWAP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_LOW, CGROUP_ROOT_768_THRES_LOW); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_MEDIUM, CGROUP_ROOT_768_THRES_MEDIUM); + memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_768_THRES_LEAVE); section = "Memory768"; } else if (total_ramsize <= MEM_SIZE_1024) { /* set thresholds for ram size more than 1G */ proactive_threshold = PROACTIVE_1024_THRES; proactive_leave = PROACTIVE_1024_LEAVE; - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_DEDUP, MEMCG_MEMORY_1024_THRES_DEDUP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_SWAP, MEMCG_MEMORY_1024_THRES_SWAP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_LOW, MEMCG_MEMORY_1024_THRES_LOW); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_MEDIUM, MEMCG_MEMORY_1024_THRES_MEDIUM); - lowmem_memcg_set_leave_threshold(MEMCG_MEMORY, MEMCG_MEMORY_1024_THRES_LEAVE); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_DEDUP, CGROUP_ROOT_1024_THRES_DEDUP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_SWAP, CGROUP_ROOT_1024_THRES_SWAP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_LOW, CGROUP_ROOT_1024_THRES_LOW); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_MEDIUM, CGROUP_ROOT_1024_THRES_MEDIUM); + memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_1024_THRES_LEAVE); section = "Memory1024"; } else if (total_ramsize <= MEM_SIZE_2048) { proactive_threshold = PROACTIVE_2048_THRES; proactive_leave = PROACTIVE_2048_LEAVE; - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_DEDUP, MEMCG_MEMORY_2048_THRES_DEDUP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_SWAP, MEMCG_MEMORY_2048_THRES_SWAP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_LOW, MEMCG_MEMORY_2048_THRES_LOW); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_MEDIUM, MEMCG_MEMORY_2048_THRES_MEDIUM); - lowmem_memcg_set_leave_threshold(MEMCG_MEMORY, MEMCG_MEMORY_2048_THRES_LEAVE); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_DEDUP, CGROUP_ROOT_2048_THRES_DEDUP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_SWAP, CGROUP_ROOT_2048_THRES_SWAP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_LOW, CGROUP_ROOT_2048_THRES_LOW); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_MEDIUM, CGROUP_ROOT_2048_THRES_MEDIUM); + memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_2048_THRES_LEAVE); section = "Memory2048"; } else { proactive_threshold = PROACTIVE_3072_THRES; proactive_leave = PROACTIVE_3072_LEAVE; - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_DEDUP, MEMCG_MEMORY_3072_THRES_DEDUP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_SWAP, MEMCG_MEMORY_3072_THRES_SWAP); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_LOW, MEMCG_MEMORY_3072_THRES_LOW); - lowmem_memcg_set_threshold(MEMCG_MEMORY, LOWMEM_MEDIUM, MEMCG_MEMORY_3072_THRES_MEDIUM); - lowmem_memcg_set_leave_threshold(MEMCG_MEMORY, MEMCG_MEMORY_3072_THRES_LEAVE); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_DEDUP, CGROUP_ROOT_3072_THRES_DEDUP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_SWAP, CGROUP_ROOT_3072_THRES_SWAP); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_LOW, CGROUP_ROOT_3072_THRES_LOW); + memcg_set_threshold(CGROUP_ROOT, LOWMEM_MEDIUM, CGROUP_ROOT_3072_THRES_MEDIUM); + memcg_set_leave_threshold(CGROUP_ROOT, CGROUP_ROOT_3072_THRES_LEAVE); section = "Memory3072"; } config_parse(MEM_CONF_FILE, memory_load_config, (void *)section); for (i = 0; i < LOWMEM_MAX_LEVEL; i++) - _I("set threshold for state '%s' to %u MB", convert_memstate_to_str(i), memcg_root->threshold[i]); + _I("set threshold for state '%s' to %u MB", convert_memstate_to_str(i), get_root_memcg_info()->threshold[i]); _I("set number of max victims as %d", num_max_victims); - _I("set threshold leave to %u MB", memcg_root->threshold_leave); + _I("set threshold leave to %u MB", get_root_memcg_info()->threshold_leave); _I("set proactive threshold to %u MB", proactive_threshold); _I("set proactive low memory killer leave to %u MB", proactive_leave); } -static void init_memcg_params(void) +/*static void init_memcg_params(void) { int idx = 0; GSList *cgroups; memcg_tree = (struct memcg **)malloc(sizeof(struct memcg *) * - MEMCG_MAX); + CGROUP_END); assert(memcg_tree); - for (idx = 0; idx < MEMCG_MAX; idx++) { - struct memcg_info *mi = &gmi[idx]; + for (idx = CGROUP_ROOT; idx < CGROUP_END; idx++) { + struct memcg_info *mi = &gmemcg_info[idx]; memcg_tree[idx] = (struct memcg *)malloc(sizeof(struct memcg)); assert(memcg_tree[idx]); @@ -1853,68 +1851,17 @@ static void init_memcg_params(void) memcg_tree[idx]->info = mi; _I("init memory cgroup for %s", mi->name); - if (mi->parent_memcg == MEMCG_ROOT) { - memcg_root = memcg_tree[idx]->info; + if (mi->parent_memcg == CGROUP_TOP) { + get_root_memcg_info() = memcg_tree[idx]->info; } else { cgroups = memcg_tree[mi->parent_memcg]->cgroups; cgroups = g_slist_prepend(cgroups, mi); memcg_tree[mi->parent_memcg]->use_hierarchy = true; } } -} - -static int write_params_memcg_info(struct memcg_info *mi) -{ - unsigned int limit = mi->limit; - const char *name = mi->name; - int ret = RESOURCED_ERROR_NONE; - int swappiness = -1; - _I("write memcg param for %s", name); - /* enable cgroup move */ - ret = cgroup_write_node_uint32(name, - MEMCG_MOVE_CHARGE, 3); - if (ret) - return ret; - - /* - * write swapness if it has a meaningful value. - * if it has own swappiness value, set it to memcg at first. - * otherwise, check default_swappiness value and use it. - */ - if (mi->swappiness >= 0) - swappiness = mi->swappiness; - else if (default_swappiness >= 0) - swappiness = default_swappiness; - - if (swappiness >= 0) { - ret = cgroup_write_node_uint32(name, - MEMCG_SWAPPINESS, swappiness); - if (ret) - _I("failed to write %s %d to %s the", - MEMCG_SWAPPINESS, swappiness, name); - } +}*/ - if (mi->limit_ratio == LOWMEM_NO_LIMIT) - return ret; - /* write limit_in_bytes */ - ret = cgroup_write_node_uint32(name, - MEMCG_LIMIT_BYTE, limit); - _I("set %s's limit to %u", name, limit); - return ret; -} - -static int write_memcg_params(void) -{ - unsigned int i; - - for (i = 0; i < MEMCG_MAX; i++) { - struct memcg_info *mi = memcg_tree[i]->info; - write_params_memcg_info(mi); - } - - return RESOURCED_ERROR_NONE; -} static void lowmem_move_memcgroup(int pid, int oom_score_adj) { @@ -1951,18 +1898,20 @@ static void lowmem_move_memcgroup(int pid, int oom_score_adj) * management in userspace. A separate memcg won't affect * the other aspects of lowmem and swap if there is no set * action for it. */ - if (pai->memory.memcg_idx == MEMCG_BGLOCKED) + if (pai->memory.memcg_idx == CGROUP_MEDIUM) return; - memcg_idx = MEMCG_BGLOCKED; - mi = memcg_tree[memcg_idx]->info; + memcg_idx = CGROUP_MEDIUM; +// mi = memcg_tree[memcg_idx]->info; + mi = get_memcg_info(memcg_idx); } else if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED + OOMADJ_APP_INCREASE) { if (oom_score_adj != pai->memory.oom_score_adj) proc_set_process_memory_state(pai, pai->memory.memcg_idx, pai->memory.memcg_info, oom_score_adj); return; } else if (oom_score_adj >= OOMADJ_INIT) { - memcg_idx = MEMCG_APPS; - mi = memcg_tree[memcg_idx]->info; + memcg_idx = CGROUP_HIGH; +// mi = memcg_tree[memcg_idx]->info; + mi = get_memcg_info(memcg_idx); if (oom_score_adj >= OOMADJ_FAVORITE) should_swap = 1; @@ -1975,11 +1924,12 @@ static void lowmem_move_memcgroup(int pid, int oom_score_adj) * it is no necessary to control memcg any longer. * Stop other operation and return. */ - if (memcg_idx == MEMCG_APPS) { + if (memcg_idx == CGROUP_HIGH) { ret = lowmem_limit_move_cgroup(pai); if (!ret) { - memcg_idx = MEMCG_LIMIT; - mi = memcg_tree[memcg_idx]->info; +// memcg_idx = MEMCG_LIMIT; +// mi = memcg_tree[memcg_idx]->info; + mi = get_memcg_info(memcg_idx); proc_set_process_memory_state(pai, memcg_idx, mi, oom_score_adj); return; } @@ -1993,7 +1943,8 @@ static void lowmem_move_memcgroup(int pid, int oom_score_adj) * cgroup. */ if (should_swap) - lowmem_swap_memory(memcg_idx, memcg_tree[memcg_idx]->info); +// lowmem_swap_memory(memcg_idx, memcg_tree[memcg_idx]->info); + lowmem_swap_memory(memcg_idx, mi); } @@ -2045,26 +1996,6 @@ static void lowmem_deactivate_worker(void) g_async_queue_unref(lmw.queue); } -static int create_memcgs(void) -{ - int i = 0; - int ret = RESOURCED_ERROR_NONE; - struct memcg_info *mi; - char *name; - - /* skip for memory cgroup */ - for (i = 0; i < MEMCG_MAX; i++) { - if (memcg_root == memcg_tree[i]->info) - continue; - mi = memcg_tree[i]->info; - name = mi->hashname; - ret = cgroup_make_subdir(MEMCG_PATH, name, NULL); - _D("create memory cgroup for %s, ret = %d", name, ret); - } - - return ret; -} - static int lowmem_press_eventfd_read(int fd) { uint64_t dummy_state; @@ -2110,6 +2041,7 @@ static void lowmem_press_cgroup_handler(enum lmk_type type, struct memcg_info *m static bool lowmem_press_eventfd_handler(int fd, void *data) { int i; + struct cgroup *cgroup; struct memcg_info *mi; GSList *iter = NULL; enum lmk_type lmk_type = LMK_MEMORY; @@ -2118,31 +2050,37 @@ static bool lowmem_press_eventfd_handler(int fd, void *data) if (lowmem_press_eventfd_read(fd) < 0) _E("Failed to read lowmem press event, %m\n"); - for (i = 0; i < MEMCG_MAX; i++) { - if (!memcg_tree[i] || !memcg_tree[i]->info) + for (i = CGROUP_ROOT; i < CGROUP_END; i++) { + if (!get_memcg_info(i)) +// if (!memcg_tree[i] || !memcg_tree[i]->info) + if (!get_cgroup_tree(i) || !get_memcg_info(i)) continue; - mi = memcg_tree[i]->info; + mi = get_memcg_info(i); +// mi = memcg_tree[i]->info; if (fd == mi->evfd) { /* call low memory handler for this memcg */ - if (i == MEMCG_MEMORY) + if (i == CGROUP_ROOT) lowmem_press_root_cgroup_handler(); else { - if (i == MEMCG_APPS) + if (i == CGROUP_HIGH) lmk_type = LMK_ACTIVE; - else if (i == MEMCG_SWAP) + else if (i == CGROUP_LOW) lmk_type = LMK_OLDEST; lowmem_press_cgroup_handler(lmk_type, mi); } return true; } /* ToDo: iterate child memcgs */ - gslist_for_each_item(iter, memcg_tree[i]->cgroups) +// gslist_for_each_item(iter, memcg_tree[i]->cgroups) + gslist_for_each_item(iter, get_child_cgroups(i)) { - mi = (struct memcg_info *)(iter->data); + cgroup = (struct cgroup *)(iter->data); + mi = cgroup->memcg_info; +// mi = (struct memcg_info *)(iter->data); if (fd == mi->evfd) { - if (i == MEMCG_APPS) + if (i == CGROUP_HIGH) lmk_type = LMK_ACTIVE; - else if (i == MEMCG_SWAP) + else if (i == CGROUP_LOW) lmk_type = LMK_OLDEST; lowmem_press_cgroup_handler(lmk_type, mi); _D("lowmem cgroup handler is called for %s", @@ -2184,11 +2122,13 @@ static int lowmem_press_setup_eventfd(void) { unsigned int i; - for (i = 0; i < MEMCG_MAX; i++) { - if (!memcg_tree[i]->use_hierarchy) + for (i = CGROUP_ROOT; i < CGROUP_END; i++) { +// if (!memcg_tree[i]->use_hierarchy) + if (!get_use_hierarchy(i)) continue; - lowmem_press_register_eventfd(memcg_tree[i]->info); +// lowmem_press_register_eventfd(memcg_tree[i]->info); + lowmem_press_register_eventfd(get_memcg_info(i)); } return RESOURCED_ERROR_NONE; } @@ -2208,7 +2148,7 @@ int lowmem_trigger_reclaim(int flags, int victims, enum lmk_type type, int thres flags |= OOM_FORCE | OOM_IN_DEPTH | OOM_SINGLE_SHOT; victims = victims > 0 ? victims : MAX_MEMORY_CGROUP_VICTIMS; type = type > 0 ? type : LMK_OLDEST; - threshold = threshold > 0 ? threshold : memcg_root->threshold_leave; + threshold = threshold > 0 ? threshold : get_root_memcg_info()->threshold_leave; lowmem_change_memory_state(LOWMEM_LOW, 1); LOWMEM_SET_REQUEST(ctl, flags, @@ -2226,7 +2166,7 @@ void lowmem_trigger_swap_reclaim(enum lmk_type type, int swap_size) victims = num_max_victims > MAX_PROACTIVE_HIGH_VICTIMS ? MAX_PROACTIVE_HIGH_VICTIMS : num_max_victims; - size = memcg_root->threshold_leave + swap_size; + size = get_root_memcg_info()->threshold_leave + swap_size; _I("reclaim from swap module, type : %d, size : %d, victims: %d", type, size, victims); lowmem_trigger_reclaim(0, victims, type, size); } @@ -2262,7 +2202,7 @@ static void lowmem_proactive_oom_killer(int flags, char *appid) before = proc_get_mem_available(); /* If memory state is medium or normal, just return and kill in oom killer */ - if (before < memcg_root->threshold[LOWMEM_MEDIUM] || before > proactive_leave) + if (before < get_root_memcg_info()->threshold[LOWMEM_MEDIUM] || before > proactive_leave) return; victims = num_max_victims > MAX_PROACTIVE_HIGH_VICTIMS @@ -2286,13 +2226,13 @@ static void lowmem_proactive_oom_killer(int flags, char *appid) * after launching app, ensure that available memory is * above threshold_leave */ - if (after >= memcg_root->threshold[LOWMEM_MEDIUM]) + if (after >= get_root_memcg_info()->threshold[LOWMEM_MEDIUM]) return; - if (proactive_threshold - rss >= memcg_root->threshold[LOWMEM_MEDIUM]) + if (proactive_threshold - rss >= get_root_memcg_info()->threshold[LOWMEM_MEDIUM]) size = proactive_threshold; else - size = rss + memcg_root->threshold[LOWMEM_MEDIUM] + THRESHOLD_MARGIN; + size = rss + get_root_memcg_info()->threshold[LOWMEM_MEDIUM] + THRESHOLD_MARGIN; _D("history based proactive LMK : avg rss %u, available %u required = %u MB", rss, before, size); @@ -2381,8 +2321,9 @@ static int lowmem_bg_reclaim_handler(void *data) * (if swap is enabled) earlier than they used to while minimizing the * impact on the user experience. */ - msg.type = MEMCG_BGLOCKED; - msg.info = memcg_tree[msg.type]->info; + msg.type = CGROUP_MEDIUM; +// msg.info = memcg_tree[msg.type]->info; + msg.memcg_info = get_memcg_info(msg.type); resourced_notify(RESOURCED_NOTIFIER_SWAP_START, &msg); return RESOURCED_ERROR_NONE; @@ -2455,9 +2396,12 @@ static int lowmem_init(void) { int ret = RESOURCED_ERROR_NONE; - get_total_memory(); + _D("resourced memory init start"); + ret = cgroup_make_full_subdir(MEMCG_PATH); + ret_value_msg_if(ret < 0, ret, "memory cgroup init failed\n"); + memcg_params_init(); - init_memcg_params(); + get_total_memory(); setup_memcg_params(); if (allocate_vip_app_list() != RESOURCED_ERROR_NONE) _E("allocate_vip_app_list FAIL"); @@ -2474,8 +2418,7 @@ static int lowmem_init(void) config_parse(MEM_CONF_FILE, load_bg_reclaim_config, NULL); config_parse(MEM_CONF_FILE, load_mem_logconfig, NULL); - create_memcgs(); - write_memcg_params(); + memcg_write_params(); ret = lowmem_activate_worker(); if (ret) { @@ -2503,11 +2446,12 @@ static int lowmem_init(void) static int lowmem_exit(void) { - int i; - for (i = 0; i < MEMCG_MAX; i++) { +// cgroup_params_exit(); +// int i; +/* for (i = CGROUP_ROOT; i < CGROUP_END; i++) { g_slist_free_full(memcg_tree[i]->cgroups, free); free(memcg_tree[i]); - } + }*/ if (strncmp(event_level, MEMCG_DEFAULT_EVENT_LEVEL, sizeof(MEMCG_DEFAULT_EVENT_LEVEL))) free(event_level); @@ -2547,52 +2491,64 @@ void lowmem_change_memory_state(int state, int force) lowmem_trigger_memory_state_action(mem_state); } -void lowmem_memcg_set_threshold(int type, int level, int value) +/*void memcg_set_threshold(int type, int level, int value) { memcg_tree[type]->info->threshold[level] = value; } -void lowmem_memcg_set_leave_threshold(int type, int value) +void memcg_set_leave_threshold(int type, int value) { memcg_tree[type]->info->threshold_leave = value; -} +}*/ unsigned long lowmem_get_ktotalram(void) { return ktotalram; } -int lowmem_get_memcg(enum memcg_type type, struct memcg **memcg_ptr) +/*int lowmem_get_memcg(enum cgroup_type type, struct memcg **memcg_ptr) { - if (memcg_ptr == NULL || memcg_tree == NULL || type >= MEMCG_MAX) + if (memcg_ptr == NULL || memcg_tree == NULL || type >= CGROUP_END) return RESOURCED_ERROR_FAIL; *memcg_ptr = memcg_tree[type]; return RESOURCED_ERROR_NONE; -} +}*/ void lowmem_restore_memcg(struct proc_app_info *pai) { char *cgpath; int index, ret; - struct memcg_info *mi; + struct cgroup *cgroup = NULL; + struct memcg_info *mi = NULL; pid_t pid = pai->main_pid; ret = cgroup_pid_get_path("memory", pid, &cgpath); if (ret < 0) return; - for (index = MEMCG_MAX-1; index >= MEMCG_MEMORY; index--) { - mi = &gmi[index]; - if (strstr(cgpath, mi->hashname)) + for (index = CGROUP_END-1; index >= CGROUP_ROOT; index--) { + cgroup = get_cgroup_tree(index); + if (!cgroup) + continue; + + mi = cgroup->memcg_info; + if (!mi) + continue; + + if (!strcmp(cgroup->hashname, "")) + continue; + if (strstr(cgpath, cgroup->hashname)) break; } pai->memory.memcg_idx = index; pai->memory.memcg_info = mi; - if (index == MEMCG_LIMIT) + if(strstr(cgpath, pai->appid)) pai->memory.use_mem_limit = true; +/* if (index == MEMCG_LIMIT) + pai->memory.use_mem_limit = true;*/ free(cgpath); } diff --git a/src/resource-optimizer/memory/swap/swap.c b/src/resource-optimizer/memory/swap/swap.c index e421f43..eca812b 100644 --- a/src/resource-optimizer/memory/swap/swap.c +++ b/src/resource-optimizer/memory/swap/swap.c @@ -191,19 +191,22 @@ static inline void swap_add_bundle(struct swap_thread_bundle *bundle) pthread_mutex_unlock(&swap_thread_queue.lock); } -static int swap_move_to_cgroup_by_pid(enum memcg_type type, pid_t pid) +static int swap_move_to_cgroup_by_pid(enum cgroup_type type, pid_t pid) { int ret; - struct memcg *memcg_swap = NULL; + struct cgroup *cgroup_swap = NULL; struct memcg_info *mi; struct proc_app_info *pai = find_app_info(pid); GSList *iter_child = NULL; - ret = lowmem_get_memcg(type, &memcg_swap); - if (ret != RESOURCED_ERROR_NONE) + cgroup_swap = get_cgroup_tree((int)type); + if(!cgroup_swap) return RESOURCED_ERROR_FAIL; +/* ret = lowmem_get_memcg(type, &memcg_swap); + if (ret != RESOURCED_ERROR_NONE) + return RESOURCED_ERROR_FAIL;*/ - mi = memcg_swap->info; + mi = cgroup_swap->memcg_info; if (!pai) return cgroup_write_pid_fullpath(mi->name, pid); @@ -212,7 +215,7 @@ static int swap_move_to_cgroup_by_pid(enum memcg_type type, pid_t pid) pid_t child = GPOINTER_TO_PID(iter_child->data); ret = cgroup_write_pid_fullpath(mi->name, child); } - pai->memory.memcg_idx = MEMCG_SWAP; + pai->memory.memcg_idx = CGROUP_LOW; pai->memory.memcg_info = mi; return ret; } @@ -235,7 +238,7 @@ static int swap_move_to_cgroup(struct memcg_info *info, GArray *candidates) pid_t child = GPOINTER_TO_PID(iter_child->data); cgroup_write_pid_fullpath(info->name, child); } - pai->memory.memcg_idx = MEMCG_SWAP; + pai->memory.memcg_idx = CGROUP_LOW; pai->memory.memcg_info = info; } return RESOURCED_ERROR_NONE; @@ -451,7 +454,7 @@ static int swap_compact_in_module(void) static int swap_reclaim_memcg(struct swap_status_msg msg) { int r; - struct memcg_info *info = msg.info; + struct memcg_info *info = msg.memcg_info; if (!info) return -EINVAL; @@ -485,7 +488,8 @@ static int swap_move_inactive_to_swap(struct swap_status_msg *msg) int ret, max_victims; struct swap_task victim; GArray *candidates = NULL; - struct memcg *memcg_swap = NULL; +// struct memcg *memcg_swap = NULL; + struct cgroup *cgroup_swap = NULL; struct proc_app_info *pai = NULL; candidates = g_array_new(false, false, sizeof(struct swap_task)); @@ -499,7 +503,7 @@ static int swap_move_inactive_to_swap(struct swap_status_msg *msg) gslist_for_each_item(iter, proc_app_list) { pai = (struct proc_app_info *)iter->data; if ((!pai->main_pid) || - (pai->memory.memcg_info != msg->info) || + (pai->memory.memcg_info != msg->memcg_info) || (pai->memory.oom_score_adj < OOMADJ_BACKGRD_UNLOCKED) || (pai->lru_state <= PROC_BACKGROUND)) continue; @@ -515,16 +519,19 @@ static int swap_move_inactive_to_swap(struct swap_status_msg *msg) goto out; } swap_reduce_victims(candidates, max_victims); - ret = lowmem_get_memcg(MEMCG_SWAP, &memcg_swap); - if (ret != RESOURCED_ERROR_NONE) + cgroup_swap = get_cgroup_tree(CGROUP_LOW); + if(!cgroup_swap) goto out; +/* ret = lowmem_get_memcg(CGROUP_LOW, &memcg_swap); + if (ret != RESOURCED_ERROR_NONE) + goto out;*/ /* * change swap info from inactive cgroup to swap group * for using same structure to move and swap it */ - msg->info = memcg_swap->info; - msg->type = MEMCG_SWAP; - ret = swap_move_to_cgroup(msg->info, candidates); + msg->memcg_info = cgroup_swap->memcg_info; + msg->type = CGROUP_LOW; + ret = swap_move_to_cgroup(msg->memcg_info, candidates); out: proc_app_list_close(); g_array_free(candidates, TRUE); @@ -839,7 +846,7 @@ static int swap_start_handler(void *data) bundle->op = SWAP_OP_RECLAIM; memcpy(&(bundle->msg), data, sizeof(struct swap_status_msg)); - if (bundle->msg.type == MEMCG_APPS) { + if (bundle->msg.type == CGROUP_HIGH) { /* * Background tasks are concerned special way, we select * tasks and move them to Swap cgroup. They are not there already. @@ -920,20 +927,21 @@ static int swap_cgroup_reset_limit(void *data) return RESOURCED_ERROR_NONE; limit = -1; - ret = cgroup_write_node_int32(msg->info->name, MEMCG_LIMIT_BYTE, limit); + ret = cgroup_write_node_int32(msg->memcg_info->name, MEMCG_LIMIT_BYTE, limit); if (ret != RESOURCED_ERROR_NONE) - _E("Failed to change hard limit of %s cgroup to -1", msg->info->name); + _E("Failed to change hard limit of %s cgroup to -1", msg->memcg_info->name); else - _D("changed hard limit of %s cgroup to -1", msg->info->name); + _D("changed hard limit of %s cgroup to -1", msg->memcg_info->name); return ret; } static void swap_start_pid_dbus_signal_handler(GVariant *params) { - int ret; +// int ret; pid_t pid; - struct memcg *memcg_swap; +// struct memcg *memcg_swap; + struct cgroup *cgroup_swap; struct swap_status_msg ss_msg; do_expr_unless_g_variant_get_typechecked(return, params, "(i)", &pid); @@ -942,13 +950,16 @@ static void swap_start_pid_dbus_signal_handler(GVariant *params) return; } - ret = lowmem_get_memcg(MEMCG_SWAP, &memcg_swap); - if (ret != RESOURCED_ERROR_NONE) + cgroup_swap = get_cgroup_tree(CGROUP_LOW); + if (!cgroup_swap) return; - swap_move_to_cgroup_by_pid(MEMCG_SWAP, pid); +/* ret = lowmem_get_memcg(CGROUP_LOW, &memcg_swap); + if (ret != RESOURCED_ERROR_NONE) + return;*/ + swap_move_to_cgroup_by_pid(CGROUP_LOW, pid); ss_msg.pid = pid; - ss_msg.type = MEMCG_SWAP; - ss_msg.info = memcg_swap->info; + ss_msg.type = CGROUP_LOW; + ss_msg.memcg_info = cgroup_swap->memcg_info; swap_start_handler(&ss_msg); _I("swap cgroup entered : pid : %d", (int)pid); } @@ -1180,17 +1191,21 @@ static int resourced_swap_check_runtime_support(void *data) * This will prevent from flushing file pages from memory - causing * slowdown when re-launching applications. */ -static void resourced_swap_change_memcg_settings(enum memcg_type type) +static void resourced_swap_change_memcg_settings(enum cgroup_type type) { int ret; - struct memcg *memcg_swap = NULL; +// struct memcg *memcg_swap = NULL; + struct cgroup *cgroup_swap = NULL; char buf[MAX_PATH_LENGTH]; - ret = lowmem_get_memcg(type, &memcg_swap); - if (ret != RESOURCED_ERROR_NONE) + cgroup_swap = get_cgroup_tree(type); + if (!cgroup_swap) return; +/* ret = lowmem_get_memcg(type, &memcg_swap); + if (ret != RESOURCED_ERROR_NONE) + return;*/ - cgroup_write_node_uint32(memcg_swap->info->name, MEMCG_MOVE_CHARGE, 1); + cgroup_write_node_uint32(cgroup_swap->memcg_info->name, MEMCG_MOVE_CHARGE, 1); snprintf(buf, sizeof(buf), "%s/%s", MEMCG_PATH, MEMCG_FORCE_RECLAIM); ret = swap_check_node(buf); if (ret == RESOURCED_ERROR_NONE) { @@ -1206,7 +1221,7 @@ static int resourced_swap_init(void *data) { int ret; - resourced_swap_change_memcg_settings(MEMCG_SWAP); + resourced_swap_change_memcg_settings(CGROUP_LOW); swap_set_state(SWAP_OFF); ret = swap_init(); diff --git a/src/resource-optimizer/memory/swap/zramswap.c b/src/resource-optimizer/memory/swap/zramswap.c index 7fb188c..4edbae4 100644 --- a/src/resource-optimizer/memory/swap/zramswap.c +++ b/src/resource-optimizer/memory/swap/zramswap.c @@ -226,7 +226,7 @@ static int swap_zram_reclaim(void *data) if (!swap_total) swap_total = proc_get_swap_total(); - r = memcg_get_swap_usage(MEMCG_SWAP_PATH, &swap_usage); + r = memcg_get_swap_usage(MEMCG_LOW_PATH, &swap_usage); if (r) return r; swapcg_usage_ratio = (float)(swap_usage / (swap_total - swap_available) *100); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c7394c3..a75fcdd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -131,11 +131,11 @@ function(ADD_MEMORY_TESTS name libs wraps sources) endfunction() # lowmem-limit unit test -ADD_MEMORY_TESTS(lowmem-limit-test "${GLIB2_LDFLAGS}" - "-Wl,--wrap=kill,--wrap=read,--wrap=access" - lowmem-limit-test.cpp lowmem-limit-mock.cpp lowmem-limit-env.cpp lowmem-env.cpp lowmem-env-mock.cpp - ../src/common/safe-kill.c - ../src/resource-limiter/memory/lowmem-limit.c) +#ADD_MEMORY_TESTS(lowmem-limit-test "${GLIB2_LDFLAGS}" +# "-Wl,--wrap=kill,--wrap=read,--wrap=access" +# lowmem-limit-test.cpp lowmem-limit-mock.cpp lowmem-limit-env.cpp lowmem-env.cpp lowmem-env-mock.cpp +# ../src/common/safe-kill.c +# ../src/resource-limiter/memory/lowmem-limit.c) # lowmem-system unit test ADD_MEMORY_TESTS(lowmem-system-test "${GLIB2_LDFLAGS}" "-Wl,--wrap=opendir,--wrap=readdir,--wrap=closedir,--wrap=opendir64,--wrap=readdir64,--wrap=closedir64" diff --git a/tests/lowmem-dbus-env.cpp b/tests/lowmem-dbus-env.cpp index da618c7..2c71d36 100644 --- a/tests/lowmem-dbus-env.cpp +++ b/tests/lowmem-dbus-env.cpp @@ -35,14 +35,14 @@ LowmemDbusEnv::~LowmemDbusEnv() global_test_lowmem_dbus_env = nullptr; } -void LowmemDbusEnv::lowmem_memcg_set_threshold(int type, int level, int value) +void LowmemDbusEnv::memcg_set_threshold(int type, int level, int value) { check_expected(type); check_expected(level); check_expected(value); } -void LowmemDbusEnv::lowmem_memcg_set_leave_threshold(int type, int value) +void LowmemDbusEnv::memcg_set_leave_threshold(int type, int value) { check_expected(type); check_expected(value); diff --git a/tests/lowmem-dbus-env.hpp b/tests/lowmem-dbus-env.hpp index 8f99ea2..e8c47a2 100644 --- a/tests/lowmem-dbus-env.hpp +++ b/tests/lowmem-dbus-env.hpp @@ -28,8 +28,8 @@ public: LowmemDbusEnv(); ~LowmemDbusEnv(); - void lowmem_memcg_set_threshold(int type, int level, int value); - void lowmem_memcg_set_leave_threshold(int type, int value); + void memcg_set_threshold(int type, int level, int value); + void memcg_set_leave_threshold(int type, int value); int lowmem_trigger_reclaim(int flags, int victims, enum lmk_type type, int threshold); int proc_set_oom_score_adj(int pid, int oom_score_adj); void lowmem_trigger_swap(pid_t pid, int memcg_idx); diff --git a/tests/lowmem-dbus-mock.cpp b/tests/lowmem-dbus-mock.cpp index f766829..2108c61 100644 --- a/tests/lowmem-dbus-mock.cpp +++ b/tests/lowmem-dbus-mock.cpp @@ -26,8 +26,8 @@ #define WRAP_DBUS(rettype, name, def_args, call_args) \ WRAP(global_test_lowmem_dbus_env, rettype, name, def_args, call_args) -MOCK_DBUS(void, lowmem_memcg_set_threshold, (int type, int level, int value), (type, level, value)) -MOCK_DBUS(void, lowmem_memcg_set_leave_threshold, (int type, int value), (type, value)) +MOCK_DBUS(void, memcg_set_threshold, (int type, int level, int value), (type, level, value)) +MOCK_DBUS(void, memcg_set_leave_threshold, (int type, int value), (type, value)) MOCK_DBUS(int, lowmem_trigger_reclaim, (int flags, int victims, enum lmk_type type, int threshold), (flags, victims, type, threshold)) MOCK_DBUS(int, proc_set_oom_score_adj, (int pid, int oom_score_adj), (pid, oom_score_adj)) diff --git a/tests/lowmem-dbus-test.cpp b/tests/lowmem-dbus-test.cpp index 2d0e2e8..0d536e8 100644 --- a/tests/lowmem-dbus-test.cpp +++ b/tests/lowmem-dbus-test.cpp @@ -26,24 +26,24 @@ #include -void test_lowmem_memcg_set_threshold(LowmemDbusEnv &env, int level, int value) +void test_memcg_set_threshold(LowmemDbusEnv &env, int level, int value) { if (level >= 0 && value >= 0) { - expect_value(lowmem_memcg_set_threshold, type, MEMCG_MEMORY); - expect_value(lowmem_memcg_set_threshold, level, level); - expect_value(lowmem_memcg_set_threshold, value, value); + expect_value(memcg_set_threshold, type, CGROUP_ROOT); + expect_value(memcg_set_threshold, level, level); + expect_value(memcg_set_threshold, value, value); } env.trigger_signal_oom_set_threshold(g_variant_new("(ii)", level, value)); } -void test_lowmem_memcg_set_leave_threshold(LowmemDbusEnv &env, int value) +void test_memcg_set_leave_threshold(LowmemDbusEnv &env, int value) { if (value >= 0) { - expect_value(lowmem_memcg_set_leave_threshold, type, MEMCG_MEMORY); - expect_value(lowmem_memcg_set_leave_threshold, value, value); + expect_value(memcg_set_leave_threshold, type, CGROUP_ROOT); + expect_value(memcg_set_leave_threshold, value, value); } env.trigger_signal_oom_set_leave_threshold(g_variant_new("(i)", value)); @@ -73,7 +73,7 @@ void test_lowmem_set_platform(LowmemDbusEnv &env, int pid) { if (pid > 0) { expect_value(lowmem_trigger_swap, pid, pid); - expect_value(lowmem_trigger_swap, memcg_idx, MEMCG_SWAP); + expect_value(lowmem_trigger_swap, memcg_idx, CGROUP_LOW); } env.trigger_signal_oom_set_platform(g_variant_new("(i)", pid)); @@ -101,19 +101,19 @@ void simple_dbus_test(void **) std::numeric_limits int_limits; - test_lowmem_memcg_set_threshold(env, -1, 0); - test_lowmem_memcg_set_threshold(env, 0, -1); - test_lowmem_memcg_set_threshold(env, int_limits.min(), int_limits.min()); - test_lowmem_memcg_set_threshold(env, 0, 0); - test_lowmem_memcg_set_threshold(env, 123, 456); - test_lowmem_memcg_set_threshold(env, int_limits.max()-1, int_limits.max()); + test_memcg_set_threshold(env, -1, 0); + test_memcg_set_threshold(env, 0, -1); + test_memcg_set_threshold(env, int_limits.min(), int_limits.min()); + test_memcg_set_threshold(env, 0, 0); + test_memcg_set_threshold(env, 123, 456); + test_memcg_set_threshold(env, int_limits.max()-1, int_limits.max()); env.trigger_signal_oom_set_threshold(unsupported_gvariant()); - test_lowmem_memcg_set_leave_threshold(env, int_limits.min()); - test_lowmem_memcg_set_leave_threshold(env, -1); - test_lowmem_memcg_set_leave_threshold(env, 0); - test_lowmem_memcg_set_leave_threshold(env, 123); - test_lowmem_memcg_set_leave_threshold(env, int_limits.max()); + test_memcg_set_leave_threshold(env, int_limits.min()); + test_memcg_set_leave_threshold(env, -1); + test_memcg_set_leave_threshold(env, 0); + test_memcg_set_leave_threshold(env, 123); + test_memcg_set_leave_threshold(env, int_limits.max()); env.trigger_signal_oom_set_leave_threshold(unsupported_gvariant()); test_lowmem_trigger(env); diff --git a/tests/lowmem-limit-env.cpp b/tests/lowmem-limit-env.cpp index 070247d..df8ad37 100644 --- a/tests/lowmem-limit-env.cpp +++ b/tests/lowmem-limit-env.cpp @@ -108,7 +108,7 @@ void LowmemLimitEnv::configure_remove_app(pid_t pid) void LowmemLimitEnv::configure_cgroup_usages(const char *cgroup, unsigned long sw_usage, unsigned long usage) { - auto cg_name = std::string("/sys/fs/cgroup/memory/MemLimit/") + std::string(cgroup); + auto cg_name = std::string(MEMCG_HIGH_PP_PATH) + std::string(cgroup); auto &cg = cgroup_memory[cg_name]; cg.files["memory.memsw.usage_in_bytes"] = std::to_string(sw_usage); cg.files["memory.usage_in_bytes"] = std::to_string(usage); @@ -174,7 +174,7 @@ int LowmemLimitEnv::add_fd_read_handler(int fd, fd_changed_cb callback, void LowmemLimitEnv::event_cgroup_eventfd(const std::string &cgroup_event) { - const auto &p = eventfds.find(std::string("/sys/fs/cgroup/memory/MemLimit/") + cgroup_event); + const auto &p = eventfds.find(std::string(MEMCG_HIGH_PP_PATH) + cgroup_event); if (p != eventfds.end()) { event_fd_handler(p->second); } else { diff --git a/tests/lowmem-limit-env.hpp b/tests/lowmem-limit-env.hpp index 60d9c38..78cbe00 100644 --- a/tests/lowmem-limit-env.hpp +++ b/tests/lowmem-limit-env.hpp @@ -60,7 +60,7 @@ private: std::map apps; std::map fd_handlers; - const std::string default_cgroup_memory{"/sys/fs/cgroup/memory"}; + const std::string default_cgroup_memory{MEMCG_PATH}; const std::pair default_cgroup_usage{"memory.memsw.usage_in_bytes", "33554432"}; typedef std::map CGroupFiles; diff --git a/tests/lowmem-limit-test.cpp b/tests/lowmem-limit-test.cpp index ab08a39..3a0af78 100644 --- a/tests/lowmem-limit-test.cpp +++ b/tests/lowmem-limit-test.cpp @@ -54,7 +54,7 @@ void expect_d_bus_emit(const char *path, const char *interface, const char *name class CgPath { public: - CgPath(const char *name) : app_name{name}, cg_name{std::string{"/sys/fs/cgroup/memory/MemLimit/"}+name} {} + CgPath(const char *name) : app_name{name}, cg_name{std::string{MEMCG_HIGH_PP_PATH}+name} {} CgPath(CgPath &&) = delete; const char *get_app_name() const { return app_name.c_str(); } @@ -84,7 +84,7 @@ void app_test_prepare( test_lowmem_limit_env.configure_add_app(APP_PID, app_name, std::move(usages)); - expect_string(cgroup_make_subdir, parentdir, "/sys/fs/cgroup/memory/MemLimit"); + expect_string(cgroup_make_subdir, parentdir, MEMCG_HIGH_PP_PATH); expect_string(cgroup_make_subdir, cgroup_name, app_name); if (limit_type == LowmemLimitEnv::MemLimitType::OOM) { -- 2.7.4 From 75df5cd01c3c7271cb6a8ecfde97726bd39c49b2 Mon Sep 17 00:00:00 2001 From: Unsung Lee Date: Mon, 10 Jan 2022 12:38:31 +0900 Subject: [PATCH 07/16] Modify swap size unit(bytes->mbytes) Change-Id: I428240e773ddd001de4e8f1d318039a0da55116a Signed-off-by: Unsung Lee --- src/resource-limiter/memory/vmpressure-lowmem-handler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/resource-limiter/memory/vmpressure-lowmem-handler.c b/src/resource-limiter/memory/vmpressure-lowmem-handler.c index 7182937..fd1002b 100644 --- a/src/resource-limiter/memory/vmpressure-lowmem-handler.c +++ b/src/resource-limiter/memory/vmpressure-lowmem-handler.c @@ -809,7 +809,7 @@ static unsigned int is_memory_recovered(unsigned int *avail, unsigned int thres) *avail = available; - _I("[LMK] should_be_freed=%uMB[== threshold - available + margin]", should_be_freed); + _I("[LMK] should_be_freed=%uMB[== threshold(%u) - available(%u) + margin(%u)]", should_be_freed, thres, available, THRESHOLD_MARGIN); return should_be_freed; } @@ -2166,7 +2166,7 @@ void lowmem_trigger_swap_reclaim(enum lmk_type type, int swap_size) victims = num_max_victims > MAX_PROACTIVE_HIGH_VICTIMS ? MAX_PROACTIVE_HIGH_VICTIMS : num_max_victims; - size = get_root_memcg_info()->threshold_leave + swap_size; + size = get_root_memcg_info()->threshold_leave + BYTE_TO_MBYTE(swap_size); _I("reclaim from swap module, type : %d, size : %d, victims: %d", type, size, victims); lowmem_trigger_reclaim(0, victims, type, size); } -- 2.7.4 From 2bc05ad0859d5f50abc7d8d1db4ca9c223c81a0d Mon Sep 17 00:00:00 2001 From: Unsung Lee Date: Mon, 10 Jan 2022 12:47:48 +0900 Subject: [PATCH 08/16] Modify victim task size unit(MB->KB) Change-Id: I87d0c6312817159821a24d8203146a5231fb7aa4 Signed-off-by: Unsung Lee --- src/resource-limiter/memory/vmpressure-lowmem-handler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resource-limiter/memory/vmpressure-lowmem-handler.c b/src/resource-limiter/memory/vmpressure-lowmem-handler.c index fd1002b..bf0aa2a 100644 --- a/src/resource-limiter/memory/vmpressure-lowmem-handler.c +++ b/src/resource-limiter/memory/vmpressure-lowmem-handler.c @@ -1003,7 +1003,7 @@ static int lowmem_kill_victims(int max_victims, if (!(flags & OOM_NOMEMORY_CHECK) && total_victim_size >= should_be_freed_kb) { - _D("[LMK] victim=%d, max_victims=%d, total_size=%uMB", + _D("[LMK] victim=%d, max_victims=%d, total_size=%uKB", victim, max_victims, total_victim_size); status = LOWMEM_RECLAIM_DONE; break; -- 2.7.4 From 7471d6a67cc82f1295c337e28b8d2564ad75fc49 Mon Sep 17 00:00:00 2001 From: Unsung Lee Date: Wed, 12 Jan 2022 20:18:57 +0900 Subject: [PATCH 09/16] Modify configuration file name/path Change-Id: I3b84a0961d379e127025762ee6b2a705ad14d031 Signed-off-by: Unsung Lee --- CMakeLists.txt | 3 ++- {src/process/block => conf}/block.conf | 0 {src/resource-limiter/cpu => conf}/cpu-sched.conf | 0 {src/resource-limiter/cpu => conf}/cpu.conf | 0 .../memory/dedup => conf}/dedup.conf | 0 {src/resource-monitor => conf}/heart.conf | 0 .../memory-profile-iot-headless.conf | 0 .../memory-tv.conf => conf/memory-profile-tv.conf | 0 .../memory-iot-headless.conf => conf/memory.conf | 0 resourced.conf => conf/org.tizen.resourced.conf | 0 src/process/proc.conf => conf/process.conf | 0 .../memory/swap => conf}/swap.conf | 0 packaging/resourced.spec | 18 +++++++++--------- src/CMakeLists.txt | 22 +++++++++++----------- src/process/priority/proc-priority.c | 2 +- src/process/proc-appusage.c | 2 +- src/process/proc-main.c | 2 +- src/resource-limiter/cpu/cpu.c | 8 ++++---- 18 files changed, 29 insertions(+), 28 deletions(-) rename {src/process/block => conf}/block.conf (100%) rename {src/resource-limiter/cpu => conf}/cpu-sched.conf (100%) rename {src/resource-limiter/cpu => conf}/cpu.conf (100%) rename {src/resource-optimizer/memory/dedup => conf}/dedup.conf (100%) rename {src/resource-monitor => conf}/heart.conf (100%) rename src/resource-limiter/memory/memory.conf => conf/memory-profile-iot-headless.conf (100%) rename src/resource-limiter/memory/memory-tv.conf => conf/memory-profile-tv.conf (100%) rename src/resource-limiter/memory/memory-iot-headless.conf => conf/memory.conf (100%) rename resourced.conf => conf/org.tizen.resourced.conf (100%) rename src/process/proc.conf => conf/process.conf (100%) rename {src/resource-optimizer/memory/swap => conf}/swap.conf (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b2cc84..0c30bd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ SET(CMAKELISTS_DIR ${CMAKE_SOURCE_DIR}/CMakeLis SET(INCLUDE_COMMON_DIR ${CMAKE_SOURCE_DIR}/src/common) SET(INCLUDE_CGROUP_DIR ${CMAKE_SOURCE_DIR}/src/common/cgroup) SET(INCLUDE_PUBLIC_DIR ${CMAKE_SOURCE_DIR}/include) +SET(CONF_DIR ${CMAKE_SOURCE_DIR}/conf) SET(RESOURCED_INCLUDEDIR ${INCLUDE_COMMON_DIR} ${INCLUDE_CGROUP_DIR} ${INCLUDE_PUBLIC_DIR}) #misc @@ -81,7 +82,7 @@ SET(WATCHDOG_SOURCE_DIR ${PROCESS_SOURCE_DIR}/watchd SET(PRIORITY_SOURCE_DIR ${PROCESS_SOURCE_DIR}/priority) -INSTALL(FILES ${CMAKE_SOURCE_DIR}/resourced.conf DESTINATION /etc/dbus-1/system.d) +INSTALL(FILES ${CONF_DIR}/org.tizen.resourced.conf DESTINATION /etc/dbus-1/system.d) ADD_SUBDIRECTORY(src) IF(DEFINED RD_TESTS_PATH) diff --git a/src/process/block/block.conf b/conf/block.conf similarity index 100% rename from src/process/block/block.conf rename to conf/block.conf diff --git a/src/resource-limiter/cpu/cpu-sched.conf b/conf/cpu-sched.conf similarity index 100% rename from src/resource-limiter/cpu/cpu-sched.conf rename to conf/cpu-sched.conf diff --git a/src/resource-limiter/cpu/cpu.conf b/conf/cpu.conf similarity index 100% rename from src/resource-limiter/cpu/cpu.conf rename to conf/cpu.conf diff --git a/src/resource-optimizer/memory/dedup/dedup.conf b/conf/dedup.conf similarity index 100% rename from src/resource-optimizer/memory/dedup/dedup.conf rename to conf/dedup.conf diff --git a/src/resource-monitor/heart.conf b/conf/heart.conf similarity index 100% rename from src/resource-monitor/heart.conf rename to conf/heart.conf diff --git a/src/resource-limiter/memory/memory.conf b/conf/memory-profile-iot-headless.conf similarity index 100% rename from src/resource-limiter/memory/memory.conf rename to conf/memory-profile-iot-headless.conf diff --git a/src/resource-limiter/memory/memory-tv.conf b/conf/memory-profile-tv.conf similarity index 100% rename from src/resource-limiter/memory/memory-tv.conf rename to conf/memory-profile-tv.conf diff --git a/src/resource-limiter/memory/memory-iot-headless.conf b/conf/memory.conf similarity index 100% rename from src/resource-limiter/memory/memory-iot-headless.conf rename to conf/memory.conf diff --git a/resourced.conf b/conf/org.tizen.resourced.conf similarity index 100% rename from resourced.conf rename to conf/org.tizen.resourced.conf diff --git a/src/process/proc.conf b/conf/process.conf similarity index 100% rename from src/process/proc.conf rename to conf/process.conf diff --git a/src/resource-optimizer/memory/swap/swap.conf b/conf/swap.conf similarity index 100% rename from src/resource-optimizer/memory/swap/swap.conf rename to conf/swap.conf diff --git a/packaging/resourced.spec b/packaging/resourced.spec index 893cff9..c590009 100644 --- a/packaging/resourced.spec +++ b/packaging/resourced.spec @@ -157,7 +157,7 @@ mkdir -p %{buildroot}/%{confdir}/configs # https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/#ordering # List of configuration files provided by this package - update when any new config file is added! -%define config_files block cpu cpu-sched heart memory proc swap dedup +%define config_files block cpu cpu-sched heart memory process swap dedup for i in %{confdir}/*.conf; do if [ "$i" = %{confdir}/"*.conf" ]; then @@ -188,19 +188,19 @@ if [ $1 -eq 0 ]; then fi %post config-tv -%{_sbindir}/update-alternatives --install %{confdir}/memory.conf resourced-config-memory %{confdir}/configs/config-memory-tv.conf 150 +%{_sbindir}/update-alternatives --install %{confdir}/memory.conf resourced-config-memory %{confdir}/configs/config-memory-profile-tv.conf 150 %preun config-tv if [ $1 -eq 0 ]; then - %{_sbindir}/update-alternatives --remove resourced-config-memory %{confdir}/configs/config-memory-tv.conf + %{_sbindir}/update-alternatives --remove resourced-config-memory %{confdir}/configs/config-memory-profile-tv.conf fi %post config-iot-headless -%{_sbindir}/update-alternatives --install %{confdir}/memory.conf resourced-config-memory %{confdir}/configs/config-memory-iot-headless.conf 150 +%{_sbindir}/update-alternatives --install %{confdir}/memory.conf resourced-config-memory %{confdir}/configs/config-memory-profile-iot-headless.conf 150 %preun config-iot-headless if [ $1 -eq 0 ]; then - %{_sbindir}/update-alternatives --remove resourced-config-memory %{confdir}/configs/config-memory-iot-headless.conf + %{_sbindir}/update-alternatives --remove resourced-config-memory %{confdir}/configs/config-memory-profile-iot-headless.conf fi %files @@ -222,11 +222,11 @@ fi %attr(700, root, root) %{TZ_SYS_ETC}/dump.d/module.d/dump_heart_data.sh %files config -%config %{_sysconfdir}/dbus-1/system.d/resourced.conf +%config %{_sysconfdir}/dbus-1/system.d/org.tizen.resourced.conf %{_unitdir}/resourced.service %{_unitdir}/multi-user.target.wants/resourced.service %{confdir}/configs/config-memory.conf -%{confdir}/configs/config-proc.conf +%{confdir}/configs/config-process.conf %{confdir}/configs/config-swap.conf %{confdir}/configs/config-dedup.conf %{confdir}/configs/config-block.conf @@ -236,11 +236,11 @@ fi %files config-tv %manifest resourced.manifest -%{confdir}/configs/config-memory-tv.conf +%{confdir}/configs/config-memory-profile-tv.conf %files config-iot-headless %manifest resourced.manifest -%{confdir}/configs/config-memory-iot-headless.conf +%{confdir}/configs/config-memory-profile-iot-headless.conf %if %{?vip_agent_module} == ON %files vip-release-agent diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4fe2721..2ab2da7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -133,7 +133,7 @@ ADD_LIBRARY(block MODULE ${BLOCK_SOURCE_DIR}/block-monitor.c) TARGET_LINK_LIBRARIES(block resourced-private-api ${RESOURCED_REQUIRE_PKGS_LDFLAGS}) INSTALL(TARGETS block DESTINATION ${MAKE_INSTALL_PREFIX}${RD_PLUGIN_PATH}) -INSTALL(FILES ${BLOCK_SOURCE_DIR}/block.conf DESTINATION ${RD_CONFIG_PATH}) +INSTALL(FILES ${CONF_DIR}/block.conf DESTINATION ${RD_CONFIG_PATH}) ADD_DEFINITIONS("-DFREEZER_DIR=\"${LIB_INSTALL_DIR}\"") ADD_LIBRARY(freezer MODULE ${FREEZER_SOURCE_DIR}/freezer.c) @@ -147,13 +147,13 @@ ADD_LIBRARY(swap MODULE ${SWAP_SOURCE_DIR}/zramswap.c) TARGET_LINK_LIBRARIES(swap resourced-private-api ${RESOURCED_REQUIRE_PKGS_LDFLAGS}) INSTALL(TARGETS swap DESTINATION ${MAKE_INSTALL_PREFIX}${RD_PLUGIN_PATH}) -INSTALL(FILES ${SWAP_SOURCE_DIR}/swap.conf DESTINATION ${RD_CONFIG_PATH}) +INSTALL(FILES ${CONF_DIR}/swap.conf DESTINATION ${RD_CONFIG_PATH}) ADD_LIBRARY(dedup MODULE ${DEDUP_SOURCE_DIR}/dedup.c) TARGET_LINK_LIBRARIES(dedup resourced-private-api ${RESOURCED_REQUIRE_PKGS_LDFLAGS}) INSTALL(TARGETS dedup DESTINATION ${MAKE_INSTALL_PREFIX}${RD_PLUGIN_PATH}) -INSTALL(FILES ${DEDUP_SOURCE_DIR}/dedup.conf DESTINATION ${RD_CONFIG_PATH}) +INSTALL(FILES ${CONF_DIR}/dedup.conf DESTINATION ${RD_CONFIG_PATH}) ADD_LIBRARY(heart MODULE ${RESOURCE_MONITOR_SOURCE_DIR}/heart.c @@ -166,7 +166,7 @@ ADD_LIBRARY(heart MODULE ${RESOURCE_MONITOR_SOURCE_DIR}/logging.c) TARGET_LINK_LIBRARIES(heart resourced-private-api ${RESOURCED_REQUIRE_PKGS_LDFLAGS}) INSTALL(TARGETS heart DESTINATION ${MAKE_INSTALL_PREFIX}${RD_PLUGIN_PATH}) -INSTALL(FILES ${RESOURCE_MONITOR_SOURCE_DIR}/heart.conf DESTINATION ${RD_CONFIG_PATH}) +INSTALL(FILES ${CONF_DIR}/heart.conf DESTINATION ${RD_CONFIG_PATH}) CONFIGURE_FILE(${RESOURCE_MONITOR_SOURCE_DIR}/dump_heart_data.sh.in ${RESOURCE_MONITOR_SOURCE_DIR}/dump_heart_data.sh @ONLY) INSTALL(FILES ${RESOURCE_MONITOR_SOURCE_DIR}/dump_heart_data.sh DESTINATION ${RD_SYS_ETC}/dump.d/module.d) @@ -219,15 +219,15 @@ INSTALL(TARGETS ${RD_BINARY_NAME} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE WORLD_EXECUTE) IF("${MEMORY_MODULE}" STREQUAL "ON") - INSTALL(FILES ${MEMORY_LIMITER_SOURCE_DIR}/memory.conf DESTINATION ${RD_CONFIG_PATH}) - INSTALL(FILES ${MEMORY_LIMITER_SOURCE_DIR}/memory-tv.conf DESTINATION ${RD_CONFIG_PATH}) - INSTALL(FILES ${MEMORY_LIMITER_SOURCE_DIR}/memory-iot-headless.conf DESTINATION ${RD_CONFIG_PATH}) + INSTALL(FILES ${CONF_DIR}/memory.conf DESTINATION ${RD_CONFIG_PATH}) + INSTALL(FILES ${CONF_DIR}/memory-profile-tv.conf DESTINATION ${RD_CONFIG_PATH}) + INSTALL(FILES ${CONF_DIR}/memory-profile-iot-headless.conf DESTINATION ${RD_CONFIG_PATH}) ENDIF() IF("${CPU_MODULE}" STREQUAL "ON") - INSTALL(FILES ${CPU_LIMITER_SOURCE_DIR}/cpu.conf + INSTALL(FILES ${CONF_DIR}/cpu.conf DESTINATION ${RD_CONFIG_PATH} RENAME cpu.conf) - INSTALL(FILES ${CPU_LIMITER_SOURCE_DIR}/cpu-sched.conf + INSTALL(FILES ${CONF_DIR}/cpu-sched.conf DESTINATION ${RD_CONFIG_PATH} RENAME cpu-sched.conf) ENDIF() @@ -239,5 +239,5 @@ IF("${VIP_AGENT}" STREQUAL "ON") INSTALL(TARGETS vip-release-agent DESTINATION bin) ENDIF() -INSTALL(FILES ${PROCESS_SOURCE_DIR}/proc.conf - DESTINATION ${RD_CONFIG_PATH} RENAME proc.conf) +INSTALL(FILES ${CONF_DIR}/process.conf + DESTINATION ${RD_CONFIG_PATH} RENAME process.conf) diff --git a/src/process/priority/proc-priority.c b/src/process/priority/proc-priority.c index 728bf92..1211837 100644 --- a/src/process/priority/proc-priority.c +++ b/src/process/priority/proc-priority.c @@ -36,7 +36,7 @@ #include "resourced.h" #include "trace.h" -#define PRIORITY_CONF_FILE RD_CONFIG_FILE(proc) +#define PRIORITY_CONF_FILE RD_CONFIG_FILE(process) #define FIXED_OOM_CONF_SECTION "OOM_FIXED_APPS" diff --git a/src/process/proc-appusage.c b/src/process/proc-appusage.c index 50da8ef..25f1b5d 100644 --- a/src/process/proc-appusage.c +++ b/src/process/proc-appusage.c @@ -37,7 +37,7 @@ #include "heart-common.h" #define UPDATE_INTERVAL DAY_TO_SEC(2) -#define APPUSAGE_CONF_FILE RD_CONFIG_FILE(proc) +#define APPUSAGE_CONF_FILE RD_CONFIG_FILE(process) #define APPUSAGE_CONF_SECTION "APPUSAGE" static int favorite_count; diff --git a/src/process/proc-main.c b/src/process/proc-main.c index 6121d52..832224e 100644 --- a/src/process/proc-main.c +++ b/src/process/proc-main.c @@ -60,7 +60,7 @@ #endif #endif -#define WATCHDOG_EXCLUDE_CONF_FILE RD_CONFIG_FILE(proc) +#define WATCHDOG_EXCLUDE_CONF_FILE RD_CONFIG_FILE(process) #define WATCHDOG_EXCLUDE_CONF_SECTION "WATCHDOG_EXCLUDED_PROCESSES" static GHashTable *watchdog_exclude_list; diff --git a/src/resource-limiter/cpu/cpu.c b/src/resource-limiter/cpu/cpu.c index 9ae15fb..c39a8bf 100644 --- a/src/resource-limiter/cpu/cpu.c +++ b/src/resource-limiter/cpu/cpu.c @@ -84,7 +84,7 @@ enum { enum cpu_control_type { SET_NONE, - SET_DEFAUT, + SET_DEFAULT, SET_BOOTING, SET_WRT, SET_LAZY, @@ -182,7 +182,7 @@ static int load_cpu_config(struct parse_result *result, void *user_data) if (pid > 0) { cpu_move_cgroup(pid, CPUCG_MEDIUM_GROUP_PATH); def_list.control[def_list.num].pid = pid; - def_list.control[def_list.num++].type = SET_DEFAUT; + def_list.control[def_list.num++].type = SET_DEFAULT; } else { _E("not found appname = %s", result->value); } @@ -268,7 +268,7 @@ static int cpu_foreground_state(void *data) pri = getpriority(PRIO_PROCESS, ps->pid); if (pri == -1 || pri > CPU_DEFAULT_PRI) setpriority(PRIO_PGRP, ps->pid, CPU_DEFAULT_PRI); - if (check_predefined(ps->pid) != SET_DEFAUT) + if (check_predefined(ps->pid) != SET_DEFAULT) cpu_move_cgroup_foreach(ps->pid, ps->pai, CPUCG_HIGH_GROUP_PATH); return RESOURCED_ERROR_NONE; } @@ -358,7 +358,7 @@ static int cpu_terminatestart_state(void *data) static int cpu_exclude_state(void *data) { struct proc_exclude *pe = (struct proc_exclude *)data; - if (check_predefined(pe->pid) == SET_DEFAUT) + if (check_predefined(pe->pid) == SET_DEFAULT) return RESOURCED_ERROR_NONE; if (pe->type == PROC_INCLUDE) cpu_move_cgroup(pe->pid, CPUCG_MEDIUM_GROUP_PATH); -- 2.7.4 From 01771eef2bff24f180f1d439f65dd1dd94c64811 Mon Sep 17 00:00:00 2001 From: Unsung Lee Date: Mon, 24 Jan 2022 13:00:26 +0900 Subject: [PATCH 10/16] Classify apps & optimize memory cgroup Classify apps according to oom_score_adj & remove useless find_app_info() functions Change-Id: Id7131dd11a36b16cc6b2b061cccc9aa842c51224 Signed-off-by: Unsung Lee --- src/common/cgroup/cgroup.c | 58 +++- src/common/cgroup/cgroup.h | 21 ++ src/common/cgroup/memory-cgroup.h | 4 +- src/common/filemap.c | 6 +- src/common/proc-common.h | 1 + src/common/procfs.c | 12 +- src/common/procfs.h | 4 +- src/process/block/block-monitor.c | 4 +- src/process/priority/proc-priority.c | 8 +- src/process/proc-main.c | 78 ++--- src/process/proc-main.h | 2 +- src/process/proc-monitor.c | 24 +- src/process/proc-process.c | 74 ++--- src/process/proc-process.h | 8 +- src/resource-limiter/memory/lowmem-dbus.c | 7 +- src/resource-limiter/memory/lowmem-handler.h | 22 +- src/resource-limiter/memory/lowmem-limit.c | 62 ++-- .../memory/vmpressure-lowmem-handler.c | 329 +++++++++++---------- src/resource-optimizer/memory/dedup/.dedup.c.swp | Bin 16384 -> 0 bytes src/resource-optimizer/memory/dedup/dedup.c | 24 +- src/resource-optimizer/memory/swap/fileswap.c | 4 +- src/resource-optimizer/memory/swap/swap.c | 133 +++++---- src/resource-optimizer/memory/swap/zramswap.c | 8 +- src/resource-optimizer/memory/swap/zswap.c | 2 +- tests/cmocka-proc-dbus-typecheck.c | 18 +- tests/lowmem-dbus-env.cpp | 5 +- tests/lowmem-dbus-env.hpp | 4 +- tests/lowmem-dbus-mock.cpp | 5 +- tests/lowmem-dbus-test.cpp | 3 +- 29 files changed, 531 insertions(+), 399 deletions(-) delete mode 100644 src/resource-optimizer/memory/dedup/.dedup.c.swp diff --git a/src/common/cgroup/cgroup.c b/src/common/cgroup/cgroup.c index 64d99f2..81cf67d 100644 --- a/src/common/cgroup/cgroup.c +++ b/src/common/cgroup/cgroup.c @@ -29,6 +29,7 @@ #include "resourced.h" #include "trace.h" #include "file-helper.h" +#include "procfs.h" #include #include @@ -92,10 +93,53 @@ static struct cgroup cgroup_tree[CGROUP_END] = { cgroup->cgroups = NULL; }*/ +int cgroup_get_type(int oom_score_adj) +{ + if (oom_score_adj == OOMADJ_SERVICE_MIN) + return CGROUP_VIP; + else if (oom_score_adj >= OOMADJ_SU && + oom_score_adj < OOMADJ_BACKGRD_PERCEPTIBLE) + return CGROUP_HIGH; + else if (oom_score_adj >= OOMADJ_BACKGRD_PERCEPTIBLE && + oom_score_adj < OOMADJ_BACKGRD_UNLOCKED + OOMADJ_APP_INCREASE) + return CGROUP_MEDIUM; + else if (oom_score_adj >= OOMADJ_BACKGRD_UNLOCKED + OOMADJ_APP_INCREASE && + oom_score_adj <= OOMADJ_APP_MAX) + return CGROUP_LOW; + else + return CGROUP_ROOT; +} + +int cgroup_get_lowest_oom_score_adj(int type) +{ + if (type == CGROUP_VIP) + return OOMADJ_SERVICE_MIN; + else if (type == CGROUP_HIGH) + return OOMADJ_SU; + else if (type == CGROUP_MEDIUM) + return OOMADJ_BACKGRD_PERCEPTIBLE; + else if (type == CGROUP_LOW) + return OOMADJ_BACKGRD_UNLOCKED + OOMADJ_APP_INCREASE; + else + return OOMADJ_SU; +} + +int cgroup_get_highest_oom_score_adj(int type) +{ + if (type == CGROUP_VIP) + return OOMADJ_SERVICE_MIN; + else if (type == CGROUP_HIGH) + return OOMADJ_FOREGRD_UNLOCKED; + else if (type == CGROUP_MEDIUM) + return OOMADJ_BACKGRD_UNLOCKED; + else + return OOMADJ_APP_MAX; +} + struct cgroup *get_cgroup_tree(int idx) { if(idx < CGROUP_ROOT || idx >= CGROUP_END) { - _E("(%d) cgroup tree is NULL", idx); + _E("[DEBUG] (%d) cgroup tree is NULL", idx); return NULL; } else @@ -105,7 +149,7 @@ struct cgroup *get_cgroup_tree(int idx) void set_memcg_info(int idx, struct memcg_info *mi) { if(idx < CGROUP_ROOT || idx >= CGROUP_END) { - _E("(%d) index is out of scope", idx); + _E("[DEBUG] (%d) index is out of scope", idx); } else cgroup_tree[idx].memcg_info = mi; @@ -114,7 +158,7 @@ void set_memcg_info(int idx, struct memcg_info *mi) struct memcg_info *get_memcg_info(int idx) { if(idx < CGROUP_ROOT || idx >= CGROUP_END) { - _E("(%d) cgroup tree's memcg info is NULL", idx); + _E("[DEBUG] (%d) cgroup tree's memcg info is NULL", idx); return NULL; } else @@ -124,7 +168,7 @@ struct memcg_info *get_memcg_info(int idx) GSList *get_child_cgroups(int idx) { if(idx < CGROUP_ROOT || idx >= CGROUP_END) { - _E("(%d) cgroup tree's child is NULL", idx); + _E("[DEBUG] (%d) cgroup tree's child is NULL", idx); return NULL; } else @@ -134,7 +178,7 @@ GSList *get_child_cgroups(int idx) int get_parent_cgroup(int idx) { if(idx < CGROUP_ROOT || idx >= CGROUP_END) { - _E("(%d) cgroup range is out of scope", idx); + _E("[DEBUG] (%d) cgroup range is out of scope", idx); return CGROUP_TOP; } else { @@ -145,7 +189,7 @@ int get_parent_cgroup(int idx) void set_use_hierarchy(int idx, bool use_hierarchy) { if(idx < CGROUP_ROOT || idx >= CGROUP_END) { - _E("(%d) cgroup range is out of scope", idx); + _E("[DEBUG] (%d) cgroup range is out of scope", idx); } else { cgroup_tree[idx].use_hierarchy = use_hierarchy; @@ -155,7 +199,7 @@ void set_use_hierarchy(int idx, bool use_hierarchy) bool get_use_hierarchy(int idx) { if(idx < CGROUP_ROOT || idx >= CGROUP_END) { - _E("(%d) cgroup range is out of scope", idx); + _E("[DEBUG] (%d) cgroup range is out of scope", idx); return CGROUP_DEFAULT_USE_HIERARCHY; } else { diff --git a/src/common/cgroup/cgroup.h b/src/common/cgroup/cgroup.h index 25ec742..701b7b3 100644 --- a/src/common/cgroup/cgroup.h +++ b/src/common/cgroup/cgroup.h @@ -100,6 +100,27 @@ struct cgroup { }; /** + * @desc Get cgroup type according to oom_score_adj + * @param oom_score_adj - oom_score_adj + * @return cgroup type + */ +int cgroup_get_type(int oom_score_adj); + +/** + * @desc Get the highest oom_score_adj of the cgroup type + * @param type - cgroup type + * @return oom_score_adj + */ +int cgroup_get_highest_oom_score_adj(int type); + +/** + * @desc Get the lowest oom_score_adj of the cgroup type + * @param type - cgroup type + * @return oom_score_adj + */ +int cgroup_get_lowest_oom_score_adj(int type); + +/** * @desc Get one unsigned int32 value from cgroup * @param cgroup_name - cgroup path * @param file_name - cgroup content to write diff --git a/src/common/cgroup/memory-cgroup.h b/src/common/cgroup/memory-cgroup.h index ee19655..2e430d4 100644 --- a/src/common/cgroup/memory-cgroup.h +++ b/src/common/cgroup/memory-cgroup.h @@ -184,7 +184,9 @@ struct memcg_info { struct lowmem_control_data { enum lowmem_control_type control_type; - int args[2]; + int pid; + int oom_score_adj; + struct proc_app_info *pai; }; struct cgroup_memory_stat { diff --git a/src/common/filemap.c b/src/common/filemap.c index 6c9e7a5..b7b24cf 100644 --- a/src/common/filemap.c +++ b/src/common/filemap.c @@ -139,7 +139,7 @@ static struct filemap_node *filemap_node_init(void *start, const char *key, { struct filemap_node *fn = start; - assert(keylen < FILEMAP_MAX_KEY_LEN - 1); + assert(keylen < sizeof (fn->key) - 1); assert(start); fn->keylen = keylen; @@ -155,8 +155,8 @@ static struct filemap_info *filemap_info_init(void *start, const char *key, struct filemap_info *fi = start; assert(start); - assert(keylen < FILEMAP_MAX_KEY_LEN - 1); - assert(valuelen < FILEMAP_MAX_VALUE_LEN - 1); + assert(keylen < sizeof (fi->key) - 1); + assert(valuelen < sizeof (fi->value) - 1); fi->keylen = keylen; strncpy(fi->key, key, keylen + 1); diff --git a/src/common/proc-common.h b/src/common/proc-common.h index 7d9a964..4ec250e 100644 --- a/src/common/proc-common.h +++ b/src/common/proc-common.h @@ -186,6 +186,7 @@ struct proc_app_info { bool dont_freeze; }; +int proc_priority_set_fixed_oom(void *data); int proc_get_freezer_status(void); struct proc_app_info *find_app_info(const pid_t pid); diff --git a/src/common/procfs.c b/src/common/procfs.c index 6d57624..64e1e8d 100644 --- a/src/common/procfs.c +++ b/src/common/procfs.c @@ -51,6 +51,7 @@ #include "swap-common.h" #include "smaps.h" #include "notifier.h" +#include "lowmem-handler.h" #define MEM_SWAP_RATIO 0.5 @@ -153,7 +154,7 @@ int proc_get_oom_score_adj(int pid, int *oom_score_adj) return RESOURCED_ERROR_NONE; } -int proc_set_oom_score_adj(int pid, int oom_score_adj) +int proc_set_oom_score_adj(int pid, int oom_score_adj, struct proc_app_info *pai) { FILE *fp; struct lowmem_control_data lowmem_data; @@ -176,8 +177,9 @@ int proc_set_oom_score_adj(int pid, int oom_score_adj) if (oom_score_adj >= OOMADJ_SU) { lowmem_data.control_type = LOWMEM_MOVE_CGROUP; - lowmem_data.args[0] = (int)pid; - lowmem_data.args[1] = (int)oom_score_adj; + lowmem_data.pid = pid; + lowmem_data.oom_score_adj = oom_score_adj; + lowmem_data.pai = pai; resourced_notify(RESOURCED_NOTIFIER_MEM_CONTROL, &lowmem_data); } @@ -354,7 +356,7 @@ int proc_get_mem_usage(pid_t pid, unsigned int *usage) ret = proc_get_approx_mem_usage(pid, &total); if (ret < 0) { - _E("Failed to get usage : %d", pid); + _E("[DEBUG] Failed to get usage : %d", pid); return ret; } @@ -381,7 +383,7 @@ int proc_get_ram_usage(pid_t pid, unsigned int *usage) ret = proc_get_approx_mem_usage(pid, &total); if (ret < 0) { - _E("Failed to get usage : %d", pid); + _E("[DEBUG] Failed to get usage : %d", pid); return ret; } diff --git a/src/common/procfs.h b/src/common/procfs.h index b30ba46..df1b12b 100644 --- a/src/common/procfs.h +++ b/src/common/procfs.h @@ -32,6 +32,8 @@ extern "C" { #endif /* __cplusplus */ +#include "proc-common.h" + #define OOMADJ_SERVICE_MIN (-900) #define OOMADJ_SU (0) #define OOMADJ_INIT (100) @@ -261,7 +263,7 @@ int proc_get_oom_score_adj(int pid, int *oom_score_adj); * @desc set oom score adj value to /proc/{pid}/oom_score_adj * @return negative value if error or pid doesn't exist */ -int proc_set_oom_score_adj(int pid, int oom_score_adj); +int proc_set_oom_score_adj(int pid, int oom_score_adj, struct proc_app_info *pai); /** * @desc get smack subject label from /proc/{pid}/attr/current diff --git a/src/process/block/block-monitor.c b/src/process/block/block-monitor.c index 44a86b1..96e9022 100644 --- a/src/process/block/block-monitor.c +++ b/src/process/block/block-monitor.c @@ -124,7 +124,7 @@ static void block_logging(struct block_monitor_info *bmi, pid_t pid, int type = bmi->logging; if (type & BLOCK_LOGGING_DLOG) - _I("pid %d(%s) accessed %s", pid, label, filename); + _I("[DEBUG] pid %d(%s) accessed %s", pid, label, filename); if (type & BLOCK_LOGGING_FILE) { FILE *f; @@ -256,7 +256,7 @@ int register_fanotify(struct block_monitor_info *bmi) if (!bmi || !strlen(bmi->path)) return RESOURCED_ERROR_NO_DATA; - _D("monitor register : path %s, mode %08x", bmi->path, bmi->mode); + _D("[DEBUG] monitor register : path %s, mode %08x", bmi->path, bmi->mode); bmi->mfd = fanotify_init(FAN_CLOEXEC|FAN_NONBLOCK | FAN_CLASS_CONTENT, O_RDONLY | O_LARGEFILE | O_CLOEXEC | O_NOATIME); diff --git a/src/process/priority/proc-priority.c b/src/process/priority/proc-priority.c index 1211837..24a2be2 100644 --- a/src/process/priority/proc-priority.c +++ b/src/process/priority/proc-priority.c @@ -46,7 +46,7 @@ static GHashTable *oom_fixed_app_list; static GHashTable *oom_fixed_pid_list; -static int proc_priority_set_fixed_oom(void *data) +int proc_priority_set_fixed_oom(void *data) { int ret; int *fixed_oom = NULL; @@ -60,7 +60,7 @@ static int proc_priority_set_fixed_oom(void *data) /* Make another hashtable for fast searching during proc_set_oom_score_adj */ if (fixed_oom) { - ret = proc_set_oom_score_adj(ps->pid, *fixed_oom); + ret = proc_set_oom_score_adj(ps->pid, *fixed_oom, ps->pai); if (ret != RESOURCED_ERROR_NONE) { _E("Failed to set the fixed oom for %s", ps->pai->appid); return ret; @@ -140,7 +140,7 @@ static int proc_priority_init(void *data) config_parse(PRIORITY_CONF_FILE, load_fixed_oom_config, NULL); - register_notifier(RESOURCED_NOTIFIER_APP_LAUNCH, proc_priority_set_fixed_oom); +// register_notifier(RESOURCED_NOTIFIER_APP_LAUNCH, proc_priority_set_fixed_oom); register_notifier(RESOURCED_NOTIFIER_APP_TERMINATED, proc_priority_remove_pid); return RESOURCED_ERROR_NONE; } @@ -151,7 +151,7 @@ static int proc_priority_exit(void *data) g_hash_table_destroy(oom_fixed_app_list); if (oom_fixed_pid_list) g_hash_table_destroy(oom_fixed_pid_list); - unregister_notifier(RESOURCED_NOTIFIER_APP_LAUNCH, proc_priority_set_fixed_oom); +// unregister_notifier(RESOURCED_NOTIFIER_APP_LAUNCH, proc_priority_set_fixed_oom); unregister_notifier(RESOURCED_NOTIFIER_APP_TERMINATED, proc_priority_remove_pid); return RESOURCED_ERROR_NONE; } diff --git a/src/process/proc-main.c b/src/process/proc-main.c index 832224e..58f0a5a 100644 --- a/src/process/proc-main.c +++ b/src/process/proc-main.c @@ -456,16 +456,18 @@ static struct proc_program_info *find_program_info(const char *pkgname) return NULL; } -resourced_ret_c proc_set_runtime_exclude_list(const int pid, int type) +resourced_ret_c proc_set_runtime_exclude_list(const int pid, int type, struct proc_app_info *pai) { _cleanup_free_ char *runtime_app_info_path = NULL; - struct proc_app_info *pai = NULL; +// struct proc_app_info *pai = NULL; struct proc_status ps = {0}; int ret; - pai = find_app_info(pid); - if (!pai) +// pai = find_app_info(pid); + if (!pai) { + _E("[DEBUG] process app info is NULL"); return RESOURCED_ERROR_NO_DATA; + } ps.pid = pid; ps.pai = pai; @@ -480,7 +482,7 @@ resourced_ret_c proc_set_runtime_exclude_list(const int pid, int type) } else { pai->runtime_exclude = type; } - _D("pid %d set proc exclude list, type = %d, exclude = %d", + _D("[DEBUG] pid %d set proc exclude list, type = %d, exclude = %d", pid, type, pai->runtime_exclude); runtime_app_info_path = proc_get_runtime_app_info_path(pai); @@ -515,16 +517,16 @@ static void proc_set_default_svc_oomscore } } - proc_set_service_oomscore(svc->main_pid, oom_score_adj); + proc_set_service_oomscore(svc->main_pid, oom_score_adj, svc); /* The svc->memory.oom_score_adj should have been updated by the * subroutine of proc_set_service_oomscore(). But at this stage, * the proc_app_info of service app is not added to the app list. As a * result the subroutine cannot update proc_app_info of a service app. * Therefore, manually update oom_score_adj of service app. */ - retval = proc_get_oom_score_adj(svc->main_pid, &oom_score_adj); +/* retval = proc_get_oom_score_adj(svc->main_pid, &oom_score_adj); if (retval == RESOURCED_ERROR_NONE) - svc->memory.oom_score_adj = oom_score_adj; + svc->memory.oom_score_adj = oom_score_adj;*/ } static struct proc_program_info *proc_add_program_list(const int type, @@ -561,8 +563,8 @@ static struct proc_program_info *proc_add_program_list(const int type, ppi->app_list = g_slist_prepend(ppi->app_list, pai); else { ppi->svc_list = g_slist_prepend(ppi->svc_list, pai); - if (!restore) - proc_set_default_svc_oomscore(ppi, pai); +/* if (!restore) + proc_set_default_svc_oomscore(ppi, pai);*/ } return ppi; } @@ -761,7 +763,7 @@ __attribute__((weak)) struct proc_app_info *proc_create_app_info(const char *app prelaunch = NULL; if (!streq(pai->appid, appid)) { - _E("prelaunched app(%s) is not matched with new app info(%s)", + _E("[DEBUG] prelaunched app(%s) is not matched with new app info(%s)", pai->appid, appid); proc_remove_app_info(pai); @@ -778,7 +780,7 @@ __attribute__((weak)) struct proc_app_info *proc_create_app_info(const char *app } else { /* prelaunch */ if (prelaunch) { - _E("prelaunched app was not gone to launch state, appid(%s)", prelaunch->appid); + _E("[DEBUG] prelaunched app was not gone to launch state, appid(%s)", prelaunch->appid); proc_remove_app_info(prelaunch); prelaunch = NULL; } @@ -821,6 +823,9 @@ __attribute__((weak)) struct proc_app_info *proc_create_app_info(const char *app else pai->starttime = uptime; } + proc_set_process_memory_state(pai, CGROUP_TOP, NULL, -1); + pai->memory.use_mem_limit = false; + pai->memory.oom_killed = false; } return pai; } @@ -1267,6 +1272,9 @@ static int resourced_proc_restore(void *data) return RESOURCED_ERROR_NONE; } + + + int proc_get_freezer_status() { int ret = CGROUP_FREEZER_DISABLED; @@ -1378,11 +1386,11 @@ void proc_set_group(pid_t ownerpid, pid_t childpid, char *pkgname) child_state == PROC_STATE_FOREGROUND) { owner->lru_state = PROC_FOREGROUND; ps.pid = owner->main_pid; - proc_set_oom_score_adj(owner->main_pid, child_oom); + proc_set_oom_score_adj(owner->main_pid, child_oom, owner); } else { if (owner_oom <= OOMADJ_BACKGRD_LOCKED) ps.pid = childpid; - proc_set_oom_score_adj(childpid, owner_oom); + proc_set_oom_score_adj(childpid, owner_oom, owner); } if (!ps.pid) @@ -1452,7 +1460,7 @@ enum proc_state proc_check_suspend_state(struct proc_app_info *pai) return PROC_STATE_DEFAULT; } -/*static const char *convert_status_to_str(int status) +static const char *convert_status_to_str(int status) { static const char *set[] = {"foreground", "active", "backround", "inactive", "launch", "resume", "terminate", @@ -1463,8 +1471,7 @@ enum proc_state proc_check_suspend_state(struct proc_app_info *pai) return "error status"; else return set[status]; -}*/ - +} int resourced_proc_status_change(int status, pid_t pid, char *app_name, char *pkg_name, int apptype) { @@ -1489,7 +1496,7 @@ int resourced_proc_status_change(int status, pid_t pid, char *app_name, char *pk ps.pid = pid; ps.pai = NULL; - //_E("status: %s, app_name: %s, pid: %d, oom_score: %d", convert_status_to_str(status), app_name, pid, oom_score_adj); + _I("[DEBUG] status: %s, app_name: %s, pid: %d, oom_score: %d", convert_status_to_str(status), app_name, pid, oom_score_adj); switch (status) { case PROC_CGROUP_SET_FOREGRD: @@ -1505,7 +1512,7 @@ int resourced_proc_status_change(int status, pid_t pid, char *app_name, char *pk if (apptype == PROC_TYPE_WIDGET || apptype == PROC_TYPE_WATCH) { if (!ps.pai) ps.pai = proc_add_app_info(app_name, pkg_name, pid, 0, 0, apptype, PROC_STATE_FOREGROUND); - proc_set_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED); + proc_set_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED, ps.pai); resourced_notify(RESOURCED_NOTIFIER_WIDGET_FOREGRD, &ps); } else { if (proc_get_freezer_status() != CGROUP_FREEZER_DISABLED && @@ -1513,7 +1520,7 @@ int resourced_proc_status_change(int status, pid_t pid, char *app_name, char *pk resourced_notify(RESOURCED_NOTIFIER_APP_WAKEUP, &ps); snprintf(pidbuf, sizeof(pidbuf), "%d", pid); dbus_proc_handler(PREDEF_FOREGRD, pidbuf); - ret = proc_set_foregrd(pid, oom_score_adj); + ret = proc_set_foregrd(pid, oom_score_adj, ps.pai); if (ret != 0) return RESOURCED_ERROR_NO_DATA; if (ps.pai) @@ -1535,16 +1542,18 @@ int resourced_proc_status_change(int status, pid_t pid, char *app_name, char *pk if (!ps.pai) break; + proc_priority_set_fixed_oom(&ps); + if (apptype == PROC_TYPE_WIDGET) - proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED); + proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED, ps.pai); else - proc_set_oom_score_adj(pid, OOMADJ_INIT); + proc_set_oom_score_adj(pid, OOMADJ_INIT, ps.pai); if (CHECK_BIT(ps.pai->flags, PROC_VIP_ATTRIBUTE)) - proc_set_oom_score_adj(pid, OOMADJ_SU); + proc_set_oom_score_adj(pid, OOMADJ_SU, ps.pai); if (ps.pai->categories) - proc_set_runtime_exclude_list(pid, PROC_EXCLUDE); + proc_set_runtime_exclude_list(pid, PROC_EXCLUDE, ps.pai); resourced_notify(RESOURCED_NOTIFIER_APP_LAUNCH, &ps); if (proc_get_freezer_status() == CGROUP_FREEZER_DISABLED) break; @@ -1565,18 +1574,21 @@ int resourced_proc_status_change(int status, pid_t pid, char *app_name, char *pk ps.pai = proc_add_app_info(app_name, pkg_name, pid, 0, 0, apptype, PROC_STATE_FOREGROUND); if (!ps.pai) break; + + proc_set_default_svc_oomscore(ps.pai->program, ps.pai); + resourced_notify(RESOURCED_NOTIFIER_SERVICE_LAUNCH, &ps); if (!(CHECK_BIT(ps.pai->flags, PROC_BGCTRL_APP)) || ps.pai->categories) - proc_set_runtime_exclude_list(pid, PROC_EXCLUDE); + proc_set_runtime_exclude_list(pid, PROC_EXCLUDE, ps.pai); break; case PROC_CGROUP_SET_RESUME_REQUEST: /* init oom_score_value */ if (!app_name) { - _E("resume request: need app name! pid = %d", pid); + _E("[DEBUG] resume request: need app name! pid = %d", pid); return RESOURCED_ERROR_NO_DATA; } - _SD("resume request: app %s, pid %d", app_name, pid); + _SD("[DEBUG] resume request: app %s, pid %d", app_name, pid); ps.pai = find_app_info(pid); if (!ps.pai) @@ -1588,7 +1600,7 @@ int resourced_proc_status_change(int status, pid_t pid, char *app_name, char *pk ps.pai->lru_state = PROC_ACTIVE; if (apptype == PROC_TYPE_GUI && oom_score_adj >= OOMADJ_FAVORITE) { resourced_notify(RESOURCED_NOTIFIER_APP_RESUME, &ps); - proc_set_oom_score_adj(pid, OOMADJ_INIT); + proc_set_oom_score_adj(pid, OOMADJ_INIT, ps.pai); } if (proc_get_freezer_status() == CGROUP_FREEZER_DISABLED) break; @@ -1625,14 +1637,15 @@ int resourced_proc_status_change(int status, pid_t pid, char *app_name, char *pk ps.pai = find_app_info(pid); if (!ps.pai) ps.pai = proc_add_app_info(app_name, pkg_name, pid, 0, 0, apptype, PROC_STATE_FOREGROUND); - proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_PERCEPTIBLE); + proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_PERCEPTIBLE, ps.pai); if (apptype == PROC_TYPE_WATCH) break; resourced_notify(RESOURCED_NOTIFIER_WIDGET_BACKGRD, &ps); } else { snprintf(pidbuf, sizeof(pidbuf), "%d", pid); dbus_proc_handler(PREDEF_BACKGRD, pidbuf); - ret = proc_set_backgrd(pid, oom_score_adj); + ps.pai = find_app_info(pid); + ret = proc_set_backgrd(pid, oom_score_adj, ps.pai); if (ret != 0) break; @@ -1641,7 +1654,6 @@ int resourced_proc_status_change(int status, pid_t pid, char *app_name, char *pk if (resourced_freezer_proc_late_control()) break; - ps.pai = find_app_info(pid); if (!ps.pai) ps.pai = proc_add_app_info(app_name, pkg_name, pid, 0, 0, apptype, PROC_STATE_BACKGROUND); ps.pid = pid; @@ -1670,7 +1682,7 @@ int resourced_proc_status_change(int status, pid_t pid, char *app_name, char *pk resourced_notify(RESOURCED_NOTIFIER_APP_ACTIVE, &ps); break; case PROC_CGROUP_SET_PROC_EXCLUDE_REQUEST: - proc_set_runtime_exclude_list(pid, PROC_EXCLUDE); + proc_set_runtime_exclude_list(pid, PROC_EXCLUDE, find_app_info(pid)); break; case PROC_CGROUP_SET_TERMINATED: ps.pai = find_app_info(pid); @@ -1682,7 +1694,7 @@ int resourced_proc_status_change(int status, pid_t pid, char *app_name, char *pk break; case PROC_CGROUP_SET_SYSTEM_SERVICE: if (oom_score_adj < OOMADJ_BACKGRD_PERCEPTIBLE) - proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_PERCEPTIBLE); + proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_PERCEPTIBLE, NULL); resourced_notify(RESOURCED_NOTIFIER_SYSTEM_SERVICE, &ps); break; default: diff --git a/src/process/proc-main.h b/src/process/proc-main.h index 56aca18..0663749 100644 --- a/src/process/proc-main.h +++ b/src/process/proc-main.h @@ -76,7 +76,7 @@ int resourced_proc_status_change(int status, pid_t pid, char* app_name, char* p void resourced_proc_dump(int type, const char *path); -resourced_ret_c proc_set_runtime_exclude_list(const int pid, int type); +resourced_ret_c proc_set_runtime_exclude_list(const int pid, int type, struct proc_app_info *pai); struct proc_app_info *proc_add_app_info(const char *appid, const char *pkgid, pid_t pid, int flags, int categories, enum application_type type, enum proc_state state); diff --git a/src/process/proc-monitor.c b/src/process/proc-monitor.c index bc67195..19d2313 100644 --- a/src/process/proc-monitor.c +++ b/src/process/proc-monitor.c @@ -192,7 +192,7 @@ static void dbus_get_checkappstatus(GDBusMethodInvocation *invocation, GVariant pai = find_app_info(pid); if (!pai) { - _D("There is no appid %d", pid); + _D("[DEBUG] There is no appid %d", pid); goto response; } @@ -273,7 +273,7 @@ EXPORT_TEST void dbus_get_app_cpu(GDBusMethodInvocation *invocation, GVariant *p pai = find_app_info_by_appid(appid); if (!pai) { - _E("There is no appid %s", appid); + _E("[DEBUG] There is no appid %s", appid); goto failure; } @@ -306,7 +306,7 @@ EXPORT_TEST void dbus_get_app_memory(GDBusMethodInvocation *invocation, GVariant pai = find_app_info_by_appid(appid); if (!pai || !pai->main_pid) { - _E("There is no appid %s", appid); + _E("[DEBUG] There is no appid %s", appid); goto failure; } @@ -551,12 +551,12 @@ EXPORT_TEST void proc_dbus_exclude_signal_handler(GVariant *params) pe.pid = pid; pe.type = PROC_EXCLUDE; resourced_notify(RESOURCED_NOTIFIER_CONTROL_EXCLUDE, &pe); - proc_set_runtime_exclude_list(pe.pid, pe.type); + proc_set_runtime_exclude_list(pe.pid, pe.type, find_app_info(pe.pid)); } else if (!strncmp(str, "in", 2)) { pe.pid = pid; pe.type = PROC_INCLUDE; resourced_notify(RESOURCED_NOTIFIER_CONTROL_EXCLUDE, &pe); - proc_set_runtime_exclude_list(pe.pid, pe.type); + proc_set_runtime_exclude_list(pe.pid, pe.type, find_app_info(pe.pid)); } } else return; @@ -597,7 +597,7 @@ EXPORT_TEST void proc_dbus_exclude_appid_signal_handler(GVariant *params) ps.pai = find_app_info_by_appid(appid); if (!ps.pai) { - _E("no entry of %s in app list", appid); + _E("[DEBUG] no entry of %s in app list", appid); return; } ps.pid = ps.pai->main_pid; @@ -615,12 +615,12 @@ EXPORT_TEST void proc_dbus_exclude_appid_signal_handler(GVariant *params) pe.pid = ps.pid; pe.type = PROC_EXCLUDE; resourced_notify(RESOURCED_NOTIFIER_CONTROL_EXCLUDE, &pe); - proc_set_runtime_exclude_list(pe.pid, pe.type); + proc_set_runtime_exclude_list(pe.pid, pe.type, ps.pai); } else if (!strncmp(str, "in", 2)) { pe.pid = ps.pid; pe.type = PROC_INCLUDE; resourced_notify(RESOURCED_NOTIFIER_CONTROL_EXCLUDE, &pe); - proc_set_runtime_exclude_list(pe.pid, pe.type); + proc_set_runtime_exclude_list(pe.pid, pe.type, ps.pai); } } else return; @@ -730,7 +730,7 @@ static void proc_dbus_watchdog_handler(GVariant *params) ret = proc_get_cmdline(pid, appname, sizeof appname); if (ret != RESOURCED_ERROR_NONE) { - _E("ERROR : invalid pid(%d)", pid); + _E("[DEBUG] ERROR : invalid pid(%d)", pid); return; } @@ -739,11 +739,11 @@ static void proc_dbus_watchdog_handler(GVariant *params) return; if (current_lcd_state == LCD_STATE_OFF) { - _E("Receive watchdog signal to pid: %d(%s) but don't show ANR popup in LCD off state\n", pid, appname); + _E("[DEBUG] Receive watchdog signal to pid: %d(%s) but don't show ANR popup in LCD off state\n", pid, appname); return; } - _E("Receive watchdog signal to app %s, pid %d\n", appname, pid); + _E("[DEBUG] Receive watchdog signal to app %s, pid %d\n", appname, pid); ps.pai = find_app_info(pid); ps.pid = pid; resourced_notify(RESOURCED_NOTIFIER_APP_ANR, &ps); @@ -829,7 +829,7 @@ EXPORT_TEST void proc_dbus_lcd_off(GVariant *params) EXPORT_TEST void booting_done_signal_handler(GVariant *params) { - _I("booting done"); + _I("[DEBUG] booting done"); modules_init_late(NULL); resourced_notify(RESOURCED_NOTIFIER_BOOTING_DONE, NULL); } diff --git a/src/process/proc-process.c b/src/process/proc-process.c index 488c9ce..066e6ff 100644 --- a/src/process/proc-process.c +++ b/src/process/proc-process.c @@ -48,25 +48,28 @@ enum proc_background_type { PROC_BACKGROUND_ACTIVE, }; -int proc_set_service_oomscore(const pid_t pid, const int oom_score) +int proc_set_service_oomscore(const pid_t pid, const int oom_score, struct proc_app_info *pai) { int service_oom; if (oom_score > 0 && oom_score != OOMADJ_SERVICE_DEFAULT) service_oom = oom_score - OOMADJ_SERVICE_GAP; else service_oom = OOMADJ_SERVICE_DEFAULT; - return proc_set_oom_score_adj(pid, service_oom); + return proc_set_oom_score_adj(pid, service_oom, pai); } -static void proc_set_oom_score_childs(GSList *childs, int oom_score_adj) +static void proc_set_oom_score_childs(struct proc_app_info *pai, int oom_score_adj) { GSList *iter; - if (!childs) + if(!pai) return; - gslist_for_each_item(iter, childs) { - proc_set_oom_score_adj(GPOINTER_TO_PID(iter->data), oom_score_adj); + if (!pai->childs) + return; + + gslist_for_each_item(iter, pai->childs) { + proc_set_oom_score_adj(GPOINTER_TO_PID(iter->data), oom_score_adj, pai); } } @@ -81,7 +84,7 @@ static void proc_set_oom_score_services(int state, GSList *svcs, gslist_for_each_item(iter, svcs) { struct proc_app_info *svc = (struct proc_app_info *)(iter->data); svc->state = state; - proc_set_service_oomscore(svc->main_pid, oom_score_adj); + proc_set_service_oomscore(svc->main_pid, oom_score_adj, svc); } } @@ -106,7 +109,7 @@ static int proc_get_lowest_oom_score(GSList *uiapps) return min_oom_score; } -static int proc_backgrd_manage(int currentpid, int active, int oom_score_adj) +static int proc_backgrd_manage(int currentpid, int active, int oom_score_adj, struct proc_app_info *pai) { pid_t pid = -1; int flag = RESOURCED_NOTIFIER_APP_BACKGRD; @@ -118,14 +121,14 @@ static int proc_backgrd_manage(int currentpid, int active, int oom_score_adj) int freeze_val = 0; GSList *iter; struct proc_program_info *ppi; - struct proc_app_info *pai = find_app_info(currentpid); +// struct proc_app_info *pai = find_app_info(currentpid); int is_favorite = 0; if (proc_get_freezer_status() != CGROUP_FREEZER_DISABLED) freeze_val = resourced_freezer_proc_late_control(); if (!pai) { - _E("can't find app info about pid %d", currentpid); + _E("[DEBUG] can't find app info about pid %d", currentpid); return RESOURCED_ERROR_INVALID_PARAMETER; } @@ -231,8 +234,8 @@ static int proc_backgrd_manage(int currentpid, int active, int oom_score_adj) new_oom = cur_oom + OOMADJ_FAVORITE_APP_INCREASE; _D("FAVORITE : process %d set score %d (beford %d)", pid, new_oom, cur_oom); - proc_set_oom_score_adj(pid, new_oom); - proc_set_oom_score_childs(spi->childs, new_oom); + proc_set_oom_score_adj(pid, new_oom, spi); + proc_set_oom_score_childs(spi, new_oom); } } else { if (spi->lru_state >= PROC_BACKGROUND && @@ -248,8 +251,8 @@ static int proc_backgrd_manage(int currentpid, int active, int oom_score_adj) new_oom = cur_oom + OOMADJ_APP_INCREASE; _D("BACKGRD : process %d set score %d (before %d)", pid, new_oom, cur_oom); - proc_set_oom_score_adj(pid, new_oom); - proc_set_oom_score_childs(spi->childs, new_oom); + proc_set_oom_score_adj(pid, new_oom, spi); + proc_set_oom_score_childs(spi, new_oom); } } fclose(fp); @@ -257,10 +260,10 @@ static int proc_backgrd_manage(int currentpid, int active, int oom_score_adj) } set_oom: - proc_set_oom_score_adj(pai->main_pid, oom_score_adj); + proc_set_oom_score_adj(pai->main_pid, oom_score_adj, pai); /* change oom score about child pids */ - proc_set_oom_score_childs(pai->childs, oom_score_adj); + proc_set_oom_score_childs(pai, oom_score_adj); /* change oom score about grouped service processes */ ppi = pai->program; @@ -272,22 +275,23 @@ set_oom: return RESOURCED_ERROR_NONE; } -static int proc_foregrd_manage(int pid, int oom_score_adj) +static int proc_foregrd_manage(int pid, int oom_score_adj, struct proc_app_info *pai) { int ret = 0; struct proc_program_info *ppi; - struct proc_app_info *pai; +// struct proc_app_info *pai; - pai = find_app_info(pid); +// pai = find_app_info(pid); if (!pai) { - proc_set_oom_score_adj(pid, oom_score_adj); + _E("[DEBUG] process app info is NULL"); + proc_set_oom_score_adj(pid, oom_score_adj, pai); return RESOURCED_ERROR_NO_DATA; } - proc_set_oom_score_adj(pai->main_pid, oom_score_adj); + proc_set_oom_score_adj(pai->main_pid, oom_score_adj, pai); /* change oom score about child pids */ - proc_set_oom_score_childs(pai->childs, oom_score_adj); + proc_set_oom_score_childs(pai, oom_score_adj); pai->lru_state = PROC_FOREGROUND; @@ -405,7 +409,7 @@ int proc_sweep_memory(enum proc_sweep_type type, pid_t callpid) return count; } -int proc_set_foregrd(pid_t pid, int oom_score_adj) +int proc_set_foregrd(pid_t pid, int oom_score_adj, struct proc_app_info *pai) { int ret = 0; @@ -416,17 +420,17 @@ int proc_set_foregrd(pid_t pid, int oom_score_adj) break; case OOMADJ_FOREGRD_LOCKED: case OOMADJ_BACKGRD_LOCKED: - ret = proc_foregrd_manage(pid, OOMADJ_FOREGRD_LOCKED); + ret = proc_foregrd_manage(pid, OOMADJ_FOREGRD_LOCKED, pai); break; case OOMADJ_BACKGRD_UNLOCKED: case OOMADJ_INIT: - ret = proc_foregrd_manage(pid, OOMADJ_FOREGRD_UNLOCKED); + ret = proc_foregrd_manage(pid, OOMADJ_FOREGRD_UNLOCKED, pai); break; default: if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED || (oom_score_adj >= OOMADJ_FAVORITE && oom_score_adj <= OOMADJ_FAVORITE_APP_MAX)) - ret = proc_foregrd_manage(pid, OOMADJ_FOREGRD_UNLOCKED); + ret = proc_foregrd_manage(pid, OOMADJ_FOREGRD_UNLOCKED, pai); else ret = -1; break; @@ -435,7 +439,7 @@ int proc_set_foregrd(pid_t pid, int oom_score_adj) return ret; } -int proc_set_backgrd(int pid, int oom_score_adj) +int proc_set_backgrd(int pid, int oom_score_adj, struct proc_app_info *pai) { int ret = 0; @@ -446,11 +450,11 @@ int proc_set_backgrd(int pid, int oom_score_adj) ret = -1; break; case OOMADJ_FOREGRD_LOCKED: - ret = proc_backgrd_manage(pid, PROC_BACKGROUND_ACTIVE, OOMADJ_BACKGRD_LOCKED); + ret = proc_backgrd_manage(pid, PROC_BACKGROUND_ACTIVE, OOMADJ_BACKGRD_LOCKED, pai); break; case OOMADJ_FOREGRD_UNLOCKED: case OOMADJ_INIT: - ret = proc_backgrd_manage(pid, PROC_BACKGROUND_INACTIVE, OOMADJ_BACKGRD_UNLOCKED); + ret = proc_backgrd_manage(pid, PROC_BACKGROUND_INACTIVE, OOMADJ_BACKGRD_UNLOCKED, pai); break; default: if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED) @@ -476,23 +480,23 @@ int proc_set_active(int pid, int oom_score_adj) break; case OOMADJ_INIT: case OOMADJ_FOREGRD_UNLOCKED: - ret = proc_set_oom_score_adj(pid, OOMADJ_FOREGRD_LOCKED); + ret = proc_set_oom_score_adj(pid, OOMADJ_FOREGRD_LOCKED, find_app_info(pid)); break; case OOMADJ_BACKGRD_UNLOCKED: pai = find_app_info(pid); if (pai) pai->lru_state = PROC_ACTIVE; - ret = proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED); + ret = proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED, pai); break; case OOMADJ_PREVIOUS_BACKGRD: - ret = proc_set_oom_score_adj(pid, OOMADJ_PREVIOUS_DEFAULT); + ret = proc_set_oom_score_adj(pid, OOMADJ_PREVIOUS_DEFAULT, find_app_info(pid)); break; default: if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED) { pai = find_app_info(pid); if (pai) pai->lru_state = PROC_ACTIVE; - ret = proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED); + ret = proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_LOCKED, pai); } else ret = -1; break; @@ -513,7 +517,7 @@ int proc_set_inactive(int pid, int oom_score_adj) ret = -1; break; case OOMADJ_FOREGRD_LOCKED: - ret = proc_set_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED); + ret = proc_set_oom_score_adj(pid, OOMADJ_FOREGRD_UNLOCKED, find_app_info(pid)); break; case OOMADJ_BACKGRD_LOCKED: pai = find_app_info(pid); @@ -522,7 +526,7 @@ int proc_set_inactive(int pid, int oom_score_adj) ps.pid = pid; ps.pai = pai; pai->lru_state = PROC_BACKGROUND; - ret = proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_UNLOCKED); + ret = proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_UNLOCKED, pai); resourced_notify(RESOURCED_NOTIFIER_APP_BACKGRD, &ps); struct proc_program_info *const ppi = pai->program; if (ppi && proc_get_svc_state(ppi) == PROC_STATE_BACKGROUND) diff --git a/src/process/proc-process.h b/src/process/proc-process.h index d1519e8..9f640db 100644 --- a/src/process/proc-process.h +++ b/src/process/proc-process.h @@ -29,6 +29,8 @@ extern "C" { #endif /* __cplusplus */ +#include "proc-common.h" + enum proc_sweep_type { PROC_SWEEP_EXCLUDE_ACTIVE, PROC_SWEEP_INCLUDE_ACTIVE, @@ -36,13 +38,13 @@ enum proc_sweep_type { int proc_sweep_memory(enum proc_sweep_type type, pid_t callpid); -int proc_set_foregrd(int pid, int oom_score_adj); -int proc_set_backgrd(int pid, int oom_score_adj); +int proc_set_foregrd(int pid, int oom_score_adj, struct proc_app_info *pai); +int proc_set_backgrd(int pid, int oom_score_adj, struct proc_app_info *pai); int proc_set_active(int pid, int oom_score_adj); int proc_set_inactive(int pid, int oom_score_adj); -int proc_set_service_oomscore(const pid_t pid, const int oom_score); +int proc_set_service_oomscore(const pid_t pid, const int oom_score, struct proc_app_info *pai); #ifdef __cplusplus } diff --git a/src/resource-limiter/memory/lowmem-dbus.c b/src/resource-limiter/memory/lowmem-dbus.c index 32d8668..0aee635 100644 --- a/src/resource-limiter/memory/lowmem-dbus.c +++ b/src/resource-limiter/memory/lowmem-dbus.c @@ -33,6 +33,7 @@ #include "memory-cgroup.h" #include "procfs.h" #include "util.h" +#include "proc-common.h" static void lowmem_dbus_oom_set_threshold(GVariant *params) { @@ -64,7 +65,7 @@ static void lowmem_dbus_oom_set_leave_threshold(GVariant *params) static void lowmem_dbus_oom_trigger(GVariant *params) { lowmem_trigger_reclaim(OOM_NOMEMORY_CHECK, - MAX_MEMORY_CGROUP_VICTIMS, LMK_OLDEST, 0); + MAX_MEMORY_CGROUP_VICTIMS, CGROUP_LOW, 0); } static void lowmem_dbus_set_perceptible(GVariant *params) @@ -76,7 +77,7 @@ static void lowmem_dbus_set_perceptible(GVariant *params) g_variant_get(params, gtype, &pid); ret_unless(pid > 0); - proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_PERCEPTIBLE); + proc_set_oom_score_adj(pid, OOMADJ_BACKGRD_PERCEPTIBLE, NULL); } static void lowmem_dbus_set_platform(GVariant *params) @@ -102,7 +103,7 @@ static void lowmem_dbus_set_memlimit(GVariant *params) ret_unless(pid > 0); ret_unless(limit > 0); - lowmem_limit_set(pid, limit); + lowmem_limit_set(pid, limit, NULL); } static const struct d_bus_signal dbus_signals[] = { diff --git a/src/resource-limiter/memory/lowmem-handler.h b/src/resource-limiter/memory/lowmem-handler.h index 4130a42..5d1f003 100644 --- a/src/resource-limiter/memory/lowmem-handler.h +++ b/src/resource-limiter/memory/lowmem-handler.h @@ -35,13 +35,13 @@ extern "C" { #define MAX_MEMORY_CGROUP_VICTIMS 10 -enum lmk_type { - LMK_MEMORY, /* Kill all range of apps OOMADJ_INIT ~ OOMADJ_APP_MAX */ - LMK_FOREGROUND, /* Kill foreground apps OOMADJ_INIT ~ OOMADJ_BACKGRD_PERCEPTIBLE */ - LMK_ACTIVE, /* Kill active apps OOMADJ_PREVIOUS_DEFAULT ~ OOMADJ_BACKGRD_LOCKED */ - LMK_RECENTLY_USE, /* Kill recently use apps OOMADJ_FAVORITE ~ OOMADJ_RECENTLY_USED */ - LMK_OLDEST/* Kill only oldest inactive processes OOMADJ_BACKGRD_OLD ~ OOMADJ_APP_MAX */ -}; +/*enum lmk_type { + LMK_MEMORY, // Kill all range of apps OOMADJ_INIT ~ OOMADJ_APP_MAX + LMK_FOREGROUND, // Kill foreground apps OOMADJ_INIT ~ OOMADJ_BACKGRD_PERCEPTIBLE + LMK_ACTIVE, // Kill active apps OOMADJ_PREVIOUS_DEFAULT ~ OOMADJ_BACKGRD_LOCKED + LMK_RECENTLY_USE, // Kill recently use apps OOMADJ_FAVORITE ~ OOMADJ_RECENTLY_USED + LMK_OLDEST// Kill only oldest inactive processes OOMADJ_BACKGRD_OLD ~ OOMADJ_APP_MAX +};*/ struct task_info { /* @@ -62,6 +62,7 @@ struct task_info { */ int oom_score_lru; int size; + struct proc_app_info *pai; }; /** @@ -69,9 +70,10 @@ struct task_info { */ void make_memps_log(enum mem_log path, pid_t pid, char *victim_name); + void lowmem_dbus_init(void); -int lowmem_trigger_reclaim(int flags, int victims, enum lmk_type type, int threshold); -void lowmem_trigger_swap_reclaim(enum lmk_type type, int swap_size); +int lowmem_trigger_reclaim(int flags, int victims, enum cgroup_type type, int threshold); +void lowmem_trigger_swap_reclaim(enum cgroup_type type, int swap_size); void lowmem_change_memory_state(int state, int force); //void lowmem_memcg_set_threshold(int idx, int level, int value); //void lowmem_memcg_set_leave_threshold(int idx, int value); @@ -79,7 +81,7 @@ unsigned long lowmem_get_ktotalram(void); void lowmem_trigger_swap(pid_t pid, int memcg_idx); void lowmem_limit_init(void); void lowmem_limit_exit(void); -void lowmem_limit_set(pid_t pid, unsigned int limit); +void lowmem_limit_set(pid_t pid, unsigned int limit, struct proc_app_info *pai); int lowmem_limit_move_cgroup(struct proc_app_info *pai); void lowmem_reassign_limit(const char *dir, unsigned int limit); unsigned int lowmem_get_task_mem_usage_rss(const struct task_info *tsk); diff --git a/src/resource-limiter/memory/lowmem-limit.c b/src/resource-limiter/memory/lowmem-limit.c index 1c99131..19cd979 100644 --- a/src/resource-limiter/memory/lowmem-limit.c +++ b/src/resource-limiter/memory/lowmem-limit.c @@ -191,7 +191,7 @@ static int make_memlimit_logs(void *data) exec_cmd(ARRAY_SIZE(argv), argv); } - make_memps_log(MEMLOG_MEMPS_MEMLIMIT, mlog->pid, mlog->appname); +// make_memps_log(MEMLOG_MEMPS_MEMLIMIT, mlog->pid, mlog->appname); return RESOURCED_ERROR_NONE; } @@ -596,10 +596,9 @@ static int memlimit_config_parse(struct parse_result *result, void *user_data) return RESOURCED_ERROR_NONE; } -void lowmem_limit_set(pid_t pid, unsigned int limit) +void lowmem_limit_set(pid_t pid, unsigned int limit, struct proc_app_info *pai) { char *cgpath, appname[PROC_NAME_MAX]; - struct proc_app_info *pai = NULL; _cleanup_free_ char *path = NULL; GSList *iter = NULL; int ret; @@ -610,13 +609,16 @@ void lowmem_limit_set(pid_t pid, unsigned int limit) return; } - pai = find_app_info(pid); + /* If process app info is NULL, try to find out it one more time */ + if (!pai) + pai = find_app_info(pid); + if (pai) { cgpath = pai->appid; } else { ret = proc_get_cmdline(pid, appname, sizeof appname); if (ret < 0) { - _E("Failed to get cmdline basename of pid(%d)", pid); + _E("[DEBUG] Failed to get cmdline basename of pid(%d)", pid); return; } cgpath = appname; @@ -624,49 +626,36 @@ void lowmem_limit_set(pid_t pid, unsigned int limit) ret = asprintf(&path, "%s/%s", MEMCG_HIGH_PP_PATH, cgpath); if (ret < 0) { - _E("not enough memory"); + _E("[DEBUG] not enough memory"); return; } + _I("[DEBUG] path=%s/%s", MEMCG_HIGH_PP_PATH, cgpath); + ret = cgroup_make_subdir(MEMCG_HIGH_PP_PATH, cgpath, NULL); if (ret < 0) { - _E("Failed to create cgroup subdir '%s/%s'", + _E("[DEBUG] Failed to create cgroup subdir '%s/%s'", MEMCG_HIGH_PP_PATH, cgpath); return; } lowmem_reassign_limit(path, MBYTE_TO_BYTE(limit)); - ret = cgroup_write_pid_fullpath(path, pid); - if (ret < 0) { - return; - } -/* ret = cgroup_write_node_uint32(path, CGROUP_FILE_NAME, pid); - if (ret < 0) { - _E("Failed to write pid(%d) to '%s/%s'", pid, path, CGROUP_FILE_NAME); - return; - }*/ - ret = cgroup_write_node_uint32(path, MEMCG_MOVE_CHARGE, 3U); if (ret < 0) - _W("Failed to set immigrate mode for %s (non-crucial, continuing)", path); + _W("[DEBUG] Failed to set immigrate mode for %s (non-crucial, continuing)", path); - if (!pai) + if (!pai) { + cgroup_write_pid_fullpath(path, pid); return; + } pai->memory.use_mem_limit = true; - if (!pai->childs) - return; - - gslist_for_each_item(iter, pai->childs) { - pid_t child = GPOINTER_TO_PID(iter->data); - - cgroup_write_pid_fullpath(path, child); -/* ret = cgroup_write_node_uint32(path, CGROUP_FILE_NAME, child); - if (ret < 0) - _E("Failed to write pid(%d) to '%s/%s', ignoring for other children", - child, path, CGROUP_FILE_NAME);*/ + cgroup_write_pid_fullpath(path, pai->main_pid); + if (pai->childs) { + gslist_for_each_item(iter, pai->childs) + cgroup_write_pid_fullpath(path, GPOINTER_TO_PID(iter->data)); } } @@ -676,8 +665,9 @@ static int lowmem_limit_service(void *data) struct proc_status *ps = (struct proc_status *)data; - if (mem_service_limit) - lowmem_limit_set(ps->pid, mem_service_limit); + if (mem_service_limit) { + lowmem_limit_set(ps->pid, mem_service_limit, ps->pai); + } return RESOURCED_ERROR_NONE; } @@ -688,9 +678,9 @@ static int lowmem_limit_appwidget(void *data) struct proc_status *ps = (struct proc_status *)data; if (mem_guiapp_limit && ps->pai->type == PROC_TYPE_GUI) - lowmem_limit_set(ps->pid, mem_guiapp_limit); + lowmem_limit_set(ps->pid, mem_guiapp_limit, ps->pai); if (mem_widget_limit && ps->pai->type == PROC_TYPE_WIDGET) - lowmem_limit_set(ps->pid, mem_widget_limit); + lowmem_limit_set(ps->pid, mem_widget_limit, ps->pai); return RESOURCED_ERROR_NONE; } @@ -701,7 +691,7 @@ static int lowmem_limit_bgapp(void *data) struct proc_status *ps = (struct proc_status *)data; - lowmem_limit_set(ps->pid, mem_bgapp_limit); + lowmem_limit_set(ps->pid, mem_bgapp_limit, ps->pai); return RESOURCED_ERROR_NONE; } @@ -716,7 +706,7 @@ static int lowmem_limit_fgapp(void *data) (mem_widget_limit && ps->pai->type == PROC_TYPE_WIDGET)) return lowmem_limit_appwidget(data); - _E("Unable to set foreground app limit - app type not supported"); + _E("[DEBUG] Unable to set foreground app limit - app type not supported"); return RESOURCED_ERROR_NONE; } diff --git a/src/resource-limiter/memory/vmpressure-lowmem-handler.c b/src/resource-limiter/memory/vmpressure-lowmem-handler.c index bf0aa2a..319ace7 100644 --- a/src/resource-limiter/memory/vmpressure-lowmem-handler.c +++ b/src/resource-limiter/memory/vmpressure-lowmem-handler.c @@ -197,7 +197,9 @@ struct lowmem_control { /* Processing flags*/ unsigned int flags; /* Indictator for OOM score of targeted processes */ - enum lmk_type type; +// enum lmk_type type; + enum cgroup_type type; + /* Desired size to be restored - level to be reached (MB)*/ unsigned int size; /* Max number of processes to be considered */ @@ -335,7 +337,7 @@ static void lowmem_request_destroy(gpointer data) /*-------------------------------------------------*/ /* low memory action function for cgroup */ -static void memory_cgroup_medium_act(enum lmk_type type, struct memcg_info *mi); +static void memory_cgroup_medium_act(enum cgroup_type type, struct memcg_info *mi); /* low memory action function */ static void normal_act(void); static void swap_act(void); @@ -367,14 +369,24 @@ enum memory_level { static GPtrArray *vip_apps; -static const char *convert_type_to_str(int type) +static const char *convert_cgroup_type_to_str(int type) +{ + static const char *type_table[] = + {"/", "VIP", "High", "Medium", "Lowest"}; + if (type >= CGROUP_ROOT && type <= CGROUP_LOW) + return type_table[type]; + else + return "Error"; +} + +/*static const char *convert_type_to_str(int type) { static const char *type_table[] = {"memory", "foreground", "active", "recently_use", "oldest"}; if(type >= LMK_MEMORY && type <= LMK_OLDEST) return type_table[type]; return "error type"; -} +}*/ static const char *convert_status_to_str(int status) { @@ -663,7 +675,8 @@ static int lowmem_kill_victim(const struct task_info *tsk, // make_memps_log(MEMLOG_MEMPS, pid, appname); - pai = find_app_info(pid); +// pai = find_app_info(pid); + pai = tsk->pai; if (pai) { resourced_proc_status_change(PROC_CGROUP_SET_TERMINATE_REQUEST, @@ -687,7 +700,7 @@ static int lowmem_kill_victim(const struct task_info *tsk, else safe_kill(pid, SIGKILL); - _D("we killed, force(%d), %d (%s) score = %d, size: rss = %u, sigterm = %d\n", + _D("[LMK] we killed, force(%d), %d (%s) score = %d, size: rss = %u, sigterm = %d\n", flags & OOM_FORCE, pid, appname, tsk->oom_score_adj, tsk->size, sigterm); *victim_size = tsk->size; @@ -813,7 +826,8 @@ static unsigned int is_memory_recovered(unsigned int *avail, unsigned int thres) return should_be_freed; } -static int lowmem_get_pids_proc(GArray *pids, bool add_app) +//static int lowmem_get_pids_proc(GArray *pids, bool add_app) +static int lowmem_get_pids_proc(GArray *pids) { DIR *dp; struct dirent *dentry; @@ -848,13 +862,19 @@ static int lowmem_get_pids_proc(GArray *pids, bool add_app) continue; } + /* VIP pids should be excluded from the LMK list */ + if (cgroup_get_type(oom) == CGROUP_VIP) + continue; + /* * Check whether this array includes applications or not. * If it doesn't require to get applications * and pid has been already included in pai, * skip to append. */ - if (!add_app && find_app_info(pid)) +/* if (!add_app && find_app_info(pid)) + continue;*/ + if (oom > OOMADJ_SU && oom <= OOMADJ_APP_MAX) continue; /* @@ -867,6 +887,7 @@ static int lowmem_get_pids_proc(GArray *pids, bool add_app) tsk.oom_score_lru = oom; tsk.pids = NULL; tsk.size = lowmem_get_task_mem_usage_rss(&tsk); + tsk.pai = NULL; g_array_append_val(pids, tsk); } @@ -926,6 +947,7 @@ static int lowmem_kill_victims(int max_victims, ti.pid = pai->main_pid; ti.pgid = getpgid(ti.pid); ti.oom_score_adj = oom_score_adj; + ti.pai = pai; /* * Before oom_score_adj of favourite (oom_score = 270) applications is @@ -975,7 +997,8 @@ static int lowmem_kill_victims(int max_victims, * It can find malicious system process even though it has low oom score. */ if (start_oom == OOMADJ_SU) - lowmem_get_pids_proc(candidates, false); + //lowmem_get_pids_proc(candidates, false); + lowmem_get_pids_proc(candidates); if (start_oom <= OOMADJ_BACKGRD_LOCKED || start_oom >= OOMADJ_BACKGRD_OLD) g_array_sort(candidates, (GCompareFunc)compare_victims_point); @@ -1015,7 +1038,7 @@ static int lowmem_kill_victims(int max_victims, if (status != LOWMEM_RECLAIM_CONT) break; - _I("[LMK] select victims from proc_app_list pid(%d)\n", tsk->pid); + _I("[LMK] select victims from proc_app_list pid(%d) with oom_score_adj(%d)\n", tsk->pid, tsk->oom_score_adj); ret = lowmem_kill_victim(tsk, flags, i, &victim_size); if (ret != RESOURCED_ERROR_NONE) @@ -1034,7 +1057,20 @@ leave: return victim; } -static void calualate_range_of_oom(enum lmk_type lmk, int *min, int *max) +static int calculate_range_of_oom(enum cgroup_type type, int *min, int *max) +{ + if (type == CGROUP_VIP || type >= CGROUP_END || type <= CGROUP_TOP) { + _E("[DEBUG] cgroup type (%d) is out of scope", type); + return RESOURCED_ERROR_FAIL; + } + + *max = cgroup_get_highest_oom_score_adj(type); + *min = cgroup_get_lowest_oom_score_adj(type); + + return RESOURCED_ERROR_NONE; +} + +/*static void calualate_range_of_oom(enum lmk_type lmk, int *min, int *max) { if (lmk == LMK_OLDEST) { *max = OOMADJ_APP_MAX; @@ -1048,11 +1084,11 @@ static void calualate_range_of_oom(enum lmk_type lmk, int *min, int *max) } else if (lmk == LMK_FOREGROUND) { *max = OOMADJ_BACKGRD_PERCEPTIBLE; *min = OOMADJ_SU; - } else { /* lmk == LMK_MEMORY */ + } else { *max = OOMADJ_APP_MAX; *min = OOMADJ_SU; } -} +}*/ static void lowmem_handle_request(struct lowmem_control *ctl) { @@ -1064,7 +1100,8 @@ static void lowmem_handle_request(struct lowmem_control *ctl) unsigned int total_size = 0; unsigned int current_size = 0; unsigned int reclaim_size, shortfall = 0; - enum lmk_type lmk_type = ctl->type; +// enum lmk_type lmk_type = ctl->type; + enum cgroup_type cgroup_type = ctl->type; available = proc_get_mem_available(); reclaim_size = ctl->size > available @@ -1077,7 +1114,10 @@ static void lowmem_handle_request(struct lowmem_control *ctl) retry: /* Prepare LMK to start doing it's job. Check preconditions. */ - calualate_range_of_oom(lmk_type, &start_oom, &end_oom); +// calualate_range_of_oom(lmk_type, &start_oom, &end_oom); + if (calculate_range_of_oom(cgroup_type, &start_oom, &end_oom)) + goto done; + lmk_start_threshold = get_root_memcg_info()->threshold[LOWMEM_MEDIUM]; shortfall = is_memory_recovered(&available, ctl->size); @@ -1086,7 +1126,7 @@ retry: goto done; } _D("[LMK] before reclaim: available=%uMB, type=%s", - available, convert_type_to_str(lmk_type)); + available, convert_cgroup_type_to_str(cgroup_type)); /* precaution */ current_size = 0; @@ -1123,40 +1163,19 @@ retry: (Make sluggish or kill same victims continuously) Thus, otherwise, just return in first operation and wait some period. */ - if (lmk_type == LMK_OLDEST) { - //_D("[LMK] Oldest wasn't enough, lets try in RECENTLY USED."); - lmk_type = LMK_RECENTLY_USE; + if (cgroup_type == CGROUP_LOW) { + cgroup_type = CGROUP_MEDIUM; goto retry; - } else if (lmk_type == LMK_RECENTLY_USE) { - /* We tried in inactive processes and didn't succed, try immediatly in active */ - //_D("[LMK] Recenlty used wasn't enough, lets try in Active."); - lmk_type = LMK_ACTIVE; - - /* - * In case of force reclaim, leave threshold is harger than original threshold as margin. - * So it should be reduced when trying to kill applications in ACTIVE group - * in order to prevent aggresive killing of perceptible applications. - */ - if (ctl->flags & OOM_FORCE) - max_victim_cnt = MAX_PROACTIVE_LOW_VICTIMS; - goto retry; - } else if ((lmk_type == LMK_ACTIVE) && (ctl->flags & OOM_IN_DEPTH)) { - /* We tried in inactive processes and didn't succed, try immediatly in active */ - //_D("[LMK] Recenlty used wasn't enough, lets try in foreground."); - lmk_type = LMK_FOREGROUND; + } else if ((cgroup_type == CGROUP_MEDIUM) && (ctl->flags & OOM_IN_DEPTH)) { + cgroup_type = CGROUP_HIGH; if(ctl->flags & OOM_FORCE) max_victim_cnt = FOREGROUND_VICTIMS; goto retry; - } else if ((lmk_type == LMK_FOREGROUND) && (ctl->flags & OOM_IN_DEPTH)) { - /* - * We tried in INACTIVE and ACTIVE but still didn't succeed - * so it's time to try in /proc. Before doing it wait some time. - */ + } else if ((cgroup_type == CGROUP_HIGH) && (ctl->flags & OOM_IN_DEPTH)) { status = LOWMEM_RECLAIM_RETRY; - ctl->type = LMK_MEMORY; - //_D("[LMK] We would need to kill from /proc wait some time and try again"); + ctl->type = CGROUP_ROOT; } - else if (lmk_type == LMK_MEMORY) { + else if (cgroup_type == CGROUP_ROOT) { status = LOWMEM_RECLAIM_RETRY; } done: @@ -1272,13 +1291,30 @@ static void lowmem_swap_memory(enum cgroup_type type, struct memcg_info *mi) void lowmem_trigger_swap(pid_t pid, int memcg_idx) { + int error; + int oom_score_adj; + int lowest_oom_score_adj; struct memcg_info *mi; struct swap_status_msg msg; mi = get_memcg_info(memcg_idx); // mi = memcg_tree[memcg_idx]->info; - _D("name : %s, pid : %d", mi->name, pid); - cgroup_write_pid_fullpath(mi->name, pid); + _D("[DEBUG] name : %s, pid : %d", mi->name, pid); + + error = proc_get_oom_score_adj(pid, &oom_score_adj); + if (error) { + _E("[DEBUG] Cannot get oom_score_adj of pid (%d)", pid); + return; + } + + lowest_oom_score_adj = cgroup_get_lowest_oom_score_adj(memcg_idx); + + if (oom_score_adj < lowest_oom_score_adj) + oom_score_adj = lowest_oom_score_adj; + + proc_set_oom_score_adj(pid, oom_score_adj, NULL); + + //cgroup_write_pid_fullpath(mi->name, pid); //cgroup_write_node_uint32(mi->name, CGROUP_FILE_NAME, pid); msg.type = memcg_idx; msg.memcg_info = mi; @@ -1442,11 +1478,12 @@ static void medium_act(void) change_lowmem_state(LOWMEM_MEDIUM); if (available < get_root_memcg_info()->threshold_leave) { - struct lowmem_control *ctl = LOWMEM_NEW_REQUEST(); + struct lowmem_control *ctl; + ctl = LOWMEM_NEW_REQUEST(); if (ctl) { LOWMEM_SET_REQUEST(ctl, OOM_IN_DEPTH, - LMK_OLDEST, get_root_memcg_info()->threshold_leave, + CGROUP_LOW, get_root_memcg_info()->threshold_leave, num_max_victims, medium_cb); lowmem_queue_request(&lmw, ctl); } @@ -1512,7 +1549,7 @@ static void lowmem_dump_cgroup_procs(struct memcg_info *mi) g_array_free(pids_array, true); } -static void memory_cgroup_medium_act(enum lmk_type type, struct memcg_info *mi) +static void memory_cgroup_medium_act(enum cgroup_type type, struct memcg_info *mi) { struct lowmem_control *ctl; @@ -1862,90 +1899,74 @@ static void setup_memcg_params(void) }*/ - -static void lowmem_move_memcgroup(int pid, int oom_score_adj) +static void lowmem_move_memcgroup(int pid, int next_oom_score_adj, struct proc_app_info *pai) { - struct proc_app_info *pai = find_app_info(pid); + int cur_oom_score_adj; + int cur_memcg_idx; struct memcg_info *mi; - int ret, memcg_idx, should_swap = 0; + int next_memcg_idx = cgroup_get_type(next_oom_score_adj); - if (!pai) + if(next_memcg_idx < CGROUP_VIP || next_memcg_idx > CGROUP_LOW) { + _E("[DEBUG] cgroup type (%d) should not be called", next_memcg_idx); return; + } + mi = get_memcg_info(next_memcg_idx); - if (oom_score_adj >= OOMADJ_BACKGRD_PERCEPTIBLE && - oom_score_adj < OOMADJ_BACKGRD_UNLOCKED) { - /* We'd like lowmem a chance to do a bit more with some - * long-lived processes such as background-locked or - * favourite apps. This is ideally done with a separate - * memcg because: - * - Page reclamation in resourced is by design done - * on a per-cgroup basis, not per-process - * - The only way to control per-process memory is to - * abort the individual process, which means LMK. - * The favourites and most background-locked processes - * are the final candidates of LMK (ACTIVE or MEMORY) - * and their memory consumption is most of the time - * unhandled by resourced. - * - Bg-locked and fav processes are not even candidates - * for swap since swap is only available for bg-unlocked - * processes (the swap module doesn't even care about - * clean pages as it sets move_charge_at_immigrate=1). - * - The only remaining practice left for us would be to - * control the Apps memcg, but that is undesirable since - * active processes can share it. - * Therefore, we distinguish between active and background - * non-unlocked processes to enable optional advanced page - * management in userspace. A separate memcg won't affect - * the other aspects of lowmem and swap if there is no set - * action for it. */ - if (pai->memory.memcg_idx == CGROUP_MEDIUM) - return; - memcg_idx = CGROUP_MEDIUM; -// mi = memcg_tree[memcg_idx]->info; - mi = get_memcg_info(memcg_idx); - } else if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED + OOMADJ_APP_INCREASE) { - if (oom_score_adj != pai->memory.oom_score_adj) - proc_set_process_memory_state(pai, pai->memory.memcg_idx, - pai->memory.memcg_info, oom_score_adj); - return; - } else if (oom_score_adj >= OOMADJ_INIT) { - memcg_idx = CGROUP_HIGH; -// mi = memcg_tree[memcg_idx]->info; - mi = get_memcg_info(memcg_idx); - - if (oom_score_adj >= OOMADJ_FAVORITE) - should_swap = 1; - } else + if (!mi) { return; + } - /* - * Check whether this application has memory limit cgroup or not. - * If it is moved to memory limit cgroup, - * it is no necessary to control memcg any longer. - * Stop other operation and return. - */ - if (memcg_idx == CGROUP_HIGH) { - ret = lowmem_limit_move_cgroup(pai); - if (!ret) { -// memcg_idx = MEMCG_LIMIT; -// mi = memcg_tree[memcg_idx]->info; - mi = get_memcg_info(memcg_idx); - proc_set_process_memory_state(pai, memcg_idx, mi, oom_score_adj); + if (!pai) { + pai = find_app_info(pid); + if (!pai) { + cgroup_write_pid_fullpath(mi->name, pid); return; } } - cgroup_write_pid_fullpath(mi->name, pid); - //cgroup_write_node_uint32(mi->name, CGROUP_FILE_NAME, pid); - proc_set_process_memory_state(pai, memcg_idx, mi, oom_score_adj); - /* - * We should first move process to cgroup and then start reclaim on that - * cgroup. - */ - if (should_swap) -// lowmem_swap_memory(memcg_idx, memcg_tree[memcg_idx]->info); - lowmem_swap_memory(memcg_idx, mi); + /* parent pid */ + if (pai->main_pid == pid) { + cur_oom_score_adj = pai->memory.oom_score_adj; + cur_memcg_idx = cgroup_get_type(cur_oom_score_adj); + + /* -1 means that this pid is not yet registered at the memory cgroup + * plz, reference proc_create_app_info function + */ + if (cur_oom_score_adj != -1) { + /* VIP processes should not be asked to move. */ + if (cur_memcg_idx <= CGROUP_VIP) { + _E("[DEBUG] current cgroup (%s) cannot be VIP or Root", convert_cgroup_type_to_str(cur_memcg_idx)); + return; + } + } + //DEBUG + _I("[DEBUG] app (%s) memory cgroup move from %s to %s", pai->appid, convert_cgroup_type_to_str(cur_memcg_idx), convert_cgroup_type_to_str(next_memcg_idx)); + + if (cur_oom_score_adj == next_oom_score_adj) { + _D("[DEBUG] next oom_score_adj (%d) is same with current one", next_oom_score_adj); + return; + } + + proc_set_process_memory_state(pai, next_memcg_idx, mi, next_oom_score_adj); + + if (!lowmem_limit_move_cgroup(pai)) + return; + + if(cur_memcg_idx == next_memcg_idx) + return; + + cgroup_write_pid_fullpath(mi->name, pid); + if (next_memcg_idx == CGROUP_LOW) + lowmem_swap_memory(next_memcg_idx, mi); + } + /* child pid */ + else { + if (pai->memory.use_mem_limit) + return; + + cgroup_write_pid_fullpath(mi->name, pid); + } } static int lowmem_activate_worker(void) @@ -2019,7 +2040,7 @@ static void lowmem_press_root_cgroup_handler(void) prev_available = available; } -static void lowmem_press_cgroup_handler(enum lmk_type type, struct memcg_info *mi) +static void lowmem_press_cgroup_handler(enum cgroup_type type, struct memcg_info *mi) { unsigned int usage, threshold; int ret; @@ -2040,54 +2061,40 @@ static void lowmem_press_cgroup_handler(enum lmk_type type, struct memcg_info *m static bool lowmem_press_eventfd_handler(int fd, void *data) { - int i; - struct cgroup *cgroup; +// struct cgroup *cgroup; struct memcg_info *mi; - GSList *iter = NULL; - enum lmk_type lmk_type = LMK_MEMORY; +// GSList *iter = NULL; + enum cgroup_type type = CGROUP_ROOT; // FIXME: probably shouldn't get ignored if (lowmem_press_eventfd_read(fd) < 0) - _E("Failed to read lowmem press event, %m\n"); + _E("[DEBUG] Failed to read lowmem press event, %m\n"); - for (i = CGROUP_ROOT; i < CGROUP_END; i++) { - if (!get_memcg_info(i)) -// if (!memcg_tree[i] || !memcg_tree[i]->info) - if (!get_cgroup_tree(i) || !get_memcg_info(i)) + for (type = CGROUP_ROOT; type < CGROUP_END; type++) { + if (!get_cgroup_tree(type) || !get_memcg_info(type)) continue; - mi = get_memcg_info(i); -// mi = memcg_tree[i]->info; + mi = get_memcg_info(type); if (fd == mi->evfd) { /* call low memory handler for this memcg */ - if (i == CGROUP_ROOT) + if (type == CGROUP_ROOT) lowmem_press_root_cgroup_handler(); else { - if (i == CGROUP_HIGH) - lmk_type = LMK_ACTIVE; - else if (i == CGROUP_LOW) - lmk_type = LMK_OLDEST; - lowmem_press_cgroup_handler(lmk_type, mi); + lowmem_press_cgroup_handler(type, mi); } return true; } - /* ToDo: iterate child memcgs */ // gslist_for_each_item(iter, memcg_tree[i]->cgroups) - gslist_for_each_item(iter, get_child_cgroups(i)) +/* gslist_for_each_item(iter, get_child_cgroups(type)) { cgroup = (struct cgroup *)(iter->data); mi = cgroup->memcg_info; -// mi = (struct memcg_info *)(iter->data); if (fd == mi->evfd) { - if (i == CGROUP_HIGH) - lmk_type = LMK_ACTIVE; - else if (i == CGROUP_LOW) - lmk_type = LMK_OLDEST; - lowmem_press_cgroup_handler(lmk_type, mi); - _D("lowmem cgroup handler is called for %s", + lowmem_press_cgroup_handler(type, mi); + _D("[DEBUG] lowmem cgroup handler is called for %s", mi->name); return true; } - } + }*/ } return true; @@ -2123,11 +2130,9 @@ static int lowmem_press_setup_eventfd(void) unsigned int i; for (i = CGROUP_ROOT; i < CGROUP_END; i++) { -// if (!memcg_tree[i]->use_hierarchy) if (!get_use_hierarchy(i)) continue; -// lowmem_press_register_eventfd(memcg_tree[i]->info); lowmem_press_register_eventfd(get_memcg_info(i)); } return RESOURCED_ERROR_NONE; @@ -2138,7 +2143,7 @@ static void lowmem_force_reclaim_cb(struct lowmem_control *ctl) lowmem_change_memory_state(LOWMEM_NORMAL, 0); } -int lowmem_trigger_reclaim(int flags, int victims, enum lmk_type type, int threshold) +int lowmem_trigger_reclaim(int flags, int victims, enum cgroup_type type, int threshold) { struct lowmem_control *ctl = LOWMEM_NEW_REQUEST(); @@ -2147,7 +2152,7 @@ int lowmem_trigger_reclaim(int flags, int victims, enum lmk_type type, int thres flags |= OOM_FORCE | OOM_IN_DEPTH | OOM_SINGLE_SHOT; victims = victims > 0 ? victims : MAX_MEMORY_CGROUP_VICTIMS; - type = type > 0 ? type : LMK_OLDEST; + type = type > 0 ? type : CGROUP_LOW; threshold = threshold > 0 ? threshold : get_root_memcg_info()->threshold_leave; lowmem_change_memory_state(LOWMEM_LOW, 1); @@ -2159,7 +2164,7 @@ int lowmem_trigger_reclaim(int flags, int victims, enum lmk_type type, int thres return 0; } -void lowmem_trigger_swap_reclaim(enum lmk_type type, int swap_size) +void lowmem_trigger_swap_reclaim(enum cgroup_type type, int swap_size) { int size, victims; @@ -2167,7 +2172,7 @@ void lowmem_trigger_swap_reclaim(enum lmk_type type, int swap_size) ? MAX_PROACTIVE_HIGH_VICTIMS : num_max_victims; size = get_root_memcg_info()->threshold_leave + BYTE_TO_MBYTE(swap_size); - _I("reclaim from swap module, type : %d, size : %d, victims: %d", type, size, victims); + _I("[DEBUG] reclaim from swap module, type : %d, size : %d, victims: %d", type, size, victims); lowmem_trigger_reclaim(0, victims, type, size); } @@ -2236,7 +2241,8 @@ static void lowmem_proactive_oom_killer(int flags, char *appid) _D("history based proactive LMK : avg rss %u, available %u required = %u MB", rss, before, size); - lowmem_trigger_reclaim(0, victims, LMK_OLDEST, size); + //lowmem_trigger_reclaim(0, victims, LMK_OLDEST, size); + lowmem_trigger_reclaim(0, victims, CGROUP_LOW, size); return; } @@ -2268,7 +2274,8 @@ reclaim: */ _D("Run threshold based proactive LMK: memory level to reach: %u\n", proactive_leave + THRESHOLD_MARGIN); - lowmem_trigger_reclaim(0, victims, LMK_OLDEST, proactive_leave + THRESHOLD_MARGIN); + //lowmem_trigger_reclaim(0, victims, LMK_OLDEST, proactive_leave + THRESHOLD_MARGIN); + lowmem_trigger_reclaim(0, victims, CGROUP_LOW, proactive_leave + THRESHOLD_MARGIN); } unsigned int lowmem_get_proactive_thres(void) @@ -2288,15 +2295,15 @@ static int lowmem_prelaunch_handler(void *data) return RESOURCED_ERROR_NONE; } -static int lowmem_control_handler(void *data) +int lowmem_control_handler(void *data) { struct lowmem_control_data *lowmem_data; lowmem_data = (struct lowmem_control_data *)data; switch (lowmem_data->control_type) { case LOWMEM_MOVE_CGROUP: - lowmem_move_memcgroup((pid_t)lowmem_data->args[0], - (int)lowmem_data->args[1]); + lowmem_move_memcgroup((pid_t)lowmem_data->pid, + lowmem_data->oom_score_adj, lowmem_data->pai); break; default: break; @@ -2372,7 +2379,7 @@ static int set_vip_list(void) continue; if (pid > 0) { - proc_set_oom_score_adj(pid, OOMADJ_SERVICE_MIN); + proc_set_oom_score_adj(pid, OOMADJ_SERVICE_MIN, NULL); break; } } diff --git a/src/resource-optimizer/memory/dedup/.dedup.c.swp b/src/resource-optimizer/memory/dedup/.dedup.c.swp deleted file mode 100644 index 3cfa9a4e917bea48e93636fdea3648e4f293f855..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeI3U5wmT6~`SKTBaow0nI}M;j(i0Pn1mxS5?Xa%ZNQ6T{m?K^_f(iadFDj-k`{I9>p_RN+P z@r3S3zs%0L=N{ktKiBs7%*{^wg1kZQZMFrx-Yy6y@Bf*;^WMjVcO4gm$O$56WK+u8 zUgwqjHQwKDs~wTODIIa9$0u^fR%jhirxm!7Z_t*f8<+Kw<&0WBO-yDh@QwUa!}UUI zj2?b#OvkRj-!iEgdC9*`W9B&Az!l&M%v0c)aQDh`e5#*ZcprJ^JGSOIaT`~FE5H@t z3UCFu0$c&E09Sx3@PDd6=-n)Q5_5Y~I=_e0_al|}f2FTar}j@(+W(ohe<8KsmIlb; zyq2~_68&`lUz!l&Ma0R#mTmh~CSAZ+P z72pbR1-Jrp6wpmUxEb~)d!EMc|Jn2ZYqtx+%ixdT>)>nPL2v^6>1~4W2k>L?1PDP3 z{O*__Tn7hW0zwb~4`|>VSO?4CJ>VAb=eG*Nufa3m``|iw7>t1e?ga!K1Ao6w5MBbm z2hV}0!1urx!2!@f2Q{AL_C#j}#4sr@)Mb4@2$nwRG5&WKiL z_rS^}a++Kf;z>^Dgu&N^+Vt~ujwSQ#gi6hY36$*R@t!8_xv`#r7Ozqlc7+(&j?*QUCYhrfrdwKUbmE{KiArfTa_SKLm#4~w3< zR$?FKE%n5;u2ga^tfP3ZQgVi5E2%gtcBW)&38_P(EHg`#J0x*$GIq_#rb$j|Nd0N* zDxt7iik7*#tN6?&s^U<}N~JANL&aXwdVX8Qnuv%~DqGV9-I7)PdQ!~jZMqt>E$+FN zd1|$IUMF!`yP-Ra`RT(xY0#O%J99s)#2eJeQqqS7)UXqc`WR*pm!v#y)e*5A>}R_n zXWa;`JzQ32+_O=zi%~8{Xz6x5at&tcW4T}~@rus}Gxd)Ld;@;N$UY=!drnk{fKx8i zOls@u9z+!Hzxn40Su8d8}CUWJ*l&)Ia|7G)dO)Mt@z>di|c1 zcPd2AMnD~X2d70fe8IEoF=v>m{*ECWP`jHW)C$i>x!F19%vzY-Jvis%if@GbbUDA@M7Vi2~H_?l@9up{z zU258i923%{_oqbDKJJO}?J57bE{Ppgz96bnem261o$#g4xKHjYuh)@tGWBZf(6S57oW0iXgDE) z72RyhiLSJ4*Y(QwWJ_+t82N5gX$tm(d=qcE6Kk0>5?Ik)x>9$c*fqt+h>2kv^hir{7zb zRk`28r!z$CZIknIZ@o^ag+uy;Uh%LWJ0LiuHTGfK2#rxjUhbxH>Uh51)o5o%N8#-cMa|wv#AenZWeobkZvZ^+Gl-T2Uu-N6`rYqT4ZMdK7%X|J@2f+sF) z&nJ>ijnH=;%LquvZPrN_>zs(TP2vtrWL$CflI*cr<(ur;Vr0+%XYp+P9AMA?+3)K= z!gKx)!FRy7z&F7j2*D}v8$9oS8FayUPzQH`qu?g+BA)G8J>Yrp1Mn!g1|9^f;2${N z-@sqfV?WD|&tF^tt^iknE5H@t3UCFu0$c&E09W9RDS*=9R#(yn(pg!-k41}j=9R{@ z(snATv^DXtXk6C($YGTTEr>kN^+Qwv^9Ll9IPw3CwYh#MkTvNQYo0&KUZ~<9Q08Je zb6uF3H9Pv4)h`#~11&I%=UXlwby;CGok&)&LOFD>A$IFo4f8*j6cK|J0EL=Q!^n5Y zKvMc!gO0SWNrORukk(g)nkFwMBglSem{@px+@W~ZO=e=UCsCo6$YIi~WQrOzE15&q z#kf6kd^*C@KlQb&K(;tNX0NZxXJly*m*?c(S#2HV-FjLFWff&s0ykZURp4tk7%Hh` zDr$c-3lxN|r==CRHy#L;&O8wNLEyg*q>2MIj}+>DSO|4B%OI=NR~K6*dHl--etAIY RkFD1{he#z$#s5m^e*^nhD=z>5 diff --git a/src/resource-optimizer/memory/dedup/dedup.c b/src/resource-optimizer/memory/dedup/dedup.c index ebd2363..88d6131 100644 --- a/src/resource-optimizer/memory/dedup/dedup.c +++ b/src/resource-optimizer/memory/dedup/dedup.c @@ -189,7 +189,7 @@ static int dedup_check_and_scanning_once(enum ksm_scan_mode mode) static int dedup_scanning_once(enum ksm_scan_mode mode) { int ret; - _D("Invoke scanning once to KSM (mode: %d)", mode); + _D("[DEDUP] Invoke scanning once to KSM (mode: %d)", mode); ret = dedup_check_and_scanning_once(mode); return ret; @@ -365,7 +365,7 @@ static int dedup_do_scan(enum ksm_scan_mode scan_mode) } if (mode != KSM_SCAN_NONE) { - _I("dedup: %d-th %s deduplication triggering", nr_dedup++, + _I("[DEDUP] dedup: %d-th %s deduplication triggering", nr_dedup++, (mode == KSM_SCAN_FULL ? "FULL" : "PARTIAL")); if (!dedup_on_lowmem) { dedup_scanning_once(KSM_SCAN_FULL); @@ -428,7 +428,7 @@ static int dedup_stop_handler(void *data) static gboolean dedup_activate_timer_cb(gpointer data) { dedup_activating_timer = NULL; - _D("dedup activating callback called"); + _D("[DEDUP] dedup activating callback called"); dedup_activate_in_module(); return false; } @@ -441,7 +441,7 @@ static int dedup_booting_done(void *data) if (dedup_at_boot_enable) { /* if dedup_at_boot_enable is disabled, * other daemon should activate dedup */ - _D("dedup booting done is called"); + _D("[DEDUP] dedup booting done is called"); if (dedup_at_boot_delay > 0) dedup_activating_timer = g_timeout_source_new_seconds(dedup_at_boot_delay); @@ -594,18 +594,18 @@ static int dedup_parse_config_file(void) dedup_partial_scan_interval /= 1000; dedup_full_scan_interval /= 1000; - _I("deduplication mode: %s", dedup_mode == DEDUP_MODE_PERIODIC ? + _I("[DEDUP] deduplication mode: %s", dedup_mode == DEDUP_MODE_PERIODIC ? "kernel-managed" : "resourced-triggered"); - _I("deduplication on boot: %s", dedup_at_boot_enable ? "true" : "false"); - _I("scanning is invoked by %s", dedup_on_lowmem ? + _I("[DEDUP] deduplication on boot: %s", dedup_at_boot_enable ? "true" : "false"); + _I("[DEDUP] scanning is invoked by %s", dedup_on_lowmem ? "LOWMEM event" : "periodic timer"); - _I("full scan interval: %d sec", dedup_full_scan_interval); + _I("[DEDUP] full scan interval: %d sec", dedup_full_scan_interval); _I("stat monitoring interval: %d sec", dedup_stat_interval); - _I("ksm pages to scan: %d", arg_ksm_pages_to_scan); - _I("ksm sleep time: %d", arg_ksm_sleep); - _I("ksm full scan interval: %d", arg_ksm_full_scan_interval); - _I("ksm scan boost: %d", arg_ksm_scan_boost); + _I("[DEDUP] ksm pages to scan: %d", arg_ksm_pages_to_scan); + _I("[DEDUP] ksm sleep time: %d", arg_ksm_sleep); + _I("[DEDUP] ksm full scan interval: %d", arg_ksm_full_scan_interval); + _I("[DEDUP] ksm scan boost: %d", arg_ksm_scan_boost); return 0; } diff --git a/src/resource-optimizer/memory/swap/fileswap.c b/src/resource-optimizer/memory/swap/fileswap.c index 2f783c9..91fbb1d 100644 --- a/src/resource-optimizer/memory/swap/fileswap.c +++ b/src/resource-optimizer/memory/swap/fileswap.c @@ -93,9 +93,9 @@ static int swap_file_reclaim(void *data) * It means that there are many background processes or * some process makes memory leak. * So, it requires to trigger proactive oom killer - * with LMK_MEMORY type. + * with CGROUP_ROOT type. */ - lowmem_trigger_swap_reclaim(LMK_MEMORY, swap_size); + lowmem_trigger_swap_reclaim(CGROUP_ROOT, swap_size); return -ENOSPC; } diff --git a/src/resource-optimizer/memory/swap/swap.c b/src/resource-optimizer/memory/swap/swap.c index eca812b..d22866a 100644 --- a/src/resource-optimizer/memory/swap/swap.c +++ b/src/resource-optimizer/memory/swap/swap.c @@ -78,7 +78,7 @@ enum swap_thread_op { SWAP_OP_ACTIVATE, SWAP_OP_RECLAIM, SWAP_OP_COMPACT, - SWAP_OP_MOVE_TO_SWAP_AND_RECLAIM, +// SWAP_OP_MOVE_TO_SWAP_AND_RECLAIM, SWAP_OP_END, }; @@ -193,21 +193,37 @@ static inline void swap_add_bundle(struct swap_thread_bundle *bundle) static int swap_move_to_cgroup_by_pid(enum cgroup_type type, pid_t pid) { - int ret; - struct cgroup *cgroup_swap = NULL; - struct memcg_info *mi; + int error; + int oom_score_adj; + int lowest_oom_score_adj; struct proc_app_info *pai = find_app_info(pid); GSList *iter_child = NULL; - cgroup_swap = get_cgroup_tree((int)type); - if(!cgroup_swap) + error = proc_get_oom_score_adj(pid, &oom_score_adj); + if (error) { + _E("[DEBUG] Cannot get oom_score_adj of pid (%d)", pid); return RESOURCED_ERROR_FAIL; -/* ret = lowmem_get_memcg(type, &memcg_swap); - if (ret != RESOURCED_ERROR_NONE) - return RESOURCED_ERROR_FAIL;*/ + } + + lowest_oom_score_adj = cgroup_get_lowest_oom_score_adj(type); + + if (oom_score_adj < lowest_oom_score_adj) + oom_score_adj = lowest_oom_score_adj; - mi = cgroup_swap->memcg_info; if (!pai) + return proc_set_oom_score_adj(pid, oom_score_adj, pai); + + proc_set_oom_score_adj(pai->main_pid, oom_score_adj, pai); + + if (!pai->childs) + return RESOURCED_ERROR_NONE; + + gslist_for_each_item(iter_child, pai->childs) { + pid_t child = GPOINTER_TO_PID(iter_child->data); + error = proc_set_oom_score_adj(child, oom_score_adj, pai); + } + +/* if (!pai) return cgroup_write_pid_fullpath(mi->name, pid); ret = cgroup_write_pid_fullpath(mi->name, pai->main_pid); @@ -216,13 +232,16 @@ static int swap_move_to_cgroup_by_pid(enum cgroup_type type, pid_t pid) ret = cgroup_write_pid_fullpath(mi->name, child); } pai->memory.memcg_idx = CGROUP_LOW; - pai->memory.memcg_info = mi; - return ret; + pai->memory.memcg_info = mi;*/ + return error; } -static int swap_move_to_cgroup(struct memcg_info *info, GArray *candidates) +/*static int swap_move_to_cgroup(struct memcg_info *info, GArray *candidates) { int index; + int error = RESOURCED_ERROR_NONE; + int oom_score_adj; + int lowest_oom_score_adj; struct swap_task tsk; struct proc_app_info *pai = NULL; GSList *iter_child = NULL; @@ -233,39 +252,57 @@ static int swap_move_to_cgroup(struct memcg_info *info, GArray *candidates) for (index = 0; index < candidates->len; index++) { tsk = g_array_index(candidates, struct swap_task, index); pai = tsk.pai; - cgroup_write_pid_fullpath(info->name, pai->main_pid); + + if (!pai) { + _E("[DEBUG] Cannot find out proc_app_info"); + continue; + } + + error = proc_get_oom_score_adj(pai->main_pid, &oom_score_adj); + if (error) { + _E("[DEBUG] Cannot get oom_score_adj of pid (%d)", pai->main_pid); + continue; + } + + lowest_oom_score_adj = cgroup_get_lowest_oom_score_adj(CGROUP_LOW); + + if (oom_score_adj < lowest_oom_score_adj) + oom_score_adj = lowest_oom_score_adj; + + proc_set_oom_score_adj(pai->main_pid, oom_score_adj, pai); + if (!pai->childs) + continue; + gslist_for_each_item(iter_child, pai->childs) { pid_t child = GPOINTER_TO_PID(iter_child->data); - cgroup_write_pid_fullpath(info->name, child); + error = proc_set_oom_score_adj(child, oom_score_adj, pai); } - pai->memory.memcg_idx = CGROUP_LOW; - pai->memory.memcg_info = info; } - return RESOURCED_ERROR_NONE; -} + return error; +}*/ -static int swap_sort_by_oom(const struct swap_task *ta, +/*static int swap_sort_by_oom(const struct swap_task *ta, const struct swap_task *tb) { - /* sort by oom score adj */ + // sort by oom score adj assert(ta != NULL); assert(tb != NULL); return ((int)(tb->pai->memory.oom_score_adj) - (int)(ta->pai->memory.oom_score_adj)); -} +}*/ -static int swap_sort_by_vmrss(const struct swap_task *ta, +/*static int swap_sort_by_vmrss(const struct swap_task *ta, const struct swap_task *tb) { - /* sort by task memory usage */ + // sort by task memory usage assert(ta != NULL); assert(tb != NULL); return ((int)(tb->size) - (int)(ta->size)); -} +}*/ -static int swap_reduce_victims(GArray *candidates, int max) +/*static int swap_reduce_victims(GArray *candidates, int max) { int index; struct swap_task tsk; @@ -279,7 +316,7 @@ static int swap_reduce_victims(GArray *candidates, int max) tsk = g_array_index(candidates, struct swap_task, index); pai = tsk.pai; - /* Measuring VmRSS is OK as it's anonymous + swapcache */ + // Measuring VmRSS is OK as it's anonymous + swapcache if (proc_get_approx_mem_usage(pai->main_pid, &usage) < 0) continue; @@ -296,17 +333,17 @@ static int swap_reduce_victims(GArray *candidates, int max) } } } - /* sort by oom_score_adj value, older are better candidates */ + // sort by oom_score_adj value, older are better candidates g_array_sort(candidates, (GCompareFunc)swap_sort_by_oom); - /* sort by memory usage, swapping bigger will free more memory */ + // sort by memory usage, swapping bigger will free more memory g_array_sort(candidates, (GCompareFunc)swap_sort_by_vmrss); - /* limit the number of potential candidates, after sort by oom */ + // limit the number of potential candidates, after sort by oom g_array_remove_range(candidates, max, candidates->len - max); return RESOURCED_ERROR_NONE; -} +}*/ static int swap_use_hard_limit(char *memcg) { @@ -481,14 +518,13 @@ static int swap_reclaim_memcg(struct swap_status_msg msg) return swap_start_reclaim(info->name); } -static int swap_move_inactive_to_swap(struct swap_status_msg *msg) +/*static int swap_move_inactive_to_swap(struct swap_status_msg *msg) { GSList *proc_app_list = NULL; GSList *iter; int ret, max_victims; struct swap_task victim; GArray *candidates = NULL; -// struct memcg *memcg_swap = NULL; struct cgroup *cgroup_swap = NULL; struct proc_app_info *pai = NULL; @@ -510,9 +546,6 @@ static int swap_move_inactive_to_swap(struct swap_status_msg *msg) victim.pai = pai; g_array_append_val(candidates, victim); } - /* - * Let's consider 50% of inactive apps to be swappable at once. - */ max_victims = candidates->len >> 1; if (max_victims == 0) { ret = RESOURCED_ERROR_NO_DATA; @@ -522,13 +555,7 @@ static int swap_move_inactive_to_swap(struct swap_status_msg *msg) cgroup_swap = get_cgroup_tree(CGROUP_LOW); if(!cgroup_swap) goto out; -/* ret = lowmem_get_memcg(CGROUP_LOW, &memcg_swap); - if (ret != RESOURCED_ERROR_NONE) - goto out;*/ - /* - * change swap info from inactive cgroup to swap group - * for using same structure to move and swap it - */ + msg->memcg_info = cgroup_swap->memcg_info; msg->type = CGROUP_LOW; ret = swap_move_to_cgroup(msg->memcg_info, candidates); @@ -537,7 +564,7 @@ out: g_array_free(candidates, TRUE); return ret; -} +}*/ static int gen_urandom_string(char *buf, size_t len) { @@ -751,7 +778,7 @@ static void swap_activate_in_module(void) static void *swap_thread_main(void * data) { - int is_empty, ret; + int is_empty; struct swap_thread_bundle *bundle; setpriority(PRIO_PROCESS, 0, SWAP_PRIORITY); @@ -789,12 +816,11 @@ static void *swap_thread_main(void * data) swap_compact_in_module(); break; /* Move inactive procesess to swap, and reclaim after that. */ - case SWAP_OP_MOVE_TO_SWAP_AND_RECLAIM: +/* case SWAP_OP_MOVE_TO_SWAP_AND_RECLAIM: ret = swap_move_inactive_to_swap(&(bundle->msg)); - /* Check if any process was moved to swap. */ if (ret == RESOURCED_ERROR_NONE) swap_reclaim_memcg(bundle->msg); - break; + break;*/ case SWAP_OP_END: default: _D("wrong swap thread operation selected"); @@ -827,7 +853,7 @@ static int swap_communicate_thread(struct swap_thread_bundle *bundle) return RESOURCED_ERROR_NONE; } - _E("pthread_mutex_trylock fail: %d, errno: %d", ret, errno); + _E("[DEBUG] pthread_mutex_trylock fail: %d, errno: %d", ret, errno); return RESOURCED_ERROR_FAIL; } @@ -846,12 +872,9 @@ static int swap_start_handler(void *data) bundle->op = SWAP_OP_RECLAIM; memcpy(&(bundle->msg), data, sizeof(struct swap_status_msg)); - if (bundle->msg.type == CGROUP_HIGH) { - /* - * Background tasks are concerned special way, we select - * tasks and move them to Swap cgroup. They are not there already. - */ - bundle->op = SWAP_OP_MOVE_TO_SWAP_AND_RECLAIM; + if (bundle->msg.type <= CGROUP_HIGH) { + _E("[DEBUG] swap op should be done on CGROUP Medium or Lowest"); + return RESOURCED_ERROR_FAIL; } ret = swap_communicate_thread(bundle); return ret; diff --git a/src/resource-optimizer/memory/swap/zramswap.c b/src/resource-optimizer/memory/swap/zramswap.c index 4edbae4..1e951a3 100644 --- a/src/resource-optimizer/memory/swap/zramswap.c +++ b/src/resource-optimizer/memory/swap/zramswap.c @@ -190,7 +190,7 @@ static int swap_zram_reclaim(void *data) */ if (lowmem_fragmentated()) { if (zram_compact) { - lowmem_trigger_swap_reclaim(LMK_MEMORY, zram_control.zram_reclaim_bytes); + lowmem_trigger_swap_reclaim(CGROUP_ROOT, zram_control.zram_reclaim_bytes); zram_compact = false; } else { swap_zram_compact(); @@ -226,14 +226,14 @@ static int swap_zram_reclaim(void *data) if (!swap_total) swap_total = proc_get_swap_total(); - r = memcg_get_swap_usage(MEMCG_LOW_PATH, &swap_usage); + r = memcg_get_swap_usage(MEMCG_LOW_GROUP_PATH, &swap_usage); if (r) return r; swapcg_usage_ratio = (float)(swap_usage / (swap_total - swap_available) *100); if (swapcg_usage_ratio > SWAPCG_CHECK_RATIO) - type = LMK_OLDEST; + type = CGROUP_LOW; else - type = LMK_MEMORY; + type = CGROUP_ROOT; lowmem_trigger_swap_reclaim(type, zram_control.zram_reclaim_bytes); zram_compact = false; diff --git a/src/resource-optimizer/memory/swap/zswap.c b/src/resource-optimizer/memory/swap/zswap.c index bae4dab..1dfe847 100644 --- a/src/resource-optimizer/memory/swap/zswap.c +++ b/src/resource-optimizer/memory/swap/zswap.c @@ -107,7 +107,7 @@ static int swap_zswap_reclaim(void *data) * So, it requires to trigger proactive oom killer. */ - lowmem_trigger_swap_reclaim(LMK_MEMORY, swap_size); + lowmem_trigger_swap_reclaim(CGROUP_ROOT, swap_size); return -ENOSPC; } diff --git a/tests/cmocka-proc-dbus-typecheck.c b/tests/cmocka-proc-dbus-typecheck.c index c7d0298..45b8d72 100644 --- a/tests/cmocka-proc-dbus-typecheck.c +++ b/tests/cmocka-proc-dbus-typecheck.c @@ -272,10 +272,11 @@ void __wrap_resourced_notify(enum notifier_type status, void *data) check_expected_ptr(data); } -resourced_ret_c __wrap_proc_set_runtime_exclude_list(const int pid, int type) +resourced_ret_c __wrap_proc_set_runtime_exclude_list(const int pid, int type, struct proc_app_info *pai) { check_expected(pid); check_expected(type); + check_expected(pai); return mock_type(resourced_ret_c); } @@ -333,6 +334,7 @@ static void test_proc_dbus_exclude_appid_signal_handler(void **state) expect_value(__wrap_proc_set_runtime_exclude_list, pid, pe.pid); expect_value(__wrap_proc_set_runtime_exclude_list, type, pe.type); + expect_value(__wrap_proc_set_runtime_exclude_list, pai, &pai); will_return(__wrap_proc_set_runtime_exclude_list, RESOURCED_ERROR_NONE); proc_dbus_exclude_appid_signal_handler(params); g_variant_unref(params); @@ -350,6 +352,7 @@ static void test_proc_dbus_exclude_appid_signal_handler(void **state) expect_value(__wrap_proc_set_runtime_exclude_list, pid, pe.pid); expect_value(__wrap_proc_set_runtime_exclude_list, type, pe.type); + expect_value(__wrap_proc_set_runtime_exclude_list, pai, &pai); will_return(__wrap_proc_set_runtime_exclude_list, RESOURCED_ERROR_NONE); proc_dbus_exclude_appid_signal_handler(params); g_variant_unref(params); @@ -367,6 +370,7 @@ static void test_proc_dbus_exclude_appid_signal_handler(void **state) expect_value(__wrap_proc_set_runtime_exclude_list, pid, pe.pid); expect_value(__wrap_proc_set_runtime_exclude_list, type, pe.type); + expect_value(__wrap_proc_set_runtime_exclude_list, pai, &pai); will_return(__wrap_proc_set_runtime_exclude_list, RESOURCED_ERROR_NONE); proc_dbus_exclude_appid_signal_handler(params); @@ -385,6 +389,7 @@ static void test_proc_dbus_exclude_appid_signal_handler(void **state) expect_value(__wrap_proc_set_runtime_exclude_list, pid, pe.pid); expect_value(__wrap_proc_set_runtime_exclude_list, type, pe.type); + expect_value(__wrap_proc_set_runtime_exclude_list, pai, &pai); will_return(__wrap_proc_set_runtime_exclude_list, RESOURCED_ERROR_NONE); proc_dbus_exclude_appid_signal_handler(params); @@ -400,6 +405,7 @@ struct proc_app_info *__wrap_find_app_info(const pid_t pid) static void test_proc_dbus_exclude_signal_handler(void **state) { (void) state; /*unused*/ + struct proc_app_info pai = {}; GVariant *params = g_variant_new("(si)", NULL, 0); __real_proc_dbus_exclude_signal_handler(params); @@ -419,8 +425,13 @@ static void test_proc_dbus_exclude_signal_handler(void **state) expect_value(__wrap_resourced_notify, status, RESOURCED_NOTIFIER_CONTROL_EXCLUDE); expect_check(__wrap_resourced_notify, data, check_data_in_resourced_notify_exclude, &((struct proc_exclude){.pid = 1416, .type = PROC_EXCLUDE})); + + expect_value(__wrap_find_app_info, pid, 1416); + will_return(__wrap_find_app_info, &pai); + expect_value(__wrap_proc_set_runtime_exclude_list, pid, 1416); expect_value(__wrap_proc_set_runtime_exclude_list, type, PROC_EXCLUDE); + expect_value(__wrap_proc_set_runtime_exclude_list, pai, &pai); will_return(__wrap_proc_set_runtime_exclude_list, RESOURCED_ERROR_NONE); __real_proc_dbus_exclude_signal_handler(params); @@ -430,8 +441,13 @@ static void test_proc_dbus_exclude_signal_handler(void **state) expect_value(__wrap_resourced_notify, status, RESOURCED_NOTIFIER_CONTROL_EXCLUDE); expect_memory(__wrap_resourced_notify, data, &((struct proc_exclude){.pid = 3213, .type = PROC_INCLUDE}), sizeof(struct proc_exclude)); + expect_value(__wrap_find_app_info, pid, 3213); + will_return(__wrap_find_app_info, &pai); + + expect_value(__wrap_proc_set_runtime_exclude_list, pid, 3213); expect_value(__wrap_proc_set_runtime_exclude_list, type, PROC_INCLUDE); + expect_value(__wrap_proc_set_runtime_exclude_list, pai, &pai); will_return(__wrap_proc_set_runtime_exclude_list, RESOURCED_ERROR_NONE); __real_proc_dbus_exclude_signal_handler(params); diff --git a/tests/lowmem-dbus-env.cpp b/tests/lowmem-dbus-env.cpp index 2c71d36..7f0e522 100644 --- a/tests/lowmem-dbus-env.cpp +++ b/tests/lowmem-dbus-env.cpp @@ -48,7 +48,7 @@ void LowmemDbusEnv::memcg_set_leave_threshold(int type, int value) check_expected(value); } -int LowmemDbusEnv::lowmem_trigger_reclaim(int flags, int victims, enum lmk_type type, int threshold) +int LowmemDbusEnv::lowmem_trigger_reclaim(int flags, int victims, enum cgroup_type type, int threshold) { check_expected(flags); check_expected(victims); @@ -70,10 +70,11 @@ void LowmemDbusEnv::lowmem_trigger_swap(pid_t pid, int memcg_idx) check_expected(memcg_idx); } -void LowmemDbusEnv::lowmem_limit_set(pid_t pid, unsigned int limit) +void LowmemDbusEnv::lowmem_limit_set(pid_t pid, unsigned int limit, struct proc_app_info *pai) { check_expected(pid); check_expected(limit); + check_expected(pai); } void LowmemDbusEnv::trigger_signal_oom_set_threshold(GVariant *gv) diff --git a/tests/lowmem-dbus-env.hpp b/tests/lowmem-dbus-env.hpp index e8c47a2..952690f 100644 --- a/tests/lowmem-dbus-env.hpp +++ b/tests/lowmem-dbus-env.hpp @@ -30,10 +30,10 @@ public: void memcg_set_threshold(int type, int level, int value); void memcg_set_leave_threshold(int type, int value); - int lowmem_trigger_reclaim(int flags, int victims, enum lmk_type type, int threshold); + int lowmem_trigger_reclaim(int flags, int victims, enum cgroup_type type, int threshold); int proc_set_oom_score_adj(int pid, int oom_score_adj); void lowmem_trigger_swap(pid_t pid, int memcg_idx); - void lowmem_limit_set(pid_t pid, unsigned int limit); + void lowmem_limit_set(pid_t pid, unsigned int limit, struct proc_app_info *pai); // events void trigger_signal_oom_set_threshold(GVariant *gv); diff --git a/tests/lowmem-dbus-mock.cpp b/tests/lowmem-dbus-mock.cpp index 2108c61..e8725e1 100644 --- a/tests/lowmem-dbus-mock.cpp +++ b/tests/lowmem-dbus-mock.cpp @@ -28,8 +28,9 @@ MOCK_DBUS(void, memcg_set_threshold, (int type, int level, int value), (type, level, value)) MOCK_DBUS(void, memcg_set_leave_threshold, (int type, int value), (type, value)) -MOCK_DBUS(int, lowmem_trigger_reclaim, (int flags, int victims, enum lmk_type type, int threshold), +MOCK_DBUS(int, lowmem_trigger_reclaim, (int flags, int victims, enum cgroup_type type, int threshold), (flags, victims, type, threshold)) MOCK_DBUS(int, proc_set_oom_score_adj, (int pid, int oom_score_adj), (pid, oom_score_adj)) MOCK_DBUS(void, lowmem_trigger_swap, (pid_t pid, int memcg_idx), (pid, memcg_idx)) -MOCK_DBUS(void, lowmem_limit_set, (pid_t pid, unsigned int limit), (pid, limit)) +MOCK_DBUS(void, lowmem_limit_set, (pid_t pid, unsigned int limit, struct proc_app_info *pai), + (pid, limit, pai)) diff --git a/tests/lowmem-dbus-test.cpp b/tests/lowmem-dbus-test.cpp index 0d536e8..a8ff32d 100644 --- a/tests/lowmem-dbus-test.cpp +++ b/tests/lowmem-dbus-test.cpp @@ -53,7 +53,7 @@ void test_lowmem_trigger(LowmemDbusEnv &env) { expect_value(lowmem_trigger_reclaim, flags, OOM_NOMEMORY_CHECK); expect_value(lowmem_trigger_reclaim, victims, MAX_MEMORY_CGROUP_VICTIMS); - expect_value(lowmem_trigger_reclaim, type, LMK_OLDEST); + expect_value(lowmem_trigger_reclaim, type, CGROUP_LOW); expect_value(lowmem_trigger_reclaim, threshold, 0); env.trigger_signal_oom_trigger(g_variant_new("()")); @@ -84,6 +84,7 @@ void test_lowmem_set_memlimit(LowmemDbusEnv &env, int pid, unsigned int limit) if (pid > 0 && limit > 0) { expect_value(lowmem_limit_set, pid, pid); expect_value(lowmem_limit_set, limit, limit); + expect_value(lowmem_limit_set, pai, NULL); } env.trigger_signal_oom_set_memlimit(g_variant_new("(iu)", pid, limit)); -- 2.7.4 From 66dd7d5b474c7745a6a47bae87314468d85ddca0 Mon Sep 17 00:00:00 2001 From: Unsung Lee Date: Fri, 4 Feb 2022 18:22:04 +0900 Subject: [PATCH 11/16] Modify configurations delete old style configuration files and create new configuration files Change-Id: I11e0cf2d9856f41aea81675b880271d4abd16143 Signed-off-by: Unsung Lee --- CMakeLists.txt | 1 + conf/README | 454 +++++++++++++++++++++ conf/block.conf | 10 - conf/cpu-sched.conf | 1 - conf/cpu.conf | 15 - conf/dedup.conf | 38 -- conf/limiter-profile-iot-headless.conf | 81 ++++ conf/limiter-profile-tv.conf | 54 +++ conf/limiter.conf | 52 +++ conf/memory-profile-iot-headless.conf | 237 ----------- conf/memory-profile-tv.conf | 168 -------- conf/memory.conf | 237 ----------- conf/{heart.conf => monitor.conf} | 2 - conf/optimizer.conf | 42 ++ conf/process.conf | 19 +- conf/swap.conf | 33 -- packaging/resourced.spec | 31 +- src/CMakeLists.txt | 26 +- src/common/cgroup/cgroup.h | 3 + src/common/cgroup/memory-cgroup.c | 1 - src/common/config-parser.c | 6 +- src/common/dedup-common.h | 2 +- src/common/swap-common.h | 2 +- src/process/block/block.c | 6 +- src/process/priority/proc-priority.c | 3 +- src/process/vip/vip-process.c | 21 +- src/resource-limiter/cpu/cpu-sched.c | 6 +- src/resource-limiter/cpu/cpu.c | 10 +- src/resource-limiter/memory/lowmem-limit.c | 4 +- .../memory/vmpressure-lowmem-handler.c | 254 ++++++++---- src/resource-monitor/battery/heart-battery.c | 9 +- src/resource-monitor/heart.c | 2 +- src/resource-monitor/heart.h | 2 +- .../memory/compaction}/compaction.c | 15 +- src/resource-optimizer/memory/dedup/dedup.c | 42 +- src/resource-optimizer/memory/swap/zramswap.c | 4 +- 36 files changed, 973 insertions(+), 920 deletions(-) create mode 100644 conf/README delete mode 100644 conf/block.conf delete mode 100644 conf/cpu-sched.conf delete mode 100644 conf/cpu.conf delete mode 100644 conf/dedup.conf create mode 100644 conf/limiter-profile-iot-headless.conf create mode 100644 conf/limiter-profile-tv.conf create mode 100644 conf/limiter.conf delete mode 100644 conf/memory-profile-iot-headless.conf delete mode 100644 conf/memory-profile-tv.conf delete mode 100644 conf/memory.conf rename conf/{heart.conf => monitor.conf} (91%) create mode 100644 conf/optimizer.conf delete mode 100644 conf/swap.conf rename src/{resource-limiter/memory => resource-optimizer/memory/compaction}/compaction.c (97%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c30bd5..b8b205f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,7 @@ SET(RESOURCE_OPTIMIZER_SOURCE_DIR ${SOURCE_DIR}/resource-optim SET(MEMORY_RESOURCE_OPTIMIZER_SOURCE_DIR ${RESOURCE_OPTIMIZER_SOURCE_DIR}/memory) SET(DEDUP_SOURCE_DIR ${RESOURCE_OPTIMIZER_SOURCE_DIR}/memory/dedup) SET(SWAP_SOURCE_DIR ${RESOURCE_OPTIMIZER_SOURCE_DIR}/memory/swap) +SET(COMPACTION_SOURCE_DIR ${RESOURCE_OPTIMIZER_SOURCE_DIR}/memory/compaction) #resource-limiter source folders SET(RESOURCE_LIMITER_SOURCE_DIR ${SOURCE_DIR}/resource-limiter) diff --git a/conf/README b/conf/README new file mode 100644 index 0000000..9ab1b08 --- /dev/null +++ b/conf/README @@ -0,0 +1,454 @@ +Resourced Configurations +======================== + +File Names +========== +1. limiter.conf : configurations to limit resources +2. optimizer.conf : configurations to optimize resources +3. monitor.conf : configurations to monitor resources +4. process.conf : configurations to manage process + +Sections +======== +Section name should be located between '[' and ']'. +The order between sections does not matter and +the order of configurations within a section is also not important. + +1. limiter.conf +=============== + +1.1 VIP_PROCESS +=============== +Format: PREDEFINE= +Comment: add vip processes in this section. + these processes will be located in the VIP cgroup (maximum cpu and memory) and + they won't be killed by a low memory killer(LMK). +ex)PREDEFINE=app1 + PREDEFINE=app2 + +1.2 OOM_FIXED_APPS +================== +Format: APP NAME= +Comment: add app names with their oom_score_adjs in this section. + do not set the score with the predefined scores described at the procfs.h. + the range of SCORE should be OOMADJ_SERVICE_MIN < SCORE < OOMADJ_BACKGRD_LOCKED +ex)app1=323 + app2=415 + +1.3 Memory +========== +Format: ThresholdDedup= +Comment: specify threshold(MB) of dedup level +ex)ThresholdDedup=30 + +Format: ThresholdSwap= +Comment: specify threshold(MB) of swap level +ex)ThresholdSwap=20 + +Format: ThresholdLow= +Comment: specify threshold(MB) of low level +ex)ThresholdLow=15 + +Format: ThresholdMedium= +Comment: specify threshold(MB) of medium level +ex)ThresholdMedium=10 + +Format: ThresholdLeave= +Comment: specify threshold leave of medium level +ex)ThresholdLeave=20 + +Format: ThresholdRatioDedup= +Comment: specify threshold ratio(%) of dedup level +ex)ThresholdRatioDedup=30 + +Format: ThresholdRatioSwap= +Comment: specify threshold ratio(%) of swap level +ex)ThresholdRatioSwap=25 + +Format: ThresholdRatioLow= +Comment: specify threshold ratio(%) of low level +ex)ThresholdRatioLow=20 + +Format: ThresholdRatioMedium= +Comment: specify threshold ratio(%) of medium level +ex)ThresholdRatioMedium=15 + +Format: ThresholdRatioLeave= +Comment: specify threshold leave ratio(%) of medium level +ex)ThresholdRatioLeave=30 + +Format: ForegroundRatio= +Comment: specify memory limit ratio(0.0<= ratio <=1.0) of foreground apps(High cgroup) +ex)ForegroundRatio=0.3 + +Format: BackgroundRatio= +Comment: specify memory limit ratio(0.0<= ratio <=1.0) of background apps(Medium cgroup). + Unset this option if it causes any unexepcted issue (e.g. jerky animation). +ex)BackgroundRatio=0.2 + +Format: LowRatio= +Comment: specify memory limit ratio(0.0<= ratio <=1.0) of old background apps(Lowest cgroup) +ex)LowRatio=0.1 + +Format: NumMaxVictims=<#victim> +Comment: specify the number of victims +ex)NumMaxVictims=10 + +Format: ProactiveThreshold= +Comment: specify threshold(MB) of proactive memory killer +ex)ProactiveThreshold=30 + +Format: ProactiveLeave= +Comment: specify threshold leave(MB) of proactive memory killer +ex)ProactiveLeave=50 + +Format: EventLevel= +Comment: specify the level of vmpressure among (low, medium, critical) +ex)EventLevel="low" + +Format: SWAPPINESS= +Comment: specify swappiness of the root cgroup +ex)SWAPPINESS=6 + +Format: FOREGROUND_SWAPPINESS= +Comment: specify swappiness of the High cgroup +ex)FOREGROUND_SWAPPINESS=6 + +Format: BACKGROUND_SWAPPINESS= +Comment: specify swappiness of the Medium cgroup +ex)BACKGROUND_SWAPPINESS=6 + +Format: LOW_SWAPPINESS= +Comment: specify swappiness of the Lowest cgroup +ex)LOW_SWAPPINESS=6 + +Format: NumFragSize= +Comment: specify external fragmentation size of "Normal" zone. + the fragmentation_size is the minimum count of order-2 pages in the kernel zone. + if #32K_PAGE + (#64K_PAGE * 2) + (#128K_PAGE * 4) + (#256K_PAGE * 8) < NumFragSize, + then compact memory in the kernel zone. +ex)NumFragSize=300 + +1.4 POPUP +========= +Format: oom_popup= +Comment: specify whether a popup is needed or not when the process is killed by LMK or + proactive killer +ex)oom_popup=no + +1.5 BackgroundReclaim +===================== +Format: AfterScreenDim= +Comment: specify whether background memory reclaim is needed when LCD_OFF signal is caught. + This will cause force reclaim or memory limit on Medium cgroup. +ex)AfterScreenDim=yes + +1.6 Logging +=========== +Format: Enable=<1 or 0> +Comment: specify whether logging is needed or not. + if "Enable" value is 1, then resourced makes a memps log during LMK. +ex)Enable=1 + +Format: LogPath= +Comment: specify logging path +ex)LogPath=/var/log + +Format: MaxNumLogfile= +Comment: specify maximum number of log files +ex)MaxNumLogfile=50 + +Format: PrefixMemps= +Comment: specify prefix of memps log file +ex)PrefixMemps=memps + +Format: PrefixMempsMemLimit= +Comment: specify prefix of memps log file for apps managed by independent cgroup +ex)PrefixMemps=memps_per_app + +1.7 MemLimit +============ +Format: MemLimitTrigger= +Comment: specify type (oom, threshold, others) of trigger for apps managed by independent cgroup + 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 +ex)MemLimitTrigger=oom + +Format: MemLimit= +Comment: specify meory limit(MB) for app +ex)MemLimitService=128 (service type app) + MemLimitWidget=128 (widget type app) + MemLimitGUIApp=128 (guiapp type app) + MemLimitBgApp=100 (background state app) + +1.8 CPU +======= +Format: PREDEFINE= +Comment: specify type and its app name. + it makes effect of cpu cgroup, cpu priority, and iopriority +ex)LAZY_PREDEFINE=app1 + PREDEFINE=app2 + BOOTING_PREDEFINE=app3 + WRT_PREDEFINE=app4 + +Format: BACKGROUND_CPU_SHARE= +Comment: specify ratio(%) of background cpu share(= Medium cgroup/root cgroup * 100) +ex)BACKGROUND_CPU_SHARE=50 + +Format: QUOTA_CPU_SHARE= +Comment: specify ratio(%) of quota cpu share(= Lowest cgroup/root cgroup * 100) +ex)QUOTA_CPU_SHARE=25 + +Format: QUOTA_MAX_BANDWIDTH= +Comment: specify ratio(%s) of quota cpu bandwidth + (cpu.cfs_quota_us = cpu.cfs_period_us * ratio/100) +ex)QUOTA_MAX_BANDWIDTH=100 + +1.9 CPU-SCHED +============= +Format: foreground=,- +Comment: specify cpu affinity of each core +ex)foreground=1,2,3-5 + +2. optimizer.conf +================= + +2.1 SWAP +======== +Format: Enable=<1 or 0> +Comment: specify whether swap is needed or not. + Enable=yes or 1 or true / Disalbe=no or 0 or false. + to prevent thrashing, do not set "ReclaimAtBootThreshold" too low. +ex)Enable=1 + +Format: Type= +Comment: specify swap type among (zram, file, zswap). + multiple swap devices are specified with '+'. + for example, both zram and file are enable by zram+file (default is zram). +ex)Type=zram + +Format: ReclaimAtBoot= +Comment: specify whether reclaim is needed at boot time +ex)ReclaimAtBoot=yes + +Format: TimerReclaimAtBoot=