Add boot completed cmd to LMKD
Add new command to allow for post-boot actions to occur. This will allow for the MemEventListener to start after the BPF files are loaded, removing the need to stall during boot-up until they are loaded in the device. Test: Verified memevent listener initialized post-boot Test: Verified LMKD no longer stalls until BPF progs are loaded Bug: 331008250 Bug: 244232958 Change-Id: I55f97b41349ea7693cff81b1170d33712b820292 Signed-off-by: Carlos Galo <carlosgalo@google.com>
This commit is contained in:
parent
81a7c21087
commit
65c1b5dcc5
|
|
@ -71,6 +71,20 @@ enum update_props_result lmkd_update_props(int sock);
|
||||||
*/
|
*/
|
||||||
int create_memcg(uid_t uid, pid_t pid);
|
int create_memcg(uid_t uid, pid_t pid);
|
||||||
|
|
||||||
|
enum boot_completed_notification_result {
|
||||||
|
BOOT_COMPLETED_NOTIF_SUCCESS,
|
||||||
|
BOOT_COMPLETED_NOTIF_FAILS,
|
||||||
|
BOOT_COMPLETED_NOTIF_ALREADY_HANDLED,
|
||||||
|
BOOT_COMPLETED_NOTIF_SEND_ERR,
|
||||||
|
BOOT_COMPLETED_NOTIF_RECV_ERR,
|
||||||
|
BOOT_COMPLETED_NOTIF_FORMAT_ERR,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notify LMKD the device has finished booting up.
|
||||||
|
*/
|
||||||
|
enum boot_completed_notification_result lmkd_notify_boot_completed(int sock);
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
#endif /* _LIBLMKD_UTILS_H_ */
|
#endif /* _LIBLMKD_UTILS_H_ */
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ enum lmk_cmd {
|
||||||
LMK_UPDATE_PROPS, /* Reinit properties */
|
LMK_UPDATE_PROPS, /* Reinit properties */
|
||||||
LMK_STAT_KILL_OCCURRED, /* Unsolicited msg to subscribed clients on proc kills for statsd log */
|
LMK_STAT_KILL_OCCURRED, /* Unsolicited msg to subscribed clients on proc kills for statsd log */
|
||||||
LMK_START_MONITORING, /* Start psi monitoring if it was skipped earlier */
|
LMK_START_MONITORING, /* Start psi monitoring if it was skipped earlier */
|
||||||
|
LMK_BOOT_COMPLETED, /* Notify LMKD boot is completed */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -281,7 +282,7 @@ static inline size_t lmkd_pack_set_update_props_repl(LMKD_CTRL_PACKET packet, in
|
||||||
return 2 * sizeof(int);
|
return 2 * sizeof(int);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LMK_PROCPRIO reply payload */
|
/* LMK_UPDATE_PROPS reply payload */
|
||||||
struct lmk_update_props_reply {
|
struct lmk_update_props_reply {
|
||||||
int result;
|
int result;
|
||||||
};
|
};
|
||||||
|
|
@ -295,6 +296,39 @@ static inline void lmkd_pack_get_update_props_repl(LMKD_CTRL_PACKET packet,
|
||||||
params->result = ntohl(packet[1]);
|
params->result = ntohl(packet[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare LMK_BOOT_COMPLETED packet and return packet size in bytes.
|
||||||
|
* Warning: no checks performed, caller should ensure valid parameters.
|
||||||
|
*/
|
||||||
|
static inline size_t lmkd_pack_set_boot_completed_notif(LMKD_CTRL_PACKET packet) {
|
||||||
|
packet[0] = htonl(LMK_BOOT_COMPLETED);
|
||||||
|
return sizeof(int);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare LMK_BOOT_COMPLETED reply packet and return packet size in bytes.
|
||||||
|
* Warning: no checks performed, caller should ensure valid parameters.
|
||||||
|
*/
|
||||||
|
static inline size_t lmkd_pack_set_boot_completed_notif_repl(LMKD_CTRL_PACKET packet, int result) {
|
||||||
|
packet[0] = htonl(LMK_BOOT_COMPLETED);
|
||||||
|
packet[1] = htonl(result);
|
||||||
|
return 2 * sizeof(int);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LMK_BOOT_COMPLETED reply payload */
|
||||||
|
struct lmk_boot_completed_notif_reply {
|
||||||
|
int result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For LMK_BOOT_COMPLETED reply payload.
|
||||||
|
* Warning: no checks performed, caller should ensure valid parameters.
|
||||||
|
*/
|
||||||
|
static inline void lmkd_pack_get_boot_completed_notif_repl(
|
||||||
|
LMKD_CTRL_PACKET packet, struct lmk_boot_completed_notif_reply* params) {
|
||||||
|
params->result = ntohl(packet[1]);
|
||||||
|
}
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
#endif /* _LMKD_H_ */
|
#endif /* _LMKD_H_ */
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,46 @@ enum update_props_result lmkd_update_props(int sock) {
|
||||||
return params.result == 0 ? UPDATE_PROPS_SUCCESS : UPDATE_PROPS_FAIL;
|
return params.result == 0 ? UPDATE_PROPS_SUCCESS : UPDATE_PROPS_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum boot_completed_notification_result lmkd_notify_boot_completed(int sock) {
|
||||||
|
LMKD_CTRL_PACKET packet;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
size = lmkd_pack_set_boot_completed_notif(packet);
|
||||||
|
if (TEMP_FAILURE_RETRY(write(sock, packet, size)) < 0) {
|
||||||
|
return BOOT_COMPLETED_NOTIF_SEND_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = TEMP_FAILURE_RETRY(read(sock, packet, CTRL_PACKET_MAX_SIZE));
|
||||||
|
if (size < 0) {
|
||||||
|
return BOOT_COMPLETED_NOTIF_RECV_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size != 2 * sizeof(int) || lmkd_pack_get_cmd(packet) != LMK_BOOT_COMPLETED) {
|
||||||
|
return BOOT_COMPLETED_NOTIF_FORMAT_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct lmk_boot_completed_notif_reply params;
|
||||||
|
lmkd_pack_get_boot_completed_notif_repl(packet, ¶ms);
|
||||||
|
|
||||||
|
enum boot_completed_notification_result res;
|
||||||
|
switch (params.result) {
|
||||||
|
case -1:
|
||||||
|
res = BOOT_COMPLETED_NOTIF_FAILS;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
res = BOOT_COMPLETED_NOTIF_SUCCESS;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
res = BOOT_COMPLETED_NOTIF_ALREADY_HANDLED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* This should never be reached */
|
||||||
|
res = BOOT_COMPLETED_NOTIF_FAILS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
int create_memcg(uid_t uid, pid_t pid) {
|
int create_memcg(uid_t uid, pid_t pid) {
|
||||||
return createProcessGroup(uid, pid, true) == 0 ? 0 : -1;
|
return createProcessGroup(uid, pid, true) == 0 ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
114
lmkd.cpp
114
lmkd.cpp
|
|
@ -205,6 +205,7 @@ static bool pidfd_supported;
|
||||||
static int last_kill_pid_or_fd = -1;
|
static int last_kill_pid_or_fd = -1;
|
||||||
static struct timespec last_kill_tm;
|
static struct timespec last_kill_tm;
|
||||||
static bool monitors_initialized;
|
static bool monitors_initialized;
|
||||||
|
static bool boot_completed_handled = false;
|
||||||
|
|
||||||
/* lmkd configurable parameters */
|
/* lmkd configurable parameters */
|
||||||
static bool debug_process_killing;
|
static bool debug_process_killing;
|
||||||
|
|
@ -569,6 +570,7 @@ static long page_k; /* page size in kB */
|
||||||
static bool update_props();
|
static bool update_props();
|
||||||
static bool init_monitors();
|
static bool init_monitors();
|
||||||
static void destroy_monitors();
|
static void destroy_monitors();
|
||||||
|
static bool init_direct_reclaim_monitoring();
|
||||||
|
|
||||||
static int clamp(int low, int high, int value) {
|
static int clamp(int low, int high, int value) {
|
||||||
return std::max(std::min(value, high), low);
|
return std::max(std::min(value, high), low);
|
||||||
|
|
@ -1537,6 +1539,11 @@ static void ctrl_command_handler(int dsock_idx) {
|
||||||
} else {
|
} else {
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (direct_reclaim_threshold_ms > 0 && !memevent_listener) {
|
||||||
|
ALOGW("Kernel support for direct_reclaim_threshold_ms is not found");
|
||||||
|
direct_reclaim_threshold_ms = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
len = lmkd_pack_set_update_props_repl(packet, result);
|
len = lmkd_pack_set_update_props_repl(packet, result);
|
||||||
|
|
@ -1569,6 +1576,38 @@ static void ctrl_command_handler(int dsock_idx) {
|
||||||
}
|
}
|
||||||
ALOGI("Initialized monitors after boot completed.");
|
ALOGI("Initialized monitors after boot completed.");
|
||||||
break;
|
break;
|
||||||
|
case LMK_BOOT_COMPLETED:
|
||||||
|
if (nargs != 0) goto wronglen;
|
||||||
|
|
||||||
|
if (boot_completed_handled) {
|
||||||
|
/* Notify we have already handled post boot-up operations */
|
||||||
|
result = 1;
|
||||||
|
} else if (!property_get_bool("sys.boot_completed", false)) {
|
||||||
|
ALOGE("LMK_BOOT_COMPLETED cannot be handled before boot completed");
|
||||||
|
result = -1;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Initialize the memevent listener after boot is completed to prevent
|
||||||
|
* waiting, during boot-up, for BPF programs to be loaded.
|
||||||
|
*/
|
||||||
|
if (init_direct_reclaim_monitoring()) {
|
||||||
|
ALOGI("Using memevents for direct reclaim detection");
|
||||||
|
} else {
|
||||||
|
ALOGI("Using vmstats for direct reclaim detection");
|
||||||
|
if (direct_reclaim_threshold_ms > 0) {
|
||||||
|
ALOGW("Kernel support for direct_reclaim_threshold_ms is not found");
|
||||||
|
direct_reclaim_threshold_ms = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = 0;
|
||||||
|
boot_completed_handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = lmkd_pack_set_boot_completed_notif_repl(packet, result);
|
||||||
|
if (ctrl_data_write(dsock_idx, (char*)packet, len) != len) {
|
||||||
|
ALOGE("Failed to report boot-completed operation results");
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ALOGE("Received unknown command code %d", cmd);
|
ALOGE("Received unknown command code %d", cmd);
|
||||||
return;
|
return;
|
||||||
|
|
@ -3294,12 +3333,12 @@ static void direct_reclaim_state_change(int data __unused, uint32_t events __unu
|
||||||
static bool init_direct_reclaim_monitoring() {
|
static bool init_direct_reclaim_monitoring() {
|
||||||
static struct event_handler_info direct_reclaim_poll_hinfo = {0, direct_reclaim_state_change};
|
static struct event_handler_info direct_reclaim_poll_hinfo = {0, direct_reclaim_state_change};
|
||||||
|
|
||||||
if (!memevent_listener) {
|
if (memevent_listener) return true;
|
||||||
// Make sure bpf programs are loaded
|
|
||||||
|
// Make sure bpf programs are loaded, else we'll wait until they are loaded
|
||||||
android::bpf::waitForProgsLoaded();
|
android::bpf::waitForProgsLoaded();
|
||||||
memevent_listener = std::make_unique<android::bpf::memevents::MemEventListener>(
|
memevent_listener = std::make_unique<android::bpf::memevents::MemEventListener>(
|
||||||
android::bpf::memevents::MemEventClient::LMKD);
|
android::bpf::memevents::MemEventClient::LMKD);
|
||||||
}
|
|
||||||
|
|
||||||
if (!memevent_listener->ok()) {
|
if (!memevent_listener->ok()) {
|
||||||
ALOGE("Failed to initialize memevents listener");
|
ALOGE("Failed to initialize memevents listener");
|
||||||
|
|
@ -3326,10 +3365,6 @@ static bool init_direct_reclaim_monitoring() {
|
||||||
epev.data.ptr = (void*)&direct_reclaim_poll_hinfo;
|
epev.data.ptr = (void*)&direct_reclaim_poll_hinfo;
|
||||||
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, memevent_listener_fd, &epev) < 0) {
|
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, memevent_listener_fd, &epev) < 0) {
|
||||||
ALOGE("Failed registering direct reclaim fd: %d; errno=%d", memevent_listener_fd, errno);
|
ALOGE("Failed registering direct reclaim fd: %d; errno=%d", memevent_listener_fd, errno);
|
||||||
/*
|
|
||||||
* Reset the fd to let `destroy_direct_reclaim_monitoring` know we failed adding this fd,
|
|
||||||
* therefore it won't try to close the `memevent_listener_fd`.
|
|
||||||
*/
|
|
||||||
memevent_listener.reset();
|
memevent_listener.reset();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -3341,19 +3376,6 @@ static bool init_direct_reclaim_monitoring() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void destroy_direct_reclaim_monitoring() {
|
|
||||||
if (!memevent_listener) return;
|
|
||||||
|
|
||||||
if (epoll_ctl(epollfd, EPOLL_CTL_DEL, memevent_listener->getRingBufferFd(), NULL) < 0) {
|
|
||||||
ALOGE("Failed to unregister direct reclaim monitoring; errno=%d", errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
maxevents--;
|
|
||||||
memevent_listener.reset();
|
|
||||||
direct_reclaim_start_tm.tv_sec = 0;
|
|
||||||
direct_reclaim_start_tm.tv_nsec = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool init_psi_monitors() {
|
static bool init_psi_monitors() {
|
||||||
/*
|
/*
|
||||||
* When PSI is used on low-ram devices or on high-end devices without memfree levels
|
* When PSI is used on low-ram devices or on high-end devices without memfree levels
|
||||||
|
|
@ -3505,16 +3527,6 @@ static bool init_monitors() {
|
||||||
ALOGI("Using vmpressure for memory pressure detection");
|
ALOGI("Using vmpressure for memory pressure detection");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_direct_reclaim_monitoring()) {
|
|
||||||
ALOGI("Using memevents for direct reclaim detection");
|
|
||||||
} else {
|
|
||||||
ALOGI("Using vmstats for direct reclaim detection");
|
|
||||||
if (direct_reclaim_threshold_ms > 0) {
|
|
||||||
ALOGW("Kernel support for direct_reclaim_threshold_ms is not found");
|
|
||||||
direct_reclaim_threshold_ms = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
monitors_initialized = true;
|
monitors_initialized = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -3529,7 +3541,6 @@ static void destroy_monitors() {
|
||||||
destroy_mp_common(VMPRESS_LEVEL_MEDIUM);
|
destroy_mp_common(VMPRESS_LEVEL_MEDIUM);
|
||||||
destroy_mp_common(VMPRESS_LEVEL_LOW);
|
destroy_mp_common(VMPRESS_LEVEL_LOW);
|
||||||
}
|
}
|
||||||
destroy_direct_reclaim_monitoring();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drop_reaper_comm() {
|
static void drop_reaper_comm() {
|
||||||
|
|
@ -3885,6 +3896,41 @@ int issue_reinit() {
|
||||||
return res == UPDATE_PROPS_SUCCESS ? 0 : -1;
|
return res == UPDATE_PROPS_SUCCESS ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int on_boot_completed() {
|
||||||
|
int sock;
|
||||||
|
|
||||||
|
sock = lmkd_connect();
|
||||||
|
if (sock < 0) {
|
||||||
|
ALOGE("failed to connect to lmkd: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum boot_completed_notification_result res = lmkd_notify_boot_completed(sock);
|
||||||
|
|
||||||
|
switch (res) {
|
||||||
|
case BOOT_COMPLETED_NOTIF_SUCCESS:
|
||||||
|
break;
|
||||||
|
case BOOT_COMPLETED_NOTIF_ALREADY_HANDLED:
|
||||||
|
ALOGW("lmkd already handled boot-completed operations");
|
||||||
|
break;
|
||||||
|
case BOOT_COMPLETED_NOTIF_SEND_ERR:
|
||||||
|
ALOGE("failed to send lmkd request: %m");
|
||||||
|
break;
|
||||||
|
case BOOT_COMPLETED_NOTIF_RECV_ERR:
|
||||||
|
ALOGE("failed to receive request: %m");
|
||||||
|
break;
|
||||||
|
case BOOT_COMPLETED_NOTIF_FORMAT_ERR:
|
||||||
|
ALOGE("lmkd reply is invalid");
|
||||||
|
break;
|
||||||
|
case BOOT_COMPLETED_NOTIF_FAILS:
|
||||||
|
ALOGE("lmkd failed to receive boot-completed notification");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sock);
|
||||||
|
return res == BOOT_COMPLETED_NOTIF_SUCCESS ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
static bool update_props() {
|
static bool update_props() {
|
||||||
/* By default disable low level vmpressure events */
|
/* By default disable low level vmpressure events */
|
||||||
level_oomadj[VMPRESS_LEVEL_LOW] =
|
level_oomadj[VMPRESS_LEVEL_LOW] =
|
||||||
|
|
@ -3945,11 +3991,15 @@ static bool update_props() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) {
|
if ((argc > 1) && argv[1]) {
|
||||||
|
if (!strcmp(argv[1], "--reinit")) {
|
||||||
if (property_set(LMKD_REINIT_PROP, "")) {
|
if (property_set(LMKD_REINIT_PROP, "")) {
|
||||||
ALOGE("Failed to reset " LMKD_REINIT_PROP " property");
|
ALOGE("Failed to reset " LMKD_REINIT_PROP " property");
|
||||||
}
|
}
|
||||||
return issue_reinit();
|
return issue_reinit();
|
||||||
|
} else if (!strcmp(argv[1], "--boot_completed")) {
|
||||||
|
return on_boot_completed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!update_props()) {
|
if (!update_props()) {
|
||||||
|
|
|
||||||
3
lmkd.rc
3
lmkd.rc
|
|
@ -10,6 +10,9 @@ service lmkd /system/bin/lmkd
|
||||||
on property:lmkd.reinit=1
|
on property:lmkd.reinit=1
|
||||||
exec_background /system/bin/lmkd --reinit
|
exec_background /system/bin/lmkd --reinit
|
||||||
|
|
||||||
|
on property:sys.boot_completed=1
|
||||||
|
exec_background /system/bin/lmkd --boot_completed
|
||||||
|
|
||||||
# reinitialize lmkd after device finished booting if experiments set any flags during boot
|
# reinitialize lmkd after device finished booting if experiments set any flags during boot
|
||||||
on property:sys.boot_completed=1 && property:lmkd.reinit=0
|
on property:sys.boot_completed=1 && property:lmkd.reinit=0
|
||||||
setprop lmkd.reinit 1
|
setprop lmkd.reinit 1
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue