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

Commit a1c684be authored by Suren Baghdasaryan's avatar Suren Baghdasaryan Committed by Gerrit Code Review
Browse files

Merge "lmkd: Add command to get number of kills"

parents 19fb58ce d4a29903
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ enum lmk_cmd {
    LMK_PROCPRIO,    /* Register a process and set its oom_adj_score */
    LMK_PROCREMOVE,  /* Unregister a process */
    LMK_PROCPURGE,   /* Purge all registered processes */
    LMK_GETKILLCNT,  /* Get number of kills */
};

/*
@@ -152,6 +153,44 @@ inline size_t lmkd_pack_set_procpurge(LMKD_CTRL_PACKET packet) {
    return sizeof(int);
}

/* LMK_GETKILLCNT packet payload */
struct lmk_getkillcnt {
    int min_oomadj;
    int max_oomadj;
};

/*
 * For LMK_GETKILLCNT packet get its payload.
 * Warning: no checks performed, caller should ensure valid parameters.
 */
inline void lmkd_pack_get_getkillcnt(LMKD_CTRL_PACKET packet,
                                   struct lmk_getkillcnt *params) {
    params->min_oomadj = ntohl(packet[1]);
    params->max_oomadj = ntohl(packet[2]);
}

/*
 * Prepare LMK_GETKILLCNT packet and return packet size in bytes.
 * Warning: no checks performed, caller should ensure valid parameters.
 */
inline size_t lmkd_pack_set_getkillcnt(LMKD_CTRL_PACKET packet,
                                       struct lmk_getkillcnt *params) {
    packet[0] = htonl(LMK_GETKILLCNT);
    packet[1] = htonl(params->min_oomadj);
    packet[2] = htonl(params->max_oomadj);
    return 3 * sizeof(int);
}

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

__END_DECLS

#endif /* _LMKD_H_ */
+102 −1
Original line number Diff line number Diff line
@@ -313,7 +313,20 @@ static struct proc *pidhash[PIDHASH_SZ];
#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))

#define ADJTOSLOT(adj) ((adj) + -OOM_SCORE_ADJ_MIN)
static struct adjslot_list procadjslot_list[ADJTOSLOT(OOM_SCORE_ADJ_MAX) + 1];
#define ADJTOSLOT_COUNT (ADJTOSLOT(OOM_SCORE_ADJ_MAX) + 1)
static struct adjslot_list procadjslot_list[ADJTOSLOT_COUNT];

#define MAX_DISTINCT_OOM_ADJ 32
#define KILLCNT_INVALID_IDX 0xFF
/*
 * Because killcnt array is sparse a two-level indirection is used
 * to keep the size small. killcnt_idx stores index of the element in
 * killcnt array. Index KILLCNT_INVALID_IDX indicates an unused slot.
 */
static uint8_t killcnt_idx[ADJTOSLOT_COUNT];
static uint16_t killcnt[MAX_DISTINCT_OOM_ADJ];
static int killcnt_free_idx = 0;
static uint32_t killcnt_total = 0;

/* PAGE_SIZE / 1024 */
static long page_k;
@@ -644,6 +657,67 @@ static void cmd_procpurge() {
    memset(&pidhash[0], 0, sizeof(pidhash));
}

static void inc_killcnt(int oomadj) {
    int slot = ADJTOSLOT(oomadj);
    uint8_t idx = killcnt_idx[slot];

    if (idx == KILLCNT_INVALID_IDX) {
        /* index is not assigned for this oomadj */
        if (killcnt_free_idx < MAX_DISTINCT_OOM_ADJ) {
            killcnt_idx[slot] = killcnt_free_idx;
            killcnt[killcnt_free_idx] = 1;
            killcnt_free_idx++;
        } else {
            ALOGW("Number of distinct oomadj levels exceeds %d",
                MAX_DISTINCT_OOM_ADJ);
        }
    } else {
        /*
         * wraparound is highly unlikely and is detectable using total
         * counter because it has to be equal to the sum of all counters
         */
        killcnt[idx]++;
    }
    /* increment total kill counter */
    killcnt_total++;
}

static int get_killcnt(int min_oomadj, int max_oomadj) {
    int slot;
    int count = 0;

    if (min_oomadj > max_oomadj)
        return 0;

    /* special case to get total kill count */
    if (min_oomadj > OOM_SCORE_ADJ_MAX)
        return killcnt_total;

    while (min_oomadj <= max_oomadj &&
           (slot = ADJTOSLOT(min_oomadj)) < ADJTOSLOT_COUNT) {
        uint8_t idx = killcnt_idx[slot];
        if (idx != KILLCNT_INVALID_IDX) {
            count += killcnt[idx];
        }
        min_oomadj++;
    }

    return count;
}

static int cmd_getkillcnt(LMKD_CTRL_PACKET packet) {
    struct lmk_getkillcnt params;

    if (use_inkernel_interface) {
        /* kernel driver does not expose this information */
        return 0;
    }

    lmkd_pack_get_getkillcnt(packet, &params);

    return get_killcnt(params.min_oomadj, params.max_oomadj);
}

static void cmd_target(int ntargets, LMKD_CTRL_PACKET packet) {
    int i;
    struct lmk_target target;
@@ -748,12 +822,28 @@ static int ctrl_data_read(int dsock_idx, char *buf, size_t bufsz) {
    return ret;
}

static int ctrl_data_write(int dsock_idx, char *buf, size_t bufsz) {
    int ret = 0;

    ret = TEMP_FAILURE_RETRY(write(data_sock[dsock_idx].sock, buf, bufsz));

    if (ret == -1) {
        ALOGE("control data socket write failed; errno=%d", errno);
    } else if (ret == 0) {
        ALOGE("Got EOF on control data socket");
        ret = -1;
    }

    return ret;
}

static void ctrl_command_handler(int dsock_idx) {
    LMKD_CTRL_PACKET packet;
    int len;
    enum lmk_cmd cmd;
    int nargs;
    int targets;
    int kill_cnt;

    len = ctrl_data_read(dsock_idx, (char *)packet, CTRL_PACKET_MAX_SIZE);
    if (len <= 0)
@@ -791,6 +881,14 @@ static void ctrl_command_handler(int dsock_idx) {
            goto wronglen;
        cmd_procpurge();
        break;
    case LMK_GETKILLCNT:
        if (nargs != 2)
            goto wronglen;
        kill_cnt = cmd_getkillcnt(packet);
        len = lmkd_pack_set_getkillcnt_repl(packet, kill_cnt);
        if (ctrl_data_write(dsock_idx, (char *)packet, len) != len)
            return;
        break;
    default:
        ALOGE("Received unknown command code %d", cmd);
        return;
@@ -1200,6 +1298,7 @@ static int kill_one_process(struct proc* procp) {

    /* CAP_KILL required */
    r = kill(pid, SIGKILL);
    inc_killcnt(procp->oomadj);
    ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB",
        taskname, pid, uid, procp->oomadj, tasksize * page_k);

@@ -1700,6 +1799,8 @@ static int init(void) {
        procadjslot_list[i].prev = &procadjslot_list[i];
    }

    memset(killcnt_idx, KILLCNT_INVALID_IDX, sizeof(killcnt_idx));

    return 0;
}