diff --git a/aosp/system/memory/lmkd/Android.bp b/aosp/system/memory/lmkd/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..d6abe761468d460adb6c52ba9b3272e4d2f52da8 --- /dev/null +++ b/aosp/system/memory/lmkd/Android.bp @@ -0,0 +1,103 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +soong_config_module_type { + name: "lmkd_hooks_cc_defaults", + module_type: "cc_defaults", + config_namespace: "lmkd", + bool_variables: ["use_hooks"], + properties: [ + "cflags", + "static_libs", + ], +} + +lmkd_hooks_cc_defaults { + name: "lmkd_hooks_defaults", + + soong_config_variables: { + use_hooks: { + cflags: [ + "-DLMKD_USE_HOOKS" + ], + static_libs: [ + "liblmkdhooks" + ] + } + } +} + +cc_defaults { + name: "stats_defaults", + cflags: [ + "-DLMKD_LOG_STATS" + ], +} + +cc_binary { + name: "lmkd", + + srcs: [ + "lmkd.cpp", + "reaper.cpp", + "watchdog.cpp", + ], + shared_libs: [ + "libcutils", + "liblog", + "libprocessgroup", + "libpsi", + "libvamem", + ], + static_libs: [ + "libstatslogc", + "liblmkd_utils", + ], + header_libs: [ + "bpf_syscall_wrappers", + ], + local_include_dirs: ["include"], + cflags: [ + "-Wall", + "-Werror", + "-Wextra", + "-DLMKD_TRACE_KILLS" + ], + init_rc: ["lmkd.rc"], + defaults: ["stats_defaults", "lmkd_hooks_defaults"], + logtags: ["event.logtags"], + afdo: true, +} + +cc_library_static { + name: "libstatslogc", + srcs: ["statslog.cpp"], + local_include_dirs: ["include"], + cflags: [ + "-Wall", + "-Werror", + "-Wextra", + ], + defaults: ["stats_defaults"], + shared_libs: [ + "liblog", + "libprocessgroup", + ], +} + +cc_library_static { + name: "liblmkd_utils", + srcs: ["liblmkd_utils.cpp"], + recovery_available: true, + shared_libs: [ + "libcutils", + "libprocessgroup", + ], + export_include_dirs: ["include"], + cppflags: [ + "-g", + "-Wall", + "-Werror", + ] +} diff --git a/aosp/system/memory/lmkd/libvamem/Android.bp b/aosp/system/memory/lmkd/libvamem/Android.bp new file mode 100644 index 0000000000000000000000000000000000000000..380ffbf78c0b788e055c40d0794f8c05f7264af4 --- /dev/null +++ b/aosp/system/memory/lmkd/libvamem/Android.bp @@ -0,0 +1,22 @@ +cc_library_headers { + name: "libvamem_headers", + export_include_dirs: ["include"], +} + +cc_library { + name: "libvamem", + srcs: ["vamem.cpp"], + shared_libs: [ + "liblog" + ], + header_libs: [ + "libvamem_headers", + ], + export_header_lib_headers: [ + "libvamem_headers", + ], + cflags: [ + "-Wall", + "-Werror", + ], +} \ No newline at end of file diff --git a/aosp/system/memory/lmkd/libvamem/include/vamem/vamem.h b/aosp/system/memory/lmkd/libvamem/include/vamem/vamem.h new file mode 100644 index 0000000000000000000000000000000000000000..9c01422220b42345ce9a4e8b36ad041626c09558 --- /dev/null +++ b/aosp/system/memory/lmkd/libvamem/include/vamem/vamem.h @@ -0,0 +1,19 @@ +#ifndef __ANDROID_VAMEM_H__ +#define __ANDROID_VAMEM_H__ + +#include +#include + +__BEGIN_DECLS + +int init_vamem_monitor(); + +int register_vamem_monitor(int epollfd, int fd, void* data); + +int unregister_vamem_monitor(int epollfd, int fd); + +void destroy_vamem_monitor(int fd); + +__END_DECLS + +#endif // __ANDROID_VAMEM_H__ \ No newline at end of file diff --git a/aosp/system/memory/lmkd/libvamem/vamem.cpp b/aosp/system/memory/lmkd/libvamem/vamem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d516f081f74487ff14cc1dc4934d02027c1a8b03 --- /dev/null +++ b/aosp/system/memory/lmkd/libvamem/vamem.cpp @@ -0,0 +1,48 @@ +#define LOG_TAG "libvamem" + +#include +#include +#include +#include + +#include +#include "vamem/vamem.h" + +#define VAMEM_GPU_FMT "/dev/gpu_mem_stats" + +int init_vamem_monitor() { + int fd; + + fd = TEMP_FAILURE_RETRY(open(VAMEM_GPU_FMT, O_WRONLY | O_CLOEXEC)); + if (fd < 0) { + ALOGE("Failed to open vamem_debugfs_path %s (errno=%d)", VAMEM_GPU_FMT, errno); + return -1; + } + + ALOGI("vamem monitor init success"); + + return fd; +} + +int register_vamem_monitor(int epollfd, int fd, void* data) { + int res; + struct epoll_event epev; + + epev.events = EPOLLPRI; + epev.data.ptr = data; + res = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &epev); + if (res < 0) { + ALOGE("epoll_ctl for vamem monitor failed; errno=%d", errno); + } + return res; +} + +int unregister_vamem_monitor(int epollfd, int fd) { + return epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL); +} + +void destroy_vamem_monitor(int fd) { + if (fd >= 0) { + close(fd); + } +} \ No newline at end of file diff --git a/aosp/system/memory/lmkd/lmkd.cpp b/aosp/system/memory/lmkd/lmkd.cpp index 63f42469932fa3fd963360b2a8e64154a792763d..a7f79fdc1cc206ce3475288f117d85f6a8830138 100644 --- a/aosp/system/memory/lmkd/lmkd.cpp +++ b/aosp/system/memory/lmkd/lmkd.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include "reaper.h" #include "statslog.h" @@ -225,6 +226,8 @@ static struct psi_threshold psi_thresholds[VMPRESS_LEVEL_COUNT] = { { PSI_FULL, 70 }, /* 70ms out of 1sec for complete stall */ }; +static int vamem_score; + static android_log_context ctx; static Reaper reaper; static int reaper_comm_fd[2]; @@ -275,6 +278,9 @@ static struct sock_event_handler_info data_sock[MAX_DATA_CONN]; /* vmpressure event handler data */ static struct event_handler_info vmpressure_hinfo[VMPRESS_LEVEL_COUNT]; +/* vamem event handler data */ +static struct event_handler_info vamem_hinfo; + /* * 1 ctrl listen socket, 3 ctrl data socket, 3 memory pressure levels, * 1 lmk events + 1 fd to wait for process death + 1 fd to receive kill failure notifications @@ -2923,6 +2929,29 @@ static std::string GetCgroupAttributePath(const char* attr) { return path; } +static void free_vamem_cb(int data __unused, uint32_t events __unused, + struct polling_params *poll_params __unused) { + union meminfo mi; + struct timespec curr_tm; + static struct wakeup_info wi; + + if (meminfo_parse(&mi) < 0) { + ALOGE("meminfo_parse failed!"); + return; + } + + if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) { + ALOGE("Failed to get current time"); + return; + } + + record_wakeup_time(&curr_tm, Polling, &wi); + + if (find_and_kill_process(vamem_score, NULL, &mi, &wi, &curr_tm, NULL)) { + ALOGE("vamem oom event triggered"); + } +} + // The implementation of this function relies on memcg statistics that are only available in the // v1 cgroup hierarchy. static void mp_event_common(int data, uint32_t events, struct polling_params *poll_params) { @@ -3164,6 +3193,22 @@ do_kill: } } +static bool init_vamem() { + int fd; + fd = init_vamem_monitor(); + if (fd < 0) { + return false; + } + vamem_hinfo.handler = free_vamem_cb; + vamem_hinfo.data = -1; + if (register_vamem_monitor(epollfd, fd, &vamem_hinfo) < 0) { + destroy_vamem_monitor(fd); + return false; + } + maxevents++; + return true; +} + static bool init_mp_psi(enum vmpressure_level level, bool use_new_strategy) { int fd; @@ -3383,6 +3428,9 @@ static bool init_monitors() { ALOGI("Using vmpressure for memory pressure detection"); } monitors_initialized = true; + if (!init_vamem()) { + ALOGE("init_vamem failed"); + } return true; } @@ -3799,6 +3847,8 @@ static bool update_props() { reaper.enable_debug(debug_process_killing); + vamem_score = 700; + /* Call the update props hook */ if (!lmkd_update_props_hook()) { ALOGE("Failed to update LMKD hook props.");