summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2018-04-15 17:34:59 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-04-15 17:34:59 +0000
commit22dc27b9fa46b20aca4f5982979681a858a97284 (patch)
treefc3d531d198811720362c6bad631e9f9c4576366
parent5176b4b37ab17d23ab1069d3394acb28f0a946a3 (diff)
parentc09b53db7bdc312ed81d7d82cb634b59a0e825bf (diff)
downloadcore-o-mr1-iot-preview-8.tar.gz
Merge "lmkd: Introduce support for legacy kill algorithm that uses minfree levels"android-o-mr1-iot-preview-8o-mr1-iot-preview-8
-rw-r--r--lmkd/README.md5
-rw-r--r--lmkd/lmkd.c105
2 files changed, 85 insertions, 25 deletions
diff --git a/lmkd/README.md b/lmkd/README.md
index ba2e83d06..656a6ea0a 100644
--- a/lmkd/README.md
+++ b/lmkd/README.md
@@ -29,6 +29,11 @@ properties:
ro.config.low_ram: choose between low-memory vs high-performance
device. Default = false.
+ ro.lmk.use_minfree_levels: use free memory and file cache thresholds for
+ making decisions when to kill. This mode works
+ the same way kernel lowmemorykiller driver used
+ to work. Default = false
+
ro.lmk.low: min oom_adj score for processes eligible to be
killed at low vmpressure level. Default = 1001
(disabled)
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 5eb3fbe15..151e1dc7b 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -109,6 +109,7 @@ static int64_t downgrade_pressure;
static bool low_ram_device;
static bool kill_heaviest_task;
static unsigned long kill_timeout_ms;
+static bool use_minfree_levels;
/* data required to handle events */
struct event_handler_info {
@@ -972,11 +973,10 @@ static int kill_one_process(struct proc* procp, int min_score_adj,
* Returns the size of the killed processes.
*/
static int find_and_kill_processes(enum vmpressure_level level,
- int pages_to_free) {
+ int min_score_adj, int pages_to_free) {
int i;
int killed_size;
int pages_freed = 0;
- int min_score_adj = level_oomadj[level];
for (i = OOM_SCORE_ADJ_MAX; i >= min_score_adj; i--) {
struct proc *procp;
@@ -1071,9 +1071,14 @@ static void mp_event_common(int data, uint32_t events __unused) {
int64_t mem_pressure;
enum vmpressure_level lvl;
union meminfo mi;
+ union zoneinfo zi;
static struct timeval last_report_tm;
static unsigned long skip_count = 0;
enum vmpressure_level level = (enum vmpressure_level)data;
+ long other_free = 0, other_file = 0;
+ int min_score_adj;
+ int pages_to_free = 0;
+ int minfree = 0;
static struct reread_data mem_usage_file_data = {
.filename = MEMCG_MEMORY_USAGE,
.fd = -1,
@@ -1114,11 +1119,40 @@ static void mp_event_common(int data, uint32_t events __unused) {
skip_count = 0;
}
- if (meminfo_parse(&mi) < 0) {
+ if (meminfo_parse(&mi) < 0 || zoneinfo_parse(&zi) < 0) {
ALOGE("Failed to get free memory!");
return;
}
+ if (use_minfree_levels) {
+ int i;
+
+ other_free = mi.field.nr_free_pages - zi.field.totalreserve_pages;
+ if (mi.field.nr_file_pages > (mi.field.shmem + mi.field.unevictable + mi.field.swap_cached)) {
+ other_file = (mi.field.nr_file_pages - mi.field.shmem -
+ mi.field.unevictable - mi.field.swap_cached);
+ } else {
+ other_file = 0;
+ }
+
+ min_score_adj = OOM_SCORE_ADJ_MAX + 1;
+ for (i = 0; i < lowmem_targets_size; i++) {
+ minfree = lowmem_minfree[i];
+ if (other_free < minfree && other_file < minfree) {
+ min_score_adj = lowmem_adj[i];
+ break;
+ }
+ }
+
+ if (min_score_adj == OOM_SCORE_ADJ_MAX + 1)
+ return;
+
+ /* Free up enough pages to push over the highest minfree level */
+ pages_to_free = lowmem_minfree[lowmem_targets_size - 1] -
+ ((other_free < other_file) ? other_free : other_file);
+ goto do_kill;
+ }
+
if (level == VMPRESS_LEVEL_LOW) {
record_low_pressure_levels(&mi);
}
@@ -1167,39 +1201,58 @@ static void mp_event_common(int data, uint32_t events __unused) {
do_kill:
if (low_ram_device) {
/* For Go devices kill only one task */
- if (find_and_kill_processes(level, 0) == 0) {
+ if (find_and_kill_processes(level, level_oomadj[level], 0) == 0) {
if (debug_process_killing) {
ALOGI("Nothing to kill");
}
}
} else {
- /* If pressure level is less than critical and enough free swap then ignore */
- if (level < VMPRESS_LEVEL_CRITICAL &&
- mi.field.free_swap > low_pressure_mem.max_nr_free_pages) {
+ int pages_freed;
+
+ if (!use_minfree_levels) {
+ /* If pressure level is less than critical and enough free swap then ignore */
+ if (level < VMPRESS_LEVEL_CRITICAL &&
+ mi.field.free_swap > low_pressure_mem.max_nr_free_pages) {
+ if (debug_process_killing) {
+ ALOGI("Ignoring pressure since %" PRId64
+ " swap pages are available ",
+ mi.field.free_swap);
+ }
+ return;
+ }
+ /* Free up enough memory to downgrate the memory pressure to low level */
+ if (mi.field.nr_free_pages < low_pressure_mem.max_nr_free_pages) {
+ pages_to_free = low_pressure_mem.max_nr_free_pages -
+ mi.field.nr_free_pages;
+ } else {
+ if (debug_process_killing) {
+ ALOGI("Ignoring pressure since more memory is "
+ "available (%" PRId64 ") than watermark (%" PRId64 ")",
+ mi.field.nr_free_pages, low_pressure_mem.max_nr_free_pages);
+ }
+ return;
+ }
+ min_score_adj = level_oomadj[level];
+ } else {
if (debug_process_killing) {
- ALOGI("Ignoring pressure since %" PRId64
- " swap pages are available ",
- mi.field.free_swap);
+ ALOGI("Killing because cache %ldkB is below "
+ "limit %ldkB for oom_adj %d\n"
+ " Free memory is %ldkB %s reserved",
+ other_file * page_k, minfree * page_k, min_score_adj,
+ other_free * page_k, other_free >= 0 ? "above" : "below");
}
- return;
}
- /* Free up enough memory to downgrate the memory pressure to low level */
- if (mi.field.nr_free_pages < low_pressure_mem.max_nr_free_pages) {
- int pages_to_free = low_pressure_mem.max_nr_free_pages -
- mi.field.nr_free_pages;
+ if (debug_process_killing) {
+ ALOGI("Trying to free %d pages", pages_to_free);
+ }
+ pages_freed = find_and_kill_processes(level, min_score_adj, pages_to_free);
+ if (pages_freed < pages_to_free) {
if (debug_process_killing) {
- ALOGI("Trying to free %d pages", pages_to_free);
- }
- int pages_freed = find_and_kill_processes(level, pages_to_free);
- if (pages_freed < pages_to_free) {
- if (debug_process_killing) {
- ALOGI("Unable to free enough memory (pages freed=%d)",
- pages_freed);
- }
- } else {
- gettimeofday(&last_report_tm, NULL);
+ ALOGI("Unable to free enough memory (pages freed=%d)", pages_freed);
}
+ } else {
+ gettimeofday(&last_report_tm, NULL);
}
}
}
@@ -1409,6 +1462,8 @@ int main(int argc __unused, char **argv __unused) {
low_ram_device = property_get_bool("ro.config.low_ram", false);
kill_timeout_ms =
(unsigned long)property_get_int32("ro.lmk.kill_timeout_ms", 0);
+ use_minfree_levels =
+ property_get_bool("ro.lmk.use_minfree_levels", false);
if (!init()) {
if (!use_inkernel_interface) {