diff --git a/lmkd.cpp b/lmkd.cpp index 23bb5c3..701ada1 100644 --- a/lmkd.cpp +++ b/lmkd.cpp @@ -200,6 +200,7 @@ static int psi_partial_stall_ms; static int psi_complete_stall_ms; static int thrashing_limit_pct; static int thrashing_limit_decay_pct; +static int swap_util_max; static bool use_psi_monitors = false; static int kpoll_fd; static struct psi_threshold psi_thresholds[VMPRESS_LEVEL_COUNT] = { @@ -2202,6 +2203,13 @@ void calc_zone_watermarks(struct zoneinfo *zi, struct zone_watermarks *watermark } } +static int calc_swap_utilization(union meminfo *mi) { + int64_t swap_used = mi->field.total_swap - mi->field.free_swap; + int64_t total_swappable = mi->field.active_anon + mi->field.inactive_anon + + mi->field.shmem + swap_used; + return total_swappable > 0 ? (swap_used * 100) / total_swappable : 0; +} + static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_params) { enum kill_reasons { NONE = -1, /* To denote no kill condition */ @@ -2211,6 +2219,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ LOW_MEM_AND_SWAP, LOW_MEM_AND_THRASHING, DIRECT_RECL_AND_THRASHING, + LOW_MEM_AND_SWAP_UTIL, KILL_REASON_COUNT }; enum reclaim_state { @@ -2242,6 +2251,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ char kill_desc[LINE_MAX]; bool cut_thrashing_limit = false; int min_score_adj = 0; + int swap_util = 0; /* Skip while still killing a process */ if (is_kill_pending()) { @@ -2362,6 +2372,16 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_ snprintf(kill_desc, sizeof(kill_desc), "%s watermark is breached and swap is low (%" PRId64 "kB < %" PRId64 "kB)", wmark > WMARK_LOW ? "min" : "low", mi.field.free_swap * page_k, swap_low_threshold * page_k); + } else if (wmark < WMARK_HIGH && swap_util_max < 100 && + (swap_util = calc_swap_utilization(&mi)) > swap_util_max) { + /* + * Too much anon memory is swapped out but swap is not low. + * Non-swappable allocations created memory pressure. + */ + kill_reason = LOW_MEM_AND_SWAP_UTIL; + snprintf(kill_desc, sizeof(kill_desc), "%s watermark is breached and swap utilization" + " is high (%d%% > %d%%)", wmark > WMARK_LOW ? "min" : "low", + swap_util, swap_util_max); } else if (wmark < WMARK_HIGH && thrashing > thrashing_limit) { /* Page cache is thrashing while memory is low */ kill_reason = LOW_MEM_AND_THRASHING; @@ -3082,6 +3102,7 @@ int main(int argc __unused, char **argv __unused) { low_ram_device ? DEF_THRASHING_LOWRAM : DEF_THRASHING)); thrashing_limit_decay_pct = clamp(0, 100, property_get_int32("ro.lmk.thrashing_limit_decay", low_ram_device ? DEF_THRASHING_DECAY_LOWRAM : DEF_THRASHING_DECAY)); + swap_util_max = clamp(0, 100, property_get_int32("ro.lmk.swap_util_max", 100)); ctx = create_android_logger(KILLINFO_LOG_TAG);