Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25f1ac6b authored by Bill Rassieur's avatar Bill Rassieur
Browse files

Merge PQ1A.181205.006 from Pi-QPR1-Release into ToT for Pi-Platform release.\n\nBUG: 120448245

Change-Id: Ia66dd2a90e074d2fcb0dbaeb424031a41752dd03
parents a17e32ac 1b94df53
Loading
Loading
Loading
Loading
+70 −34
Original line number Diff line number Diff line
@@ -27,8 +27,8 @@
#include <sys/eventfd.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <unistd.h>

#include <cutils/properties.h>
@@ -79,6 +79,8 @@
#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
#define STRINGIFY_INTERNAL(x) #x

#define FAIL_REPORT_RLIMIT_MS 1000

/* default to old in-kernel interface if no memory pressure events */
static int use_inkernel_interface = 1;
static bool has_inkernel_module;
@@ -955,9 +957,10 @@ static struct proc *proc_get_heaviest(int oomadj) {
    return maxprocp;
}

static int last_killed_pid = -1;

/* Kill one process specified by procp.  Returns the size of the process killed */
static int kill_one_process(struct proc* procp, int min_score_adj,
                            enum vmpressure_level level) {
static int kill_one_process(struct proc* procp) {
    int pid = procp->pid;
    uid_t uid = procp->uid;
    char *taskname;
@@ -990,15 +993,14 @@ static int kill_one_process(struct proc* procp, int min_score_adj,
    TRACE_KILL_START(pid);

    r = kill(pid, SIGKILL);
    ALOGI(
        "Killing '%s' (%d), uid %d, adj %d\n"
        "   to free %ldkB because system is under %s memory pressure oom_adj %d\n",
        taskname, pid, uid, procp->oomadj, tasksize * page_k,
        level_name[level], min_score_adj);
    ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB",
        taskname, pid, uid, procp->oomadj, tasksize * page_k);
    pid_remove(pid);

    TRACE_KILL_END();

    last_killed_pid = pid;

    if (r) {
        ALOGE("kill(%d): errno=%d", pid, errno);
        return -1;
@@ -1021,8 +1023,7 @@ static int kill_one_process(struct proc* procp, int min_score_adj,
 * If pages_to_free is set to 0 only one process will be killed.
 * Returns the size of the killed processes.
 */
static int find_and_kill_processes(enum vmpressure_level level,
                                   int min_score_adj, int pages_to_free) {
static int find_and_kill_processes(int min_score_adj, int pages_to_free) {
    int i;
    int killed_size;
    int pages_freed = 0;
@@ -1041,7 +1042,7 @@ static int find_and_kill_processes(enum vmpressure_level level,
            if (!procp)
                break;

            killed_size = kill_one_process(procp, min_score_adj, level);
            killed_size = kill_one_process(procp);
            if (killed_size >= 0) {
#ifdef LMKD_LOG_STATS
                if (enable_stats_log && !lmk_state_change_start) {
@@ -1138,6 +1139,22 @@ static inline unsigned long get_time_diff_ms(struct timeval *from,
           (to->tv_usec - from->tv_usec) / 1000;
}

static bool is_kill_pending(void) {
    char buf[24];
    if (last_killed_pid < 0) {
        return false;
    }

    snprintf(buf, sizeof(buf), "/proc/%d/", last_killed_pid);
    if (access(buf, F_OK) == 0) {
        return true;
    }

    // reset last killed PID because there's nothing pending
    last_killed_pid = -1;
    return false;
}

static void mp_event_common(int data, uint32_t events __unused) {
    int ret;
    unsigned long long evcount;
@@ -1146,8 +1163,9 @@ static void mp_event_common(int data, uint32_t events __unused) {
    enum vmpressure_level lvl;
    union meminfo mi;
    union zoneinfo zi;
    static struct timeval last_report_tm;
    static unsigned long skip_count = 0;
    struct timeval curr_tm;
    static struct timeval last_kill_tm;
    static unsigned long kill_skip_count = 0;
    enum vmpressure_level level = (enum vmpressure_level)data;
    long other_free = 0, other_file = 0;
    int min_score_adj;
@@ -1176,19 +1194,22 @@ static void mp_event_common(int data, uint32_t events __unused) {
        }
    }

    if (kill_timeout_ms) {
        struct timeval curr_tm;
    gettimeofday(&curr_tm, NULL);
        if (get_time_diff_ms(&last_report_tm, &curr_tm) < kill_timeout_ms) {
            skip_count++;
    if (kill_timeout_ms) {
        // If we're within the timeout, see if there's pending reclaim work
        // from the last killed process. If there is (as evidenced by
        // /proc/<pid> continuing to exist), skip killing for now.
        if ((get_time_diff_ms(&last_kill_tm, &curr_tm) < kill_timeout_ms) &&
            (low_ram_device || is_kill_pending())) {
            kill_skip_count++;
            return;
        }
    }

    if (skip_count > 0) {
    if (kill_skip_count > 0) {
        ALOGI("%lu memory pressure events were skipped after a kill!",
              skip_count);
        skip_count = 0;
              kill_skip_count);
        kill_skip_count = 0;
    }

    if (meminfo_parse(&mi) < 0 || zoneinfo_parse(&zi) < 0) {
@@ -1280,13 +1301,15 @@ 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, level_oomadj[level], 0) == 0) {
        if (find_and_kill_processes(level_oomadj[level], 0) == 0) {
            if (debug_process_killing) {
                ALOGI("Nothing to kill");
            }
        }
    } else {
        int pages_freed;
        static struct timeval last_report_tm;
        static unsigned long report_skip_count = 0;

        if (!use_minfree_levels) {
            /* If pressure level is less than critical and enough free swap then ignore */
@@ -1314,24 +1337,37 @@ do_kill:
            min_score_adj = level_oomadj[level];
        }

        pages_freed = find_and_kill_processes(level, min_score_adj, pages_to_free);
        pages_freed = find_and_kill_processes(min_score_adj, 0);

        if (use_minfree_levels) {
            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");
        if (pages_freed == 0) {
            /* Rate limit kill reports when nothing was reclaimed */
            if (get_time_diff_ms(&last_report_tm, &curr_tm) < FAIL_REPORT_RLIMIT_MS) {
                report_skip_count++;
                return;
            }
        } else {
            /* If we killed anything, update the last killed timestamp. */
            last_kill_tm = curr_tm;
        }

        if (pages_freed < pages_to_free) {
            ALOGI("Unable to free enough memory (pages to free=%d, pages freed=%d)",
                  pages_to_free, pages_freed);
        if (use_minfree_levels) {
            ALOGI("Killing to reclaim %ldkB, reclaimed %ldkB, cache(%ldkB) and "
                "free(%" PRId64 "kB)-reserved(%" PRId64 "kB) below min(%ldkB) for oom_adj %d",
                pages_to_free * page_k, pages_freed * page_k,
                other_file * page_k, mi.field.nr_free_pages * page_k,
                zi.field.totalreserve_pages * page_k,
                minfree * page_k, min_score_adj);
        } else {
            ALOGI("Reclaimed enough memory (pages to free=%d, pages freed=%d)",
                  pages_to_free, pages_freed);
            gettimeofday(&last_report_tm, NULL);
            ALOGI("Killing to reclaim %ldkB, reclaimed %ldkB at oom_adj %d",
                pages_to_free * page_k, pages_freed * page_k, min_score_adj);
        }

        if (report_skip_count > 0) {
            ALOGI("Suppressed %lu failed kill reports", report_skip_count);
            report_skip_count = 0;
        }

        last_report_tm = curr_tm;
    }
}

+1 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ using namespace android::base;
#define LMKDTEST_RESPAWN_FLAG "LMKDTEST_RESPAWN"

#define LMKD_LOGCAT_MARKER "lowmemorykiller"
#define LMKD_KILL_MARKER_TEMPLATE LMKD_LOGCAT_MARKER ": Killing '%s'"
#define LMKD_KILL_MARKER_TEMPLATE LMKD_LOGCAT_MARKER ": Kill '%s'"
#define OOM_MARKER "Out of memory"
#define OOM_KILL_MARKER "Killed process"
#define MIN_LOG_SIZE 100