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

Commit fd7eafca authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 5073521 from e77572d7 to pi-qpr2-release

Change-Id: Ic9faca28265d0f09225bf6e509087ad552c2f9b8
parents b50aaf27 e77572d7
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ enum lmk_cmd {
    LMK_TARGET = 0,  /* Associate minfree with oom_adj_score */
    LMK_PROCPRIO,    /* Register a process and set its oom_adj_score */
    LMK_PROCREMOVE,  /* Unregister a process */
    LMK_PROCPURGE,   /* Purge all registered processes */
};

/*
@@ -142,6 +143,15 @@ inline size_t lmkd_pack_set_procremove(LMKD_CTRL_PACKET packet,
    return 2 * sizeof(int);
}

/*
 * Prepare LMK_PROCPURGE packet and return packet size in bytes.
 * Warning: no checks performed, caller should ensure valid parameters.
 */
inline size_t lmkd_pack_set_procpurge(LMKD_CTRL_PACKET packet) {
    packet[0] = htonl(LMK_PROCPURGE);
    return sizeof(int);
}

__END_DECLS

#endif /* _LMKD_H_ */
+109 −25
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ static bool low_ram_device;
static bool kill_heaviest_task;
static unsigned long kill_timeout_ms;
static bool use_minfree_levels;
static bool per_app_memcg;

