Adding kswapd state monitoring with memevent_listener
Replacing mechanism of reading vmstats to detect kswapd with memevents instead. Maintain vmstats mechanism if bpf is not supported by current kernel. Test: Verified lmkd receives kswapd state changes Test: m Bug: 330606003 Change-Id: I9b980a8b94e015d1b8e0986fff9113890420d102 Signed-off-by: Carlos Galo <carlosgalo@google.com>
This commit is contained in:
parent
f9dfb20456
commit
6593e2cee6
61
lmkd.cpp
61
lmkd.cpp
|
|
@ -195,9 +195,10 @@ struct psi_threshold {
|
||||||
int threshold_ms;
|
int threshold_ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Listener for direct reclaim state changes */
|
/* Listener for direct reclaim and kswapd state changes */
|
||||||
static std::unique_ptr<android::bpf::memevents::MemEventListener> memevent_listener(nullptr);
|
static std::unique_ptr<android::bpf::memevents::MemEventListener> memevent_listener(nullptr);
|
||||||
static struct timespec direct_reclaim_start_tm;
|
static struct timespec direct_reclaim_start_tm;
|
||||||
|
static struct timespec kswapd_start_tm;
|
||||||
|
|
||||||
static int level_oomadj[VMPRESS_LEVEL_COUNT];
|
static int level_oomadj[VMPRESS_LEVEL_COUNT];
|
||||||
static int mpevfd[VMPRESS_LEVEL_COUNT] = { -1, -1, -1 };
|
static int mpevfd[VMPRESS_LEVEL_COUNT] = { -1, -1, -1 };
|
||||||
|
|
@ -1591,9 +1592,9 @@ static void ctrl_command_handler(int dsock_idx) {
|
||||||
* waiting, during boot-up, for BPF programs to be loaded.
|
* waiting, during boot-up, for BPF programs to be loaded.
|
||||||
*/
|
*/
|
||||||
if (init_memevent_listener_monitoring()) {
|
if (init_memevent_listener_monitoring()) {
|
||||||
ALOGI("Using memevents for direct reclaim detection");
|
ALOGI("Using memevents for direct reclaim and kswapd detection");
|
||||||
} else {
|
} else {
|
||||||
ALOGI("Using vmstats for direct reclaim detection");
|
ALOGI("Using vmstats for direct reclaim and kswapd detection");
|
||||||
if (direct_reclaim_threshold_ms > 0) {
|
if (direct_reclaim_threshold_ms > 0) {
|
||||||
ALOGW("Kernel support for direct_reclaim_threshold_ms is not found");
|
ALOGW("Kernel support for direct_reclaim_threshold_ms is not found");
|
||||||
direct_reclaim_threshold_ms = 0;
|
direct_reclaim_threshold_ms = 0;
|
||||||
|
|
@ -2673,6 +2674,7 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_
|
||||||
bool critical_stall = false;
|
bool critical_stall = false;
|
||||||
bool in_direct_reclaim;
|
bool in_direct_reclaim;
|
||||||
long direct_reclaim_duration_ms;
|
long direct_reclaim_duration_ms;
|
||||||
|
bool in_kswapd_reclaim;
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) {
|
if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) {
|
||||||
ALOGE("Failed to get current time");
|
ALOGE("Failed to get current time");
|
||||||
|
|
@ -2725,9 +2727,15 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_
|
||||||
swap_low_threshold = 0;
|
swap_low_threshold = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
in_direct_reclaim = memevent_listener ? (direct_reclaim_start_tm.tv_sec != 0 ||
|
if (memevent_listener) {
|
||||||
direct_reclaim_start_tm.tv_nsec != 0)
|
in_direct_reclaim =
|
||||||
: (vs.field.pgscan_direct != init_pgscan_direct);
|
direct_reclaim_start_tm.tv_sec != 0 || direct_reclaim_start_tm.tv_nsec != 0;
|
||||||
|
in_kswapd_reclaim = kswapd_start_tm.tv_sec != 0 || kswapd_start_tm.tv_nsec != 0;
|
||||||
|
} else {
|
||||||
|
in_direct_reclaim = vs.field.pgscan_direct != init_pgscan_direct;
|
||||||
|
in_kswapd_reclaim = (vs.field.pgscan_kswapd != init_pgscan_kswapd) ||
|
||||||
|
(vs.field.pgrefill != init_pgrefill);
|
||||||
|
}
|
||||||
|
|
||||||
/* Identify reclaim state */
|
/* Identify reclaim state */
|
||||||
if (in_direct_reclaim) {
|
if (in_direct_reclaim) {
|
||||||
|
|
@ -2736,13 +2744,10 @@ static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_
|
||||||
init_pgrefill = vs.field.pgrefill;
|
init_pgrefill = vs.field.pgrefill;
|
||||||
direct_reclaim_duration_ms = get_time_diff_ms(&direct_reclaim_start_tm, &curr_tm);
|
direct_reclaim_duration_ms = get_time_diff_ms(&direct_reclaim_start_tm, &curr_tm);
|
||||||
reclaim = DIRECT_RECLAIM;
|
reclaim = DIRECT_RECLAIM;
|
||||||
} else if (vs.field.pgscan_kswapd != init_pgscan_kswapd) {
|
} else if (in_kswapd_reclaim) {
|
||||||
init_pgscan_kswapd = vs.field.pgscan_kswapd;
|
init_pgscan_kswapd = vs.field.pgscan_kswapd;
|
||||||
init_pgrefill = vs.field.pgrefill;
|
init_pgrefill = vs.field.pgrefill;
|
||||||
reclaim = KSWAPD_RECLAIM;
|
reclaim = KSWAPD_RECLAIM;
|
||||||
} else if (vs.field.pgrefill != init_pgrefill) {
|
|
||||||
init_pgrefill = vs.field.pgrefill;
|
|
||||||
reclaim = KSWAPD_RECLAIM;
|
|
||||||
} else if (workingset_refault_file == prev_workingset_refault) {
|
} else if (workingset_refault_file == prev_workingset_refault) {
|
||||||
/*
|
/*
|
||||||
* Device is not thrashing and not reclaiming, bail out early until we see these stats
|
* Device is not thrashing and not reclaiming, bail out early until we see these stats
|
||||||
|
|
@ -3315,17 +3320,25 @@ static void memevent_listener_notification(int data __unused, uint32_t events __
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
for (const mem_event_t& mem_event : mem_events) {
|
||||||
* `mem_events` is ordered from oldest to newest, therefore we use
|
switch (mem_event.type) {
|
||||||
* the last/latest direct reclaim event as the current direct reclaim
|
/* Direct Reclaim */
|
||||||
* state.
|
case MEM_EVENT_DIRECT_RECLAIM_BEGIN:
|
||||||
*/
|
direct_reclaim_start_tm = curr_tm;
|
||||||
for (const mem_event_t mem_event : mem_events) {
|
break;
|
||||||
if (mem_event.type == MEM_EVENT_DIRECT_RECLAIM_BEGIN) {
|
case MEM_EVENT_DIRECT_RECLAIM_END:
|
||||||
direct_reclaim_start_tm = curr_tm;
|
direct_reclaim_start_tm.tv_sec = 0;
|
||||||
} else if (mem_event.type == MEM_EVENT_DIRECT_RECLAIM_END) {
|
direct_reclaim_start_tm.tv_nsec = 0;
|
||||||
direct_reclaim_start_tm.tv_sec = 0;
|
break;
|
||||||
direct_reclaim_start_tm.tv_nsec = 0;
|
|
||||||
|
/* kswapd */
|
||||||
|
case MEM_EVENT_KSWAPD_WAKE:
|
||||||
|
kswapd_start_tm = curr_tm;
|
||||||
|
break;
|
||||||
|
case MEM_EVENT_KSWAPD_SLEEP:
|
||||||
|
kswapd_start_tm.tv_sec = 0;
|
||||||
|
kswapd_start_tm.tv_nsec = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3353,6 +3366,12 @@ static bool init_memevent_listener_monitoring() {
|
||||||
memevent_listener.reset();
|
memevent_listener.reset();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!memevent_listener->registerEvent(MEM_EVENT_KSWAPD_WAKE) ||
|
||||||
|
!memevent_listener->registerEvent(MEM_EVENT_KSWAPD_SLEEP)) {
|
||||||
|
ALOGE("Failed to register kswapd memevents");
|
||||||
|
memevent_listener.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int memevent_listener_fd = memevent_listener->getRingBufferFd();
|
int memevent_listener_fd = memevent_listener->getRingBufferFd();
|
||||||
if (memevent_listener_fd < 0) {
|
if (memevent_listener_fd < 0) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue