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

Commit d4852269 authored by Robert Benea's avatar Robert Benea
Browse files

Add memcg related configs to init.

Allow configuring memory.swappiness, memory.soft_limit_in_bytes
and memory.limit_in_bytes by init; by doing so there is better
control of memory consumption per native app.

Test: tested on gobo branch.
bug: 63765067
Change-Id: I8906f3ff5ef77f75a0f4cdfbf9d424a579ed52bb
parent d1c73b57
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -260,6 +260,18 @@ runs the service.
> Sets the child's /proc/self/oom\_score\_adj to the specified value,
  which must range from -1000 to 1000.

`memcg.swappiness <value>`
> Sets the child's memory.swappiness to the specified value (only if memcg is mounted),
  which must be equal or greater than 0.

`memcg.soft_limit_in_bytes <value>`
> Sets the child's memory.soft_limit_in_bytes to the specified value (only if memcg is mounted),
  which must be equal or greater than 0.

`memcg.limit_in_bytes <value>`
> Sets the child's memory.limit_in_bytes to the specified value (only if memcg is mounted),
  which must be equal or greater than 0.

`shutdown <shutdown_behavior>`
> Set shutdown behavior of the service process. When this is not specified,
  the service is killed during shutdown process by using SIGTERM and SIGKILL.
+54 −0
Original line number Diff line number Diff line
@@ -171,6 +171,9 @@ Service::Service(const std::string& name, const std::vector<std::string>& args)
      ioprio_pri_(0),
      priority_(0),
      oom_score_adjust_(-1000),
      swappiness_(-1),
      soft_limit_in_bytes_(-1),
      limit_in_bytes_(-1),
      args_(args) {
    onrestart_.InitSingleTrigger("onrestart");
}
@@ -196,6 +199,9 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
      ioprio_pri_(0),
      priority_(0),
      oom_score_adjust_(-1000),
      swappiness_(-1),
      soft_limit_in_bytes_(-1),
      limit_in_bytes_(-1),
      args_(args) {
    onrestart_.InitSingleTrigger("onrestart");
}
@@ -491,6 +497,30 @@ bool Service::ParseOomScoreAdjust(const std::vector<std::string>& args, std::str
    return true;
}

bool Service::ParseMemcgSwappiness(const std::vector<std::string>& args, std::string* err) {
    if (!ParseInt(args[1], &swappiness_, 0)) {
        *err = "swappiness value must be equal or greater than 0";
        return false;
    }
    return true;
}

bool Service::ParseMemcgLimitInBytes(const std::vector<std::string>& args, std::string* err) {
    if (!ParseInt(args[1], &limit_in_bytes_, 0)) {
        *err = "limit_in_bytes value must be equal or greater than 0";
        return false;
    }
    return true;
}

bool Service::ParseMemcgSoftLimitInBytes(const std::vector<std::string>& args, std::string* err) {
    if (!ParseInt(args[1], &soft_limit_in_bytes_, 0)) {
        *err = "soft_limit_in_bytes value must be equal or greater than 0";
        return false;
    }
    return true;
}