/* data required to handle events */
struct event_handler_info {
@@ -523,9 +524,38 @@ static void cmd_procremove(LMKD_CTRL_PACKET packet) {
        return;

    lmkd_pack_get_procremove(packet, &params);
    /*
     * WARNING: After pid_remove() procp is freed and can't be used!
     * Therefore placed at the end of the function.
     */
    pid_remove(params.pid);
}

static void cmd_procpurge() {
    int i;
    struct proc *procp;
    struct proc *next;

    if (use_inkernel_interface) {
        return;
    }

    for (i = 0; i <= ADJTOSLOT(OOM_SCORE_ADJ_MAX); i++) {
        procadjslot_list[i].next = &procadjslot_list[i];
        procadjslot_list[i].prev = &procadjslot_list[i];
    }

    for (i = 0; i < PIDHASH_SZ; i++) {
        procp = pidhash[i];
        while (procp) {
            next = procp->pidhash_next;
            free(procp);
            procp = next;
        }
    }
    memset(&pidhash[0], 0, sizeof(pidhash));
}

static void cmd_target(int ntargets, LMKD_CTRL_PACKET packet) {
    int i;
    struct lmk_target target;
@@ -634,6 +664,11 @@ static void ctrl_command_handler(int dsock_idx) {
            goto wronglen;
        cmd_procremove(packet);
        break;
    case LMK_PROCPURGE:
        if (nargs != 0)
            goto wronglen;
        cmd_procpurge();
        break;
    default:
        ALOGE("Received unknown command code %d", cmd);
        return;
@@ -721,7 +756,7 @@ static void memory_stat_parse_line(char *line, struct memory_stat *mem_st) {
        mem_st->swap_in_bytes = value;
}

static int memory_stat_parse(struct memory_stat *mem_st,  int pid, uid_t uid) {
static int memory_stat_from_cgroup(struct memory_stat* mem_st, int pid, uid_t uid) {
    FILE* fp;
    char buf[PATH_MAX];

@@ -741,6 +776,43 @@ static int memory_stat_parse(struct memory_stat *mem_st, int pid, uid_t uid) {

    return 0;
}

static int memory_stat_from_procfs(struct memory_stat* mem_st, int pid) {
    char path[PATH_MAX];
    char buffer[PROC_STAT_BUFFER_SIZE];
    int fd, ret;

    snprintf(path, sizeof(path), PROC_STAT_FILE_PATH, pid);
    if ((fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) {
        ALOGE("%s open failed: %s", path, strerror(errno));
        return -1;
    }

    ret = read(fd, buffer, sizeof(buffer));
    if (ret < 0) {
        ALOGE("%s read failed: %s", path, strerror(errno));
        close(fd);
        return -1;
    }
    close(fd);

    // field 10 is pgfault
    // field 12 is pgmajfault
    // field 24 is rss_in_pages
    int64_t pgfault = 0, pgmajfault = 0, rss_in_pages = 0;
    if (sscanf(buffer,
               "%*u %*s %*s %*d %*d %*d %*d %*d %*d %" SCNd64 " %*d "
               "%" SCNd64 " %*d %*u %*u %*d %*d %*d %*d %*d %*d "
               "%*d %*d %" SCNd64 "",
               &pgfault, &pgmajfault, &rss_in_pages) != 3) {
        return -1;
    }
    mem_st->pgfault = pgfault;
    mem_st->pgmajfault = pgmajfault;
    mem_st->rss_in_bytes = (rss_in_pages * PAGE_SIZE);

    return 0;
}
#endif

/* /prop/zoneinfo parsing routines */
@@ -964,6 +1036,7 @@ static int kill_one_process(struct proc* procp) {
    char *taskname;
    int tasksize;
    int r;
    int result = -1;

#ifdef LMKD_LOG_STATS
    struct memory_stat mem_st = {};
@@ -972,46 +1045,57 @@ static int kill_one_process(struct proc* procp) {

    taskname = proc_get_name(pid);
    if (!taskname) {
        pid_remove(pid);
        return -1;
        goto out;
    }

    tasksize = proc_get_size(pid);
    if (tasksize <= 0) {
        pid_remove(pid);
        return -1;
        goto out;
    }

#ifdef LMKD_LOG_STATS
    if (enable_stats_log) {
        memory_stat_parse_result = memory_stat_parse(&mem_st, pid, uid);
        if (per_app_memcg) {
            memory_stat_parse_result = memory_stat_from_cgroup(&mem_st, pid, uid);
        } else {
            memory_stat_parse_result = memory_stat_from_procfs(&mem_st, pid);
        }
    }
#endif

    TRACE_KILL_START(pid);

    /* CAP_KILL required */
    r = kill(pid, SIGKILL);
    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();

    if (r) {
        ALOGE("kill(%d): errno=%d", pid, errno);
        return -1;
        goto out;
    } else {
#ifdef LMKD_LOG_STATS
        if (memory_stat_parse_result == 0) {
            stats_write_lmk_kill_occurred(log_ctx, LMK_KILL_OCCURRED, uid, taskname,
                    procp->oomadj, mem_st.pgfault, mem_st.pgmajfault, mem_st.rss_in_bytes,
                    mem_st.cache_in_bytes, mem_st.swap_in_bytes);
        } else if (enable_stats_log) {
            stats_write_lmk_kill_occurred(log_ctx, LMK_KILL_OCCURRED, uid, taskname, procp->oomadj,
                                          -1, -1, tasksize * BYTES_IN_KILOBYTE, -1, -1);
        }
#endif
        return tasksize;
        result = tasksize;
    }

    return tasksize;
out:
    /*
     * WARNING: After pid_remove() procp is freed and can't be used!
     * Therefore placed at the end of the function.
     */
    pid_remove(pid);
    return result;
}

/*
@@ -1556,7 +1640,7 @@ int main(int argc __unused, char **argv __unused) {
        (unsigned long)property_get_int32("ro.lmk.kill_timeout_ms", 0);
    use_minfree_levels =
        property_get_bool("ro.lmk.use_minfree_levels", false);

    per_app_memcg = property_get_bool("ro.config.per_app_memcg", low_ram_device);
#ifdef LMKD_LOG_STATS
    statslog_init(&log_ctx, &enable_stats_log);
#endif
+3 −0
Original line number Diff line number Diff line
@@ -67,6 +67,9 @@ struct memory_stat {
};

#define MEMCG_PROCESS_MEMORY_STAT_PATH "/dev/memcg/apps/uid_%u/pid_%u/memory.stat"
#define PROC_STAT_FILE_PATH "/proc/%d/stat"
#define PROC_STAT_BUFFER_SIZE 1024
#define BYTES_IN_KILOBYTE 1024

/**
 * Logs the change in LMKD state which is used as start/stop boundaries for logging