static void lowmem_autodetect_oom_adj_values(void) { int i; short oom_adj; short oom_score_adj; int array_size = ARRAY_SIZE(lowmem_adj); if (lowmem_adj_size < array_size) array_size = lowmem_adj_size; if (array_size <= 0) return; oom_adj = lowmem_adj[array_size - 1]; if (oom_adj > OOM_ADJUST_MAX) return; oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj); if (oom_score_adj <= OOM_ADJUST_MAX) return; lowmem_print(1, "lowmem_shrink: convert oom_adj to oom_score_adj:\n"); for (i = 0; i < array_size; i++) { oom_adj = lowmem_adj[i]; oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj); lowmem_adj[i] = oom_score_adj; lowmem_print(1, "oom_adj %d => oom_score_adj %d\n", oom_adj, oom_score_adj); } }
/* For Internal ISP */ void prepare_for_cam_up(int mode) { struct task_struct *tsk; struct task_struct *selected[CAM_DEPTH_MAX] = {NULL,}; int tasksize; int i; int min_score_adj = OOM_SCORE_ADJ_MAX + 1; int selected_tasksize[CAM_DEPTH_MAX] = {0,}; int selected_oom_score_adj[CAM_DEPTH_MAX] = {OOM_ADJUST_MAX,}; int all_selected_oom = 0; int max_selected_oom_idx = 0; int kill_depth; kill_depth = calc_kill_number(mode); /* show status */ pr_info("%s FREE:%lu, FILE:%lu (depth %d)\n", __func__, global_page_state(NR_FREE_PAGES)*4, global_page_state(NR_FILE_PAGES)*4, kill_depth); if (kill_depth == 0) return; /* Though it's ugly to use hard coding, * there's no other way for this. * - up to SERVICE B */ #ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES min_score_adj = lowmem_oom_adj_to_oom_score_adj(CAM_MAX_ADJ); #else min_score_adj = CAM_MAX_ADJ; #endif for (i = 0; i < CAM_DEPTH_MAX; i++) selected_oom_score_adj[i] = min_score_adj; if (kill_depth > CAM_DEPTH_MAX) { pr_info("%s: try to kill more than max value!(%d/%d)\n", __func__, kill_depth, CAM_DEPTH_MAX); return; } #ifdef CONFIG_ZRAM_FOR_ANDROID atomic_set(&s_reclaim.lmk_running, 1); #endif read_lock(&tasklist_lock); for_each_process(tsk) { struct task_struct *p; int oom_score_adj; int is_exist_oom_task = 0; if (tsk->flags & PF_KTHREAD) continue; p = find_lock_task_mm(tsk); if (!p) continue; oom_score_adj = p->signal->oom_score_adj; if (oom_score_adj < min_score_adj) { task_unlock(p); continue; } tasksize = get_mm_rss(p->mm); task_unlock(p); if (tasksize <= 0) continue; lowmem_print(2, "cam: ------ %d (%s), adj %d, size %d\n", p->pid, p->comm, oom_score_adj, tasksize); if (all_selected_oom < kill_depth) { for (i = 0; i < kill_depth; i++) { if (!selected[i]) { is_exist_oom_task = 1; max_selected_oom_idx = i; break; } } } else if (selected_oom_score_adj[max_selected_oom_idx] < oom_score_adj || (selected_oom_score_adj[max_selected_oom_idx] == oom_score_adj && selected_tasksize[max_selected_oom_idx] < tasksize)) { is_exist_oom_task = 1; } if (is_exist_oom_task) { selected[max_selected_oom_idx] = p; selected_tasksize[max_selected_oom_idx] = tasksize; selected_oom_score_adj[max_selected_oom_idx] = oom_score_adj; if (all_selected_oom < kill_depth) all_selected_oom++; if (all_selected_oom == kill_depth) { for (i = 0; i < kill_depth; i++) { if (selected_oom_score_adj[i] < selected_oom_score_adj[max_selected_oom_idx]) max_selected_oom_idx = i; else if (selected_oom_score_adj[i] == selected_oom_score_adj[max_selected_oom_idx] && selected_tasksize[i] < selected_tasksize[max_selected_oom_idx]) max_selected_oom_idx = i; } } lowmem_print(2, "cam: max_selected_oom_idx(%d) select %d (%s), adj %d, \ size %d, to kill\n", max_selected_oom_idx, p->pid, p->comm, oom_score_adj, tasksize); } } for (i = 0; i < kill_depth; i++) { if (selected[i]) { lowmem_print(1, "cam: send sigkill to %d (%s), adj %d,\ size %d\n", selected[i]->pid, selected[i]->comm, selected_oom_score_adj[i], selected_tasksize[i]); send_sig(SIGKILL, selected[i], 0); } } read_unlock(&tasklist_lock); #ifdef CONFIG_ZRAM_FOR_ANDROID atomic_set(&s_reclaim.lmk_running, 0); #endif }
static int android_oom_handler(struct notifier_block *nb, unsigned long val, void *data) { struct task_struct *tsk; #ifdef MULTIPLE_OOM_KILLER struct task_struct *selected[OOM_DEPTH] = {NULL,}; #else struct task_struct *selected = NULL; #endif int rem = 0; int tasksize; int i; int min_score_adj = OOM_SCORE_ADJ_MAX + 1; #ifdef MULTIPLE_OOM_KILLER int selected_tasksize[OOM_DEPTH] = {0,}; int selected_oom_score_adj[OOM_DEPTH] = {OOM_ADJUST_MAX,}; int all_selected_oom = 0; int max_selected_oom_idx = 0; #else int selected_tasksize = 0; int selected_oom_score_adj; #endif unsigned long *freed = data; /* show status */ pr_warning("%s invoked Android-oom-killer: " "oom_adj=%d, oom_score_adj=%d\n", current->comm, current->signal->oom_adj, current->signal->oom_score_adj); dump_stack(); show_mem(SHOW_MEM_FILTER_NODES); dump_tasks_info(); min_score_adj = lowmem_oom_adj_to_oom_score_adj(0); #ifdef MULTIPLE_OOM_KILLER for (i = 0; i < OOM_DEPTH; i++) selected_oom_score_adj[i] = min_score_adj; #else selected_oom_score_adj = min_score_adj; #endif #ifdef CONFIG_ZRAM_FOR_ANDROID atomic_set(&s_reclaim.lmk_running, 1); #endif read_lock(&tasklist_lock); for_each_process(tsk) { struct task_struct *p; int oom_score_adj; #ifdef MULTIPLE_OOM_KILLER int is_exist_oom_task = 0; #endif if (tsk->flags & PF_KTHREAD) continue; p = find_lock_task_mm(tsk); if (!p) continue; oom_score_adj = p->signal->oom_score_adj; if (oom_score_adj < min_score_adj) { task_unlock(p); continue; } tasksize = get_mm_rss(p->mm); task_unlock(p); if (tasksize <= 0) continue; lowmem_print(2, "oom: ------ %d (%s), adj %d, size %d\n", p->pid, p->comm, oom_score_adj, tasksize); #ifdef MULTIPLE_OOM_KILLER if (all_selected_oom < OOM_DEPTH) { for (i = 0; i < OOM_DEPTH; i++) { if (!selected[i]) { is_exist_oom_task = 1; max_selected_oom_idx = i; break; } } } else if (selected_oom_score_adj[max_selected_oom_idx] < oom_score_adj || (selected_oom_score_adj[max_selected_oom_idx] == oom_score_adj && selected_tasksize[max_selected_oom_idx] < tasksize)) { is_exist_oom_task = 1; } if (is_exist_oom_task) { selected[max_selected_oom_idx] = p; selected_tasksize[max_selected_oom_idx] = tasksize; selected_oom_score_adj[max_selected_oom_idx] = oom_score_adj; if (all_selected_oom < OOM_DEPTH) all_selected_oom++; if (all_selected_oom == OOM_DEPTH) { for (i = 0; i < OOM_DEPTH; i++) { if (selected_oom_score_adj[i] < selected_oom_score_adj[max_selected_oom_idx]) max_selected_oom_idx = i; else if (selected_oom_score_adj[i] == selected_oom_score_adj[max_selected_oom_idx] && selected_tasksize[i] < selected_tasksize[max_selected_oom_idx]) max_selected_oom_idx = i; } } lowmem_print(2, "oom: max_selected_oom_idx(%d) select %d (%s), adj %d, \ size %d, to kill\n", max_selected_oom_idx, p->pid, p->comm, oom_score_adj, tasksize); } #else if (selected) { if (oom_score_adj < selected_oom_score_adj) continue; if (oom_score_adj == selected_oom_score_adj && tasksize <= selected_tasksize) continue; } selected = p; selected_tasksize = tasksize; selected_oom_score_adj = oom_score_adj; lowmem_print(2, "oom: select %d (%s), adj %d, size %d, to kill\n", p->pid, p->comm, oom_score_adj, tasksize); #endif } #ifdef MULTIPLE_OOM_KILLER for (i = 0; i < OOM_DEPTH; i++) { if (selected[i]) { lowmem_print(1, "oom: send sigkill to %d (%s), adj %d,\ size %d\n", selected[i]->pid, selected[i]->comm, selected_oom_score_adj[i], selected_tasksize[i]); send_sig(SIGKILL, selected[i], 0); rem -= selected_tasksize[i]; *freed += (unsigned long)selected_tasksize[i]; #ifdef OOM_COUNT_READ oom_count++; #endif } } #else if (selected) { lowmem_print(1, "oom: send sigkill to %d (%s), adj %d, size %d\n", selected->pid, selected->comm, selected_oom_score_adj, selected_tasksize); send_sig(SIGKILL, selected, 0); set_tsk_thread_flag(selected, TIF_MEMDIE); rem -= selected_tasksize; *freed += (unsigned long)selected_tasksize; #ifdef OOM_COUNT_READ oom_count++; #endif } #endif read_unlock(&tasklist_lock); #ifdef CONFIG_ZRAM_FOR_ANDROID atomic_set(&s_reclaim.lmk_running, 0); #endif lowmem_print(2, "oom: get memory %lu", *freed); return rem; }