--- /dev/null
+/**
+ * resourced
+ *
+ * Copyright (c) 2023 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 lowmem-monitor.c
+ * @desc Provides monitor functionalities to detect lowmem state
+ */
+
+#include <unistd.h>
+
+#include "memory-cgroup.h"
+#include "lowmem.h"
+#include "lowmem-monitor.h"
+#include "procfs.h"
+#include "trace.h"
+
+#define LOWMEM_THRES_INIT 0
+
+static char *event_level = MEMCG_DEFAULT_EVENT_LEVEL;
+
+static int lowmem_monitor_pressure_eventfd_read(int fd)
+{
+ unsigned long long dummy_state;
+
+ return read(fd, &dummy_state, sizeof(dummy_state));
+}
+
+static bool lowmem_monitor_pressure_eventfd_handler(int fd, void *data)
+{
+ struct memcg_info *mi;
+ enum cgroup_type type = MEMCG_ROOT;
+ void(*pressure_low_handler)(void) = (void(*)(void))data;
+
+ /* FIXME: probably shouldn't get ignored */
+ if (lowmem_monitor_pressure_eventfd_read(fd) < 0)
+ _E("Failed to read lowmem press event, %m\n");
+
+ for (type = MEMCG_ROOT; type < MEMCG_END; type++) {
+ if (!get_cgroup_tree(type) || !get_memcg_info(type))
+ continue;
+ mi = get_memcg_info(type);
+ if (fd == mi->evfd) {
+ /* call low memory handler for this memcg */
+ if (type == MEMCG_ROOT) {
+ pressure_low_handler();
+ return true;
+ }
+ else {
+ _E("Wrong event fd for cgroup %s",
+ lowmem_convert_cgroup_type_to_str(type));
+ return false;
+ }
+ }
+ }
+
+ return false;
+}
+
+static int lowmem_monitor_pressure_register_eventfd(struct memcg_info *mi,
+ void(*pressure_low_handler)(void))
+{
+ int evfd;
+ const char *name = mi->name;
+ static fd_handler_h handler;
+
+ if (mi->threshold_mb[MEM_LEVEL_OOM] == LOWMEM_THRES_INIT)
+ return 0;
+
+ evfd = memcg_set_eventfd(name, MEMCG_EVENTFD_MEMORY_PRESSURE,
+ event_level);
+
+ if (evfd < 0) {
+ int saved_errno = errno;
+ _E("Failed to register event press fd %s cgroup", name);
+ return -saved_errno;
+ }
+
+ mi->evfd = evfd;
+
+ add_fd_read_handler(NULL, evfd, lowmem_monitor_pressure_eventfd_handler,
+ pressure_low_handler, NULL, &handler);
+ return 0;
+}
+
+int lowmem_monitor_pressure_initialize(void(*pressure_low_handler)(void))
+{
+ unsigned int i;
+
+ for (i = MEMCG_ROOT; i < MEMCG_END; i++) {
+ if (!get_use_hierarchy(i))
+ continue;
+
+ lowmem_monitor_pressure_register_eventfd(get_memcg_info(i),
+ pressure_low_handler);
+ }
+ return RESOURCED_ERROR_NONE;
+}
+
--- /dev/null
+/**
+ * resourced
+ *
+ * Copyright (c) 2023 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 exmonitor or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @file lowmem-monitor.h
+ * @desc Functions for monitor features.
+ */
+
+#ifndef __LOWMEM_MONITOR_H__
+#define __LOWMEM_MONITOR_H__
+
+int lowmem_monitor_pressure_initialize(void(*pressure_low_handler)(void));
+
+#endif /* __LOWMEM_MONITOR_H__ */
#include "cgroup.h"
#include "lowmem.h"
#include "lowmem-dbus.h"
+#include "lowmem-monitor.h"
#include "lowmem-system.h"
#include "lowmem-limit.h"
#include "lowmem-governor.h"
#include "safe-kill.h"
#include "dedup-common.h"
-#define LOWMEM_THRES_INIT 0
-
#define MAX_VICTIMS_BETWEEN_CHECK 3
#define MAX_PROACTIVE_HIGH_VICTIMS 4
#define FOREGROUND_VICTIMS 1
static unsigned proactive_leave_mb;
static unsigned lmk_start_threshold_mb;
-static char *event_level = MEMCG_DEFAULT_EVENT_LEVEL;
-
/**
* Resourced Low Memory Killer
* NOTE: planned to be moved to a separate file.
static bool memcg_swap_status;
static int fragmentation_size;
-static const char *convert_cgroup_type_to_str(int type)
+const char *lowmem_convert_cgroup_type_to_str(int type)
{
static const char *type_table[] =
{"/", "Throttling"};
return;
}
-static void lowmem_trigger_memory_state_action(int mem_state)
+void lowmem_trigger_memory_state_action(int mem_state)
{
/*
* Check if the state we want to set is different from current
if(cur_memcg_idx == next_memcg_idx)
return;
- _I("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));
+ _I("app (%s) memory cgroup move from %s to %s", pai->appid, lowmem_convert_cgroup_type_to_str(cur_memcg_idx), lowmem_convert_cgroup_type_to_str(next_memcg_idx));
cgroup_write_pid_fullpath(mi->name, pid);
if (next_memcg_idx == MEMCG_THROTTLING)
lowmem_swap_memory(get_memcg_info(MEMCG_THROTTLING)->name);
g_async_queue_unref(lmw.queue);
}
-static int lowmem_press_eventfd_read(int fd)
-{
- unsigned long long dummy_state;
-
- return read(fd, &dummy_state, sizeof(dummy_state));
-}
-
static void lowmem_press_root_cgroup_handler(void)
{
static unsigned int prev_available_mb;
prev_available_mb = available_mb;
}
-static bool lowmem_press_eventfd_handler(int fd, void *data)
-{
- struct memcg_info *mi;
- enum cgroup_type type = MEMCG_ROOT;
-
- // FIXME: probably shouldn't get ignored
- if (lowmem_press_eventfd_read(fd) < 0)
- _E("Failed to read lowmem press event, %m\n");
-
- for (type = MEMCG_ROOT; type < MEMCG_END; type++) {
- if (!get_cgroup_tree(type) || !get_memcg_info(type))
- continue;
- mi = get_memcg_info(type);
- if (fd == mi->evfd) {
- /* call low memory handler for this memcg */
- if (type == MEMCG_ROOT) {
- lowmem_press_root_cgroup_handler();
- return true;
- }
- else {
- _E("Wrong event fd for cgroup %s", convert_cgroup_type_to_str(type));
- return false;
- }
- }
- }
-
- return false;
-}
-
-static int lowmem_press_register_eventfd(struct memcg_info *mi)
-{
- int evfd;
- const char *name = mi->name;
- static fd_handler_h handler;
-
- if (mi->threshold_mb[MEM_LEVEL_OOM] == LOWMEM_THRES_INIT)
- return 0;
-
- evfd = memcg_set_eventfd(name, MEMCG_EVENTFD_MEMORY_PRESSURE,
- event_level);
-
- if (evfd < 0) {
- int saved_errno = errno;
- _E("Failed to register event press fd %s cgroup", name);
- return -saved_errno;
- }
-
- mi->evfd = evfd;
-
- add_fd_read_handler(NULL, evfd, lowmem_press_eventfd_handler, NULL, NULL, &handler);
- return 0;
-}
-
-static int lowmem_press_setup_eventfd(void)
-{
- unsigned int i;
-
- for (i = MEMCG_ROOT; i < MEMCG_END; i++) {
- if (!get_use_hierarchy(i))
- continue;
-
- lowmem_press_register_eventfd(get_memcg_info(i));
- }
- return RESOURCED_ERROR_NONE;
-}
-
static void lowmem_force_reclaim_cb(struct lowmem_control *ctl)
{
lowmem_change_memory_state(MEM_LEVEL_HIGH, 0);
/* print info of Memory section */
for (int cgroup = MEMCG_THROTTLING; cgroup < MEMCG_END; cgroup++) {
_I("[MEMORY-CGROUP] set memory for cgroup '%s' to %llu bytes",
- convert_cgroup_type_to_str(cgroup), get_memcg_info(cgroup)->limit_bytes);
+ lowmem_convert_cgroup_type_to_str(cgroup), get_memcg_info(cgroup)->limit_bytes);
}
for (int cgroup = MEMCG_ROOT; cgroup < MEMCG_END; cgroup++) {
for (int mem_lvl = 0; mem_lvl < MEM_LEVEL_MAX; mem_lvl++) {
- _I("[MEMORY-LEVEL] set threshold of %s for memory level '%s' to %u MB", convert_cgroup_type_to_str(cgroup),
+ _I("[MEMORY-LEVEL] set threshold of %s for memory level '%s' to %u MB", lowmem_convert_cgroup_type_to_str(cgroup),
convert_memstate_to_str(mem_lvl), get_memcg_info(cgroup)->threshold_mb[mem_lvl]);
}
}
}
/* register threshold and event fd */
- ret = lowmem_press_setup_eventfd();
+ ret = lowmem_monitor_pressure_initialize(
+ lowmem_press_root_cgroup_handler);
if (ret) {
_E("[MEMORY-LIMIT] eventfd setup failed");
return ret;