summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDongwoo Lee <dwoo08.lee@samsung.com>2023-01-12 21:39:12 +0900
committerDongwoo Lee <dwoo08.lee@samsung.com>2023-02-07 09:14:04 -0800
commit60fc91b3c4d56826ca216341e235c47bcecf36d3 (patch)
tree04a595f44f17225e19978c36c33c63a8f1b43668
parenta512645a82743e746463e73271426a57d1a8c3b9 (diff)
downloadpass-60fc91b3c4d56826ca216341e235c47bcecf36d3.tar.gz
pass-60fc91b3c4d56826ca216341e235c47bcecf36d3.tar.bz2
pass-60fc91b3c4d56826ca216341e235c47bcecf36d3.zip
resource: system: Add MEMORY_PRESSURE_LEVEL attribute
This adds the new attribute for representing pressure level of memory as follows: - Name: SYSTEM_ATTR_MEMORY_PRESSURE_LEVEL - Type: SYSCOMMON_RESMAN_DATA_TYPE_INT - Description: this attribute represents the current stall level for memory, which means how long delays memory allocation due to memory leakage. The level ranges between 0 and 4 (higher is worse). Change-Id: Ibdce4a983384743e2316967744ac843a6ebb15e2 Signed-off-by: Dongwoo Lee <dwoo08.lee@samsung.com>
-rw-r--r--lib/resource-monitor/resource-monitor.h1
-rw-r--r--src/resource/resource-system.c214
-rw-r--r--tools/resource-monitor/resource-monitor.c2
3 files changed, 217 insertions, 0 deletions
diff --git a/lib/resource-monitor/resource-monitor.h b/lib/resource-monitor/resource-monitor.h
index 6e0e249..e65bb9f 100644
--- a/lib/resource-monitor/resource-monitor.h
+++ b/lib/resource-monitor/resource-monitor.h
@@ -118,6 +118,7 @@ extern "C" {
#define SYSTEM_ATTR_PER_CPU_SYS_UTIL BIT(5) /* SYSCOMMON_RESMAN_DATA_TYPE_ARRAY(DOUBLE) */
#define SYSTEM_ATTR_POSSIBLE_CPU BIT(6) /* SYSCOMMON_RESMAN_DATA_TYPE_INT */
#define SYSTEM_ATTR_ONLINE_CPU BIT(7) /* SYSCOMMON_RESMAN_DATA_TYPE_INT */
+#define SYSTEM_ATTR_MEMORY_PRESSURE_LEVEL BIT(8) /* SYSCOMMON_RESMAN_DATA_TYPE_INT */
/* Process Resource */
#define PROCESS_ATTR_CPU_UTIL BIT(0) /* SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE */
diff --git a/src/resource/resource-system.c b/src/resource/resource-system.c
index 4f90c71..7940663 100644
--- a/src/resource/resource-system.c
+++ b/src/resource/resource-system.c
@@ -23,15 +23,19 @@
*/
#include <glib.h>
+#include <unistd.h>
+#include <fcntl.h>
#include <hal/hal-power.h>
#include <util/common.h>
#include <util/log.h>
#include <util/kernel.h>
+#include <util/thread.h>
#include <libsyscommon/resource-manager.h>
#include <libsyscommon/resource-type.h>
+#include <libsyscommon/resource-listener.h>
#include <resource-monitor/resource-monitor.h>
@@ -40,6 +44,8 @@ struct system_resource_data {
int num_online_cpus;
struct cpu_stat *prev_cpus;
struct cpu_stat *curr_cpus;
+ int memory_pressure_level;
+ u_int64_t memory_pressure_last_update;
};
static double __calculate_cpu_util(int64_t id, struct cpu_stat *prev,
@@ -183,6 +189,201 @@ static int system_get_cpu_num(int resource_id,
return 0;
}
+#define PSI_MEMORY_GLOBAL "/proc/pressure/memory"
+#define PSI_TYPE_WARN "some"
+#define PSI_TYPE_CRITICAL "full"
+#define PSI_EVENT_DEBOUNCE_TIME 2000 /* msec */
+#define PSI_EVENT_RESOLVE_CHECK_RATE 3000 /* msec */
+
+enum {
+ MEM_LEVEL_HIGH,
+ MEM_LEVEL_MEDIUM,
+ MEM_LEVEL_LOW,
+ MEM_LEVEL_CRITICAL,
+ MEM_LEVEL_OOM,
+ MEM_LEVEL_MAX,
+};
+
+struct psi_level_desc {
+ char *type;
+ int stall;
+ int window;
+ u_int32_t level;
+};
+
+static struct thread *psi_timer;
+static int listener_handles[MEM_LEVEL_MAX];
+static int psi_fds[MEM_LEVEL_MAX];
+static const struct psi_level_desc psi_levels[MEM_LEVEL_MAX] = {
+ [MEM_LEVEL_MEDIUM] = {
+ .type = PSI_TYPE_WARN,
+ .stall = 70000,
+ .window = 1000000,
+ .level = MEM_LEVEL_MEDIUM,
+ },
+ [MEM_LEVEL_LOW] = {
+ .type = PSI_TYPE_WARN,
+ .stall = 150000,
+ .window = 1000000,
+ .level = MEM_LEVEL_LOW,
+ },
+ [MEM_LEVEL_CRITICAL] = {
+ .type = PSI_TYPE_CRITICAL,
+ .stall = 70000,
+ .window = 1000000,
+ .level = MEM_LEVEL_CRITICAL,
+ },
+ [MEM_LEVEL_OOM] = {
+ .type = PSI_TYPE_CRITICAL,
+ .stall = 150000,
+ .window = 1000000,
+ .level = MEM_LEVEL_OOM,
+ }
+};
+
+static int system_get_memory_pressure_level(int resource_id,
+ const struct syscommon_resman_resource_attribute *attr,
+ void *data)
+{
+ struct system_resource_data *sysdata;
+ int *pressure_level = (int *)data;
+
+ if (resource_id < 0 || !attr || !data)
+ return -EINVAL;
+
+ sysdata = syscommon_resman_get_resource_privdata(resource_id);
+ if (!sysdata)
+ return -EINVAL;
+
+ *pressure_level = sysdata->memory_pressure_level;
+
+ return 0;
+}
+
+static void system_handle_psi_listener(int resource_id,
+ const struct syscommon_resman_resource_attribute *attr,
+ void *data, int listener_type)
+{
+ struct system_resource_data *sysdata;
+ struct timeval current;
+ u_int64_t current_msec;
+ int memory_pressure_level;
+
+ if (resource_id < 0 || !attr || !data)
+ return;
+
+ sysdata = syscommon_resman_get_resource_privdata(resource_id);
+ if (!sysdata)
+ return;
+
+ memory_pressure_level = *(int *)data;
+
+ /* If event occurs in debounce time, lower level event is ignored. */
+ gettimeofday(&current, NULL);
+ current_msec = current.tv_sec * 1000 + current.tv_usec / 1000;
+ if (current_msec - sysdata->memory_pressure_last_update < PSI_EVENT_DEBOUNCE_TIME
+ && memory_pressure_level <= sysdata->memory_pressure_level)
+ return;
+
+ sysdata->memory_pressure_level = memory_pressure_level;
+ sysdata->memory_pressure_last_update = current_msec;
+}
+
+static int
+register_memory_pressure_listener(const struct psi_level_desc *desc, int resource_id,
+ const struct syscommon_resman_resource_attribute *attr)
+{
+ char desc_str[BUFF_MAX];
+ int ret, fd;
+
+ fd = open(PSI_MEMORY_GLOBAL, O_RDWR | O_NONBLOCK);
+ if (fd < 0) {
+ _E("failed to open psi node: %s %d", PSI_MEMORY_GLOBAL, errno);
+ return -errno;
+ }
+
+ ret = snprintf(desc_str, BUFF_MAX, "%s %d %d", desc->type, desc->stall, desc->window);
+ if (ret >= BUFF_MAX) {
+ _E("psi event description overflows");
+ ret = -EINVAL;
+ goto err_close_fd;
+ }
+
+ ret = write(fd, desc_str, strlen(desc_str) + 1);
+ if (ret < 0) {
+ _E("failed to write psi description: %s", desc_str);
+ ret = -errno;
+ goto err_close_fd;
+ }
+
+ ret = syscommon_resman_register_epoll_listener(resource_id, attr, fd, (void *)&desc->level);
+ if (ret < 0) {
+ _E("failed to register epoll event");
+ goto err_close_fd;
+ }
+
+ listener_handles[desc->level] = ret;
+ psi_fds[desc->level] = fd;
+
+ return 0;
+
+err_close_fd:
+ close(fd);
+
+ return ret;
+}
+
+static int system_check_memory_pressure_resolved(void *data, void **result)
+{
+ struct syscommon_resman_resource_attribute dummy_attr;
+ int mem_level_high = MEM_LEVEL_HIGH;
+ int resource_id = (int)data;
+
+ system_handle_psi_listener(resource_id, &dummy_attr,
+ &mem_level_high, SYSCOMMON_RESMAN_LISTENER_TYPE_EPOLL);
+
+ return THREAD_RETURN_CONTINUE;
+}
+
+static int system_init_psi_listener(int resource_id,
+ const struct syscommon_resman_resource_attribute *attr)
+{
+ int i, ret;
+
+ ret = create_timer_thread(&psi_timer, PSI_EVENT_RESOLVE_CHECK_RATE,
+ system_check_memory_pressure_resolved, (void *)resource_id);
+ if (ret < 0)
+ return ret;
+
+ for (i = MEM_LEVEL_MEDIUM; i < MEM_LEVEL_MAX; i++) {
+ ret = register_memory_pressure_listener(&psi_levels[i], resource_id, attr);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void system_exit_psi_listener(int resource_id,
+ const struct syscommon_resman_resource_attribute *attr)
+{
+ int i;
+
+ for (i = MEM_LEVEL_MEDIUM; i < MEM_LEVEL_MAX; i++) {
+ if (listener_handles[i]) {
+ syscommon_resman_unregister_epoll_listener(listener_handles[i]);
+ listener_handles[i] = 0;
+ }
+
+ if (psi_fds[i]) {
+ close(psi_fds[i]);
+ psi_fds[i] = 0;
+ }
+ }
+
+ destroy_thread(psi_timer);
+}
+
static const struct syscommon_resman_resource_attribute system_attrs[] = {
{
.name = "SYSTEM_ATTR_CPU_UTIL",
@@ -248,6 +449,19 @@ static const struct syscommon_resman_resource_attribute system_attrs[] = {
.ops = {
.get = system_get_cpu_num,
}
+ }, {
+ .name = "SYSTEM_ATTR_MEMORY_PRESSURE_LEVEL",
+ .id = SYSTEM_ATTR_MEMORY_PRESSURE_LEVEL,
+ .type = SYSCOMMON_RESMAN_DATA_TYPE_INT,
+ .flag = SYSCOMMON_RESMAN_RESOURCE_ATTR_FLAG_PUBLIC,
+ .ops = {
+ .get = system_get_memory_pressure_level,
+ },
+ .listener_ops = {
+ .init = system_init_psi_listener,
+ .exit = system_exit_psi_listener,
+ .action = system_handle_psi_listener,
+ }
},
};
diff --git a/tools/resource-monitor/resource-monitor.c b/tools/resource-monitor/resource-monitor.c
index 815fd4d..3b0d6c8 100644
--- a/tools/resource-monitor/resource-monitor.c
+++ b/tools/resource-monitor/resource-monitor.c
@@ -118,6 +118,8 @@ static struct syscommon_resman_resource_attr_data system_attrs[] = {
{ .id = SYSTEM_ATTR_PER_CPU_SYS_UTIL, .type = SYSCOMMON_RESMAN_DATA_TYPE_ARRAY, .name = "SYSTEM_ATTR_PER_CPU_SYS_UTIL", .unit = "%", .desc = "Per-CPU utilization on system", .array_type = SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE, },
{ .id = SYSTEM_ATTR_POSSIBLE_CPU, .type = SYSCOMMON_RESMAN_DATA_TYPE_INT, .name = "SYSTEM_ATTR_POSSIBLE_CPU", .unit = "ea", .desc = "Number of possible CPU", },
{ .id = SYSTEM_ATTR_ONLINE_CPU, .type = SYSCOMMON_RESMAN_DATA_TYPE_INT, .name = "SYSTEM_ATTR_ONLINE_CPU", .unit = "ea", .desc = "Number of online CPU", },
+ { .id = SYSTEM_ATTR_MEMORY_PRESSURE_LEVEL, .type = SYSCOMMON_RESMAN_DATA_TYPE_INT, .name = "MEMORY_ATTR_PRESSURE_LEVEL", .unit = "lv", .desc = "Level of memory pressure", },
+
};
struct syscommon_resman_resource_attr_data process_attrs[] = {