4 * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 * @file lowmem-monitor.c
21 * @desc Provides monitor functionalities to detect lowmem state
26 #include "memory-cgroup.h"
32 #define LOWMEM_THRES_INIT 0
34 static char *event_level = MEMCG_DEFAULT_EVENT_LEVEL;
36 static int lowmem_monitor_pressure_eventfd_read(int fd)
38 unsigned long long dummy_state;
40 return read(fd, &dummy_state, sizeof(dummy_state));
43 static void lowmem_monitor_raise_lowmem_event(void)
45 static unsigned int prev_available_mb;
46 unsigned int available_mb;
49 available_mb = proc_get_mem_available();
50 if (prev_available_mb == available_mb)
53 mem_state = lowmem_check_mem_state(available_mb);
54 lowmem_trigger_memory_state_action(mem_state);
55 prev_available_mb = available_mb;
58 static bool lowmem_monitor_pressure_eventfd_handler(int fd, void *data)
60 struct memcg_info *mi;
61 enum cgroup_type type = MEMCG_ROOT;
63 /* FIXME: probably shouldn't get ignored */
64 if (lowmem_monitor_pressure_eventfd_read(fd) < 0)
65 _E("Failed to read lowmem press event, %m\n");
67 for (type = MEMCG_ROOT; type < MEMCG_END; type++) {
68 if (!get_cgroup_tree(type) || !get_memcg_info(type))
70 mi = get_memcg_info(type);
72 /* call low memory handler for this memcg */
73 if (type == MEMCG_ROOT) {
74 lowmem_monitor_raise_lowmem_event();
78 _E("Wrong event fd for cgroup %s",
79 lowmem_convert_cgroup_type_to_str(type));
88 static int lowmem_monitor_pressure_register_eventfd(struct memcg_info *mi)
91 const char *name = mi->name;
92 static fd_handler_h handler;
94 if (mi->threshold_mb[MEM_LEVEL_OOM] == LOWMEM_THRES_INIT)
97 evfd = memcg_set_eventfd(name, MEMCG_EVENTFD_MEMORY_PRESSURE,
101 int saved_errno = errno;
102 _E("Failed to register event press fd %s cgroup", name);
108 add_fd_read_handler(NULL, evfd, lowmem_monitor_pressure_eventfd_handler,
109 NULL, NULL, &handler);
113 static int lowmem_monitor_initialize(void *data)
117 for (i = MEMCG_ROOT; i < MEMCG_END; i++) {
118 if (!get_use_hierarchy(i))
121 lowmem_monitor_pressure_register_eventfd(get_memcg_info(i));
123 return RESOURCED_ERROR_NONE;
126 static int lowmem_monitor_finalize(void *data)
128 return RESOURCED_ERROR_NONE;
131 static struct module_ops lowmem_monitor_modules_ops = {
132 .priority = MODULE_PRIORITY_INITIAL,
133 .name = "lowmem-monitor",
134 .init = lowmem_monitor_initialize,
135 .exit = lowmem_monitor_finalize,
138 MODULE_REGISTER(&lowmem_monitor_modules_ops)