#define MEM_POPUP_STRING "oom_popup"
#define MEM_BG_RECLAIM_SECTION "BackgroundReclaim"
#define MEM_BG_RECLAIM_STRING "AfterScreenDim"
+#define MEM_LOGGING_SECTION "Logging"
#define BUF_MAX 1024
#define MAX_VICTIMS_BETWEEN_CHECK 3
#define FOREGROUND_VICTIMS 1
#define OOM_TIMER_INTERVAL 2
#define OOM_KILLER_PRIORITY -20
-#define MAX_MEMPS_LOGS 50
-#define NUM_RM_LOGS 5
#define THRESHOLD_MARGIN 10 /* MB */
#define MEM_SIZE_64 64 /* MB */
static struct lowmem_worker lmw;
+static int memlog_enabled;
+static int memlog_nr_max = DEFAULT_MEMLOG_NR_MAX;
+/* remove logfiles to reduce to this threshold.
+ * it is about five-sixths of the memlog_nr_max. */
+static int memlog_remove_batch_thres = (DEFAULT_MEMLOG_NR_MAX * 5) / 6;
+static char *memlog_path = DEFAULT_MEMLOG_PATH;
+static char *memlog_prefix[MEMLOG_MAX];
+
#define LOWMEM_WORKER_IS_ACTIVE(_lmw) g_atomic_int_get(&(_lmw)->active)
#define LOWMEM_WORKER_ACTIVATE(_lmw) g_atomic_int_set(&(_lmw)->active, 1)
#define LOWMEM_WORKER_DEACTIVATE(_lmw) g_atomic_int_set(&(_lmw)->active, 0)
return (time1 - time2);
}
-int clear_logs(void *data)
+static int clear_logs(void *data)
{
struct dirent **namelist;
int n, i, ret;
char *dir = (char*)data;
int len;
- if (!dir) {
- _E("Invalid parameter - dir is NULL");
- return RESOURCED_ERROR_INVALID_PARAMETER;
- }
+ if (!memlog_enabled)
+ return RESOURCED_ERROR_NONE;
+
+ if (!dir)
+ return RESOURCED_ERROR_NONE;
len = strlen(dir);
if (len <= 0 || len >= sizeof fpath - 1) {
}
n = scandir(dir, &namelist, memps_file_select, timesort);
+
_D("num of log files %d", n);
- if (n < MAX_MEMPS_LOGS) {
+ if (n <= memlog_nr_max) {
while (n--)
free(namelist[n]);
free(namelist);
len = sizeof fpath - len - 1;
for (i = 0; i < n; i++) {
- if (i < NUM_RM_LOGS) {
+ if (i < n - memlog_remove_batch_thres) {
if (strlen(namelist[i]->d_name) > len - 1)
continue;
strncpy(fname, namelist[i]->d_name, len - 1);
return RESOURCED_ERROR_NONE;
}
-void make_memps_log(char *file, pid_t pid, char *victim_name)
+void make_memps_log(enum mem_log memlog, pid_t pid, char *victim_name)
{
time_t now;
struct tm cur_tm;
char new_log[BUF_MAX];
static pid_t old_pid;
int oom_score_adj = 0, ret;
+ char *prefix;
+
+ if (!memlog_enabled)
+ return;
+
+ if (memlog < MEMLOG_MEMPS || memlog >= MEMLOG_MAX)
+ return;
+
+ prefix = memlog_prefix[memlog];
if (old_pid == pid)
return;
+
old_pid = pid;
now = time(NULL);
}
snprintf(new_log, sizeof(new_log),
- "%s_%s_%d_%.4d%.2d%.2d%.2d%.2d%.2d", file, victim_name,
+ "%s/%s_%s_%d_%.4d%.2d%.2d%.2d%.2d%.2d", memlog_path, prefix, victim_name,
pid, (1900 + cur_tm.tm_year), 1 + cur_tm.tm_mon,
cur_tm.tm_mday, cur_tm.tm_hour, cur_tm.tm_min,
cur_tm.tm_sec);
argv[2] = new_log;
exec_cmd(ARRAY_SIZE(argv), argv);
}
+
+ /* best effort to limit the number of logfiles up to memlog_nr_max */
+ clear_logs(memlog_path);
}
static int lowmem_kill_victim(const struct task_info *tsk,
}
if (!memps_log)
- make_memps_log(MEMPS_LOG_FILE, pid, appname);
+ make_memps_log(MEMLOG_MEMPS, pid, appname);
pai = find_app_info(pid);
oom_popup = true;
}
if (memps_log)
- make_memps_log(MEMPS_LOG_FILE, pid, appname);
+ make_memps_log(MEMLOG_MEMPS, pid, appname);
return RESOURCED_ERROR_NONE;
}
_E("Done: killed %d processes reclaimed: %u remaining: %u shortfall: %u status: %d\n",
count, total_size, reclaim_size, shortfall, status);
/* After we finish reclaiming it's worth to remove oldest memps logs */
- if (count)
- request_helper_worker(CLEAR_LOGS, MEMPS_LOG_PATH, clear_logs, NULL);
+ if (count && memlog_enabled)
+ request_helper_worker(CLEAR_LOGS, memlog_path, clear_logs, NULL);
ctl->status = status;
}
return RESOURCED_ERROR_NONE;
}
+static int load_mem_logconfig(struct parse_result *result, void *user_data)
+{
+ if (!result)
+ return RESOURCED_ERROR_INVALID_PARAMETER;
+
+ if (strncmp(result->section, MEM_LOGGING_SECTION, strlen(MEM_LOGGING_SECTION)+1))
+ return RESOURCED_ERROR_NONE;
+
+ if (!strncmp(result->name, "Enable", strlen("Enable")+1)) {
+ memlog_enabled = atoi(result->value);
+ } else if (!strncmp(result->name, "LogPath", strlen("LogPath")+1)) {
+ memlog_path = strdup(result->value);
+ } else if (!strncmp(result->name, "MaxNumLogfile", strlen("MaxNumLogfile")+1)) {
+ memlog_nr_max = atoi(result->value);
+ memlog_remove_batch_thres = (memlog_nr_max * 5) / 6;
+ } else if (!strncmp(result->name, "PrefixMemps", strlen("PrefixMemps")+1)) {
+ memlog_prefix[MEMLOG_MEMPS] = strdup(result->value);
+ } else if (!strncmp(result->name, "PrefixMempsMemLimit", strlen("PrefixMempsMemLimit")+1)) {
+ memlog_prefix[MEMLOG_MEMPS_MEMLIMIT] = strdup(result->value);
+ }
+
+ return RESOURCED_ERROR_NONE;
+}
+
static int set_memory_config(const char *section_name, const struct parse_result *result)
{
if (!result || !section_name)
free_vip_app_list();
config_parse(MEM_CONF_FILE, load_mem_config, NULL);
config_parse(MEM_CONF_FILE, load_bg_reclaim_config, NULL);
+ config_parse(MEM_CONF_FILE, load_mem_logconfig, NULL);
create_memcgs();
write_memcg_params();