bool Service::ParseSeclabel(const std::vector<std::string>& args, std::string* err) {
    seclabel_ = args[1];
    return true;
@@ -609,6 +639,12 @@ const Service::OptionParserMap::Map& Service::OptionParserMap::map() const {
        {"onrestart",   {1,     kMax, &Service::ParseOnrestart}},
        {"oom_score_adjust",
                        {1,     1,    &Service::ParseOomScoreAdjust}},
        {"memcg.swappiness",
                        {1,     1,    &Service::ParseMemcgSwappiness}},
        {"memcg.soft_limit_in_bytes",
                        {1,     1,    &Service::ParseMemcgSoftLimitInBytes}},
        {"memcg.limit_in_bytes",
                        {1,     1,    &Service::ParseMemcgLimitInBytes}},
        {"namespace",   {1,     2,    &Service::ParseNamespace}},
        {"seclabel",    {1,     1,    &Service::ParseSeclabel}},
        {"setenv",      {2,     2,    &Service::ParseSetenv}},
@@ -795,6 +831,24 @@ bool Service::Start() {
    if (errno != 0) {
        PLOG(ERROR) << "createProcessGroup(" << uid_ << ", " << pid_ << ") failed for service '"
                    << name_ << "'";
    } else {
        if (swappiness_ != -1) {
            if (!setProcessGroupSwappiness(uid_, pid_, swappiness_)) {
                PLOG(ERROR) << "setProcessGroupSwappiness failed";
            }
        }

        if (soft_limit_in_bytes_ != -1) {
            if (!setProcessGroupSoftLimit(uid_, pid_, soft_limit_in_bytes_)) {
                PLOG(ERROR) << "setProcessGroupSoftLimit failed";
            }
        }

        if (limit_in_bytes_ != -1) {
            if (!setProcessGroupLimit(uid_, pid_, limit_in_bytes_)) {
                PLOG(ERROR) << "setProcessGroupLimit failed";
            }
        }
    }

    if ((flags_ & SVC_EXEC) != 0) {
+7 −0
Original line number Diff line number Diff line
@@ -134,6 +134,9 @@ class Service {
    bool ParseOneshot(const std::vector<std::string>& args, std::string* err);
    bool ParseOnrestart(const std::vector<std::string>& args, std::string* err);
    bool ParseOomScoreAdjust(const std::vector<std::string>& args, std::string* err);
    bool ParseMemcgLimitInBytes(const std::vector<std::string>& args, std::string* err);
    bool ParseMemcgSoftLimitInBytes(const std::vector<std::string>& args, std::string* err);
    bool ParseMemcgSwappiness(const std::vector<std::string>& args, std::string* err);
    bool ParseNamespace(const std::vector<std::string>& args, std::string* err);
    bool ParseSeclabel(const std::vector<std::string>& args, std::string* err);
    bool ParseSetenv(const std::vector<std::string>& args, std::string* err);
@@ -181,6 +184,10 @@ class Service {

    int oom_score_adjust_;

    int swappiness_;
    int soft_limit_in_bytes_;
    int limit_in_bytes_;

    bool process_cgroup_empty_ = false;

    std::vector<std::string> args_;
+4 −0
Original line number Diff line number Diff line
@@ -33,6 +33,10 @@ int killProcessGroupOnce(uid_t uid, int initialPid, int signal);

int createProcessGroup(uid_t uid, int initialPid);

bool setProcessGroupSwappiness(uid_t uid, int initialPid, int swappiness);
bool setProcessGroupSoftLimit(uid_t uid, int initialPid, int64_t softLimitInBytes);
bool setProcessGroupLimit(uid_t uid, int initialPid, int64_t limitInBytes);

void removeAllProcessGroups(void);

__END_DECLS
+34 −13
Original line number Diff line number Diff line
@@ -35,12 +35,15 @@
#include <set>
#include <thread>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <private/android_filesystem_config.h>

#include <processgroup/processgroup.h>

using android::base::WriteStringToFile;

using namespace std::chrono_literals;

#define MEM_CGROUP_PATH "/dev/memcg/apps"
@@ -402,22 +405,40 @@ int createProcessGroup(uid_t uid, int initialPid)

    strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path));

    int fd = open(path, O_WRONLY);
    if (fd == -1) {
        int ret = -errno;
        PLOG(ERROR) << "Failed to open " << path;
    int ret = 0;
    if (!WriteStringToFile(std::to_string(initialPid), path)) {
        ret = -errno;
        PLOG(ERROR) << "Failed to write '" << initialPid << "' to " << path;
    }

    return ret;
}

    char pid[PROCESSGROUP_MAX_PID_LEN + 1] = {0};
    int len = snprintf(pid, sizeof(pid), "%d", initialPid);
static bool setProcessGroupValue(uid_t uid, int pid, const char* fileName, int64_t value) {
    char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
    if (strcmp(getCgroupRootPath(), MEM_CGROUP_PATH)) {
        PLOG(ERROR) << "Memcg is not mounted." << path;
        return false;
    }

    int ret = 0;
    if (write(fd, pid, len) < 0) {
        ret = -errno;
        PLOG(ERROR) << "Failed to write '" << pid << "' to " << path;
    convertUidPidToPath(path, sizeof(path), uid, pid);
    strlcat(path, fileName, sizeof(path));

    if (!WriteStringToFile(std::to_string(value), path)) {
        PLOG(ERROR) << "Failed to write '" << value << "' to " << path;
        return false;
    }
    return true;
}

    close(fd);
    return ret;
bool setProcessGroupSwappiness(uid_t uid, int pid, int swappiness) {
    return setProcessGroupValue(uid, pid, "/memory.swappiness", swappiness);
}

bool setProcessGroupSoftLimit(uid_t uid, int pid, int64_t soft_limit_in_bytes) {
    return setProcessGroupValue(uid, pid, "/memory.soft_limit_in_bytes", soft_limit_in_bytes);
}

bool setProcessGroupLimit(uid_t uid, int pid, int64_t limit_in_bytes) {
    return setProcessGroupValue(uid, pid, "/memory.limit_in_bytes", limit_in_bytes);
}