Merge "system/core: use proper nativehelper headers"
diff --git a/init/Android.mk b/init/Android.mk
index 6cd47f4..325614e 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -30,6 +30,10 @@
init_options += -DLOG_UEVENTS=0
+ifeq ($(TARGET_USER_MODE_LINUX), true)
+ init_cflags += -DUSER_MODE_LINUX
+endif
+
init_cflags += \
$(init_options) \
-Wall -Wextra \
diff --git a/init/README.md b/init/README.md
index 422fdad..f3b57bc 100644
--- a/init/README.md
+++ b/init/README.md
@@ -260,6 +260,18 @@
> 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.
diff --git a/init/init.cpp b/init/init.cpp
index bf251ff..b0b2e49 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -391,7 +391,10 @@
int ret = -1;
/* values are arch-dependent */
-#if defined(__aarch64__)
+#if defined(USER_MODE_LINUX)
+ /* uml does not support mmap_rnd_bits */
+ ret = 0;
+#elif defined(__aarch64__)
/* arm64 supports 18 - 33 bits depending on pagesize and VA_SIZE */
if (set_mmap_rnd_bits_min(33, 24, false)
&& set_mmap_rnd_bits_min(16, 16, true)) {
diff --git a/init/service.cpp b/init/service.cpp
index 7a657c8..82dd9b1 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -171,6 +171,9 @@
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 @@
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 @@
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 @@
{"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 @@
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) {
diff --git a/init/service.h b/init/service.h
index f682abd..62a3299 100644
--- a/init/service.h
+++ b/init/service.h
@@ -134,6 +134,9 @@
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 @@
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_;
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
index f0c3795..9fa4154 100644
--- a/libprocessgroup/include/processgroup/processgroup.h
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -33,6 +33,10 @@
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
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 9b8248e..8526b3a 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -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 @@
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;
- return ret;
- }
-
- char pid[PROCESSGROUP_MAX_PID_LEN + 1] = {0};
- int len = snprintf(pid, sizeof(pid), "%d", initialPid);
-
int ret = 0;
- if (write(fd, pid, len) < 0) {
+ if (!WriteStringToFile(std::to_string(initialPid), path)) {
ret = -errno;
- PLOG(ERROR) << "Failed to write '" << pid << "' to " << path;
+ PLOG(ERROR) << "Failed to write '" << initialPid << "' to " << path;
}
- close(fd);
return ret;
}
+
+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;
+ }
+
+ 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;
+}
+
+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);
+}