#include <string.h>
#include <limits.h>
+#include <vconf.h>
+#include <bundle.h>
+#include <eventsystem.h>
#include "lowmem.h"
#include "proc-common.h"
#include "util.h"
#include "safe-kill.h"
#include "module.h"
+#include "notifier.h"
+#include "freezer.h"
+#include "swap-common.h"
#define MAX_VICTIMS_BETWEEN_CHECK 3
return victim_cnt;
}
+/* lowmem actions */
+
+static int high_mem_act(void *data)
+{
+ int ret, status;
+
+ ret = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status);
+ if (ret)
+ _D("vconf_get_int fail %s", VCONFKEY_SYSMAN_LOW_MEMORY);
+ if (status != VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL) {
+ vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
+ VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL);
+ lowmem_memory_level_send_system_event(MEM_LEVEL_HIGH);
+ }
+
+ lowmem_change_lowmem_state(MEM_LEVEL_HIGH);
+
+ if (swap_get_state() == SWAP_ON && lowmem_get_memcg_swap_status()) {
+ resourced_notify(RESOURCED_NOTIFIER_SWAP_UNSET_LIMIT, get_memcg_info(MEMCG_THROTTLING));
+ lowmem_set_memcg_swap_status(false);
+ }
+ if (proc_get_freezer_status() == CGROUP_FREEZER_PAUSED)
+ resourced_notify(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE,
+ (void *)CGROUP_FREEZER_ENABLED);
+
+ return RESOURCED_ERROR_NONE;
+}
+
static int lowmem_controller_initialize(void *data)
{
+ /**
+ * FIXME: Consider to use one function to initialize the actions
+ * (killer for the lowmem killer and actions for the memory levels)
+ */
+
+ /* Initialize the action(killer) for the lowmem_worker(lowmem killer) */
lowmem_initialize_kill_candidates(lowmem_controller_kill_candidates);
+
+ /* Initialize actions for the memory levels */
+ lowmem_initialize_controller_ops_action(MEM_LEVEL_HIGH, high_mem_act);
+
return RESOURCED_ERROR_NONE;
}
/* low memory action function for cgroup */
/* low memory action function */
-static void high_mem_act(void);
static void swap_activate_act(void);
static void swap_compact_act(void);
static void lmk_act(void);
+struct lowmem_controller_ops {
+ int (*governor)(void *data);
+ int (*action)(void *data);
+};
+static struct lowmem_controller_ops lowmem_actions[MEM_LEVEL_MAX] = { NULL };
+void lowmem_initialize_controller_ops_governor(int mem_state, int (*governor)(void *data))
+{
+ switch (mem_state) {
+ case MEM_LEVEL_HIGH:
+ lowmem_actions[mem_state].governor = governor;
+ return;
+ default:
+ assert(0);
+ }
+}
+void lowmem_initialize_controller_ops_action(int mem_state, int (*action)(void *data))
+{
+ switch (mem_state) {
+ case MEM_LEVEL_HIGH:
+ lowmem_actions[mem_state].action = action;
+ return;
+ default:
+ assert(0);
+ }
+}
static size_t cur_mem_state = MEM_LEVEL_HIGH;
static int num_max_victims = MAX_MEMORY_CGROUP_VICTIMS;
static bool oom_popup_enable;
static bool oom_popup;
static bool memcg_swap_status;
+bool lowmem_get_memcg_swap_status()
+{
+ return memcg_swap_status;
+}
+void lowmem_set_memcg_swap_status(bool status)
+{
+ memcg_swap_status = status;
+}
static int fragmentation_size;
const char *lowmem_convert_cgroup_type_to_str(int type)
pthread_exit(NULL);
}
-static void change_lowmem_state(unsigned int mem_state)
+void lowmem_change_lowmem_state(unsigned int mem_state)
{
cur_mem_state = mem_state;
lmk_start_threshold_mb = get_root_memcg_info()->threshold_mb[MEM_LEVEL_OOM];
resourced_notify(RESOURCED_NOTIFIER_SWAP_START, path);
}
-static void memory_level_send_system_event(int lv)
+void lowmem_memory_level_send_system_event(int lv)
{
bundle *b;
const char *str;
bundle_free(b);
}
-static void high_mem_act(void)
-{
- int ret, status;
-
- ret = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status);
- if (ret)
- _D("vconf_get_int fail %s", VCONFKEY_SYSMAN_LOW_MEMORY);
- if (status != VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL) {
- vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
- VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL);
- memory_level_send_system_event(MEM_LEVEL_HIGH);
- }
-
- change_lowmem_state(MEM_LEVEL_HIGH);
-
- if (swap_get_state() == SWAP_ON && memcg_swap_status) {
- resourced_notify(RESOURCED_NOTIFIER_SWAP_UNSET_LIMIT, get_memcg_info(MEMCG_THROTTLING));
- memcg_swap_status = false;
- }
- if (proc_get_freezer_status() == CGROUP_FREEZER_PAUSED)
- resourced_notify(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE,
- (void *)CGROUP_FREEZER_ENABLED);
-}
-
static void swap_activate_act(void)
{
int ret, status;
if (status != VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL) {
vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL);
- memory_level_send_system_event(MEM_LEVEL_LOW);
+ lowmem_memory_level_send_system_event(MEM_LEVEL_LOW);
}
- change_lowmem_state(MEM_LEVEL_LOW);
+ lowmem_change_lowmem_state(MEM_LEVEL_LOW);
if (proc_get_freezer_status() == CGROUP_FREEZER_PAUSED)
resourced_notify(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE,
(void *)CGROUP_FREEZER_ENABLED);
if (status != VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL) {
vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL);
- memory_level_send_system_event(MEM_LEVEL_MEDIUM);
+ lowmem_memory_level_send_system_event(MEM_LEVEL_MEDIUM);
}
- change_lowmem_state(MEM_LEVEL_MEDIUM);
+ lowmem_change_lowmem_state(MEM_LEVEL_MEDIUM);
data = KSM_SCAN_PARTIAL;
resourced_notify(RESOURCED_NOTIFIER_DEDUP_SCAN, &data);
static void swap_compact_act(void)
{
- change_lowmem_state(MEM_LEVEL_CRITICAL);
+ lowmem_change_lowmem_state(MEM_LEVEL_CRITICAL);
resourced_notify(RESOURCED_NOTIFIER_SWAP_COMPACT, (void *)SWAP_COMPACT_MEM_LEVEL_CRITICAL);
- memory_level_send_system_event(MEM_LEVEL_CRITICAL);
+ lowmem_memory_level_send_system_event(MEM_LEVEL_CRITICAL);
}
static void medium_cb(struct lowmem_control *ctl)
if (ret)
_D("vconf_get_int fail %s", VCONFKEY_SYSMAN_LOW_MEMORY);
- memory_level_send_system_event(MEM_LEVEL_OOM);
+ lowmem_memory_level_send_system_event(MEM_LEVEL_OOM);
if (status != VCONFKEY_SYSMAN_LOW_MEMORY_HARD_WARNING) {
if (proc_get_freezer_status() == CGROUP_FREEZER_ENABLED)
resourced_notify(RESOURCED_NOTIFIER_FREEZER_CGROUP_STATE,
}
available_mb = proc_get_mem_available();
- change_lowmem_state(MEM_LEVEL_OOM);
+ lowmem_change_lowmem_state(MEM_LEVEL_OOM);
if (available_mb < get_root_memcg_info()->threshold_leave_mb) {
struct lowmem_control *ctl;
switch (mem_state) {
case MEM_LEVEL_HIGH:
- high_mem_act();
+ assert(lowmem_actions[mem_state].governor != NULL);
+ assert(lowmem_actions[mem_state].action != NULL);
+ if (lowmem_actions[mem_state].governor(NULL) < 0)
+ break;
+ lowmem_actions[mem_state].action(NULL);
break;
case MEM_LEVEL_MEDIUM:
dedup_act(KSM_SCAN_PARTIAL);