Merge "libprocessgroup: Remove SetClamps action" into main
diff --git a/fs_mgr/liblp/super_layout_builder.cpp b/fs_mgr/liblp/super_layout_builder.cpp
index fd7416b..bff26ea 100644
--- a/fs_mgr/liblp/super_layout_builder.cpp
+++ b/fs_mgr/liblp/super_layout_builder.cpp
@@ -184,7 +184,7 @@
return {};
}
- size_t size = e.num_sectors * LP_SECTOR_SIZE;
+ uint64_t size = e.num_sectors * LP_SECTOR_SIZE;
uint64_t super_offset = e.target_data * LP_SECTOR_SIZE;
extents.emplace_back(super_offset, size, image_name, image_offset);
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index ff03355..cc675b3 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -17,11 +17,16 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "libprocessgroup"
+#include <task_profiles.h>
+
+#include <map>
+#include <string>
+
#include <dirent.h>
#include <fcntl.h>
+#include <sched.h>
+#include <sys/resource.h>
#include <unistd.h>
-#include <task_profiles.h>
-#include <string>
#include <android-base/file.h>
#include <android-base/logging.h>
@@ -30,13 +35,13 @@
#include <android-base/strings.h>
#include <android-base/threads.h>
+#include <build_flags.h>
+
#include <cutils/android_filesystem_config.h>
#include <json/reader.h>
#include <json/value.h>
-#include <build_flags.h>
-
using android::base::GetThreadId;
using android::base::GetUintProperty;
using android::base::StringPrintf;
@@ -637,6 +642,57 @@
return access(task_path_.c_str(), W_OK) == 0;
}
+bool SetSchedulerPolicyAction::isNormalPolicy(int policy) {
+ return policy == SCHED_OTHER || policy == SCHED_BATCH || policy == SCHED_IDLE;
+}
+
+bool SetSchedulerPolicyAction::toPriority(int policy, int virtual_priority, int& priority_out) {
+ constexpr int VIRTUAL_PRIORITY_MIN = 1;
+ constexpr int VIRTUAL_PRIORITY_MAX = 99;
+
+ if (virtual_priority < VIRTUAL_PRIORITY_MIN || virtual_priority > VIRTUAL_PRIORITY_MAX) {
+ LOG(WARNING) << "SetSchedulerPolicy: invalid priority (" << virtual_priority
+ << ") for policy (" << policy << ")";
+ return false;
+ }
+
+ const int min = sched_get_priority_min(policy);
+ if (min == -1) {
+ PLOG(ERROR) << "SetSchedulerPolicy: Cannot get min sched priority for policy " << policy;
+ return false;
+ }
+
+ const int max = sched_get_priority_max(policy);
+ if (max == -1) {
+ PLOG(ERROR) << "SetSchedulerPolicy: Cannot get max sched priority for policy " << policy;
+ return false;
+ }
+
+ priority_out = min + (virtual_priority - VIRTUAL_PRIORITY_MIN) * (max - min) /
+ (VIRTUAL_PRIORITY_MAX - VIRTUAL_PRIORITY_MIN);
+
+ return true;
+}
+
+bool SetSchedulerPolicyAction::ExecuteForTask(pid_t tid) const {
+ struct sched_param param = {};
+ param.sched_priority = isNormalPolicy(policy_) ? 0 : *priority_or_nice_;
+ if (sched_setscheduler(tid, policy_, ¶m) == -1) {
+ PLOG(WARNING) << "SetSchedulerPolicy: Failed to apply scheduler policy (" << policy_
+ << ") with priority (" << *priority_or_nice_ << ") to tid " << tid;
+ return false;
+ }
+
+ if (isNormalPolicy(policy_) && priority_or_nice_ &&
+ setpriority(PRIO_PROCESS, tid, *priority_or_nice_) == -1) {
+ PLOG(WARNING) << "SetSchedulerPolicy: Failed to apply nice (" << *priority_or_nice_
+ << ") to tid " << tid;
+ return false;
+ }
+
+ return true;
+}
+
bool ApplyProfileAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
for (const auto& profile : profiles_) {
profile->ExecuteForProcess(uid, pid);
@@ -907,6 +963,62 @@
LOG(WARNING) << "WriteFile: invalid parameter: "
<< "empty value";
}
+ } else if (action_name == "SetSchedulerPolicy") {
+ const std::map<std::string, int> POLICY_MAP = {
+ {"SCHED_OTHER", SCHED_OTHER},
+ {"SCHED_BATCH", SCHED_BATCH},
+ {"SCHED_IDLE", SCHED_IDLE},
+ {"SCHED_FIFO", SCHED_FIFO},
+ {"SCHED_RR", SCHED_RR},
+ };
+ const std::string policy_str = params_val["Policy"].asString();
+
+ const auto it = POLICY_MAP.find(policy_str);
+ if (it == POLICY_MAP.end()) {
+ LOG(WARNING) << "SetSchedulerPolicy: invalid policy " << policy_str;
+ continue;
+ }
+
+ const int policy = it->second;
+
+ if (SetSchedulerPolicyAction::isNormalPolicy(policy)) {
+ if (params_val.isMember("Priority")) {
+ LOG(WARNING) << "SetSchedulerPolicy: Normal policies (" << policy_str
+ << ") use Nice values, not Priority values";
+ }
+
+ if (params_val.isMember("Nice")) {
+ // If present, this optional value will be passed in an additional syscall
+ // to setpriority(), since the sched_priority value must be 0 for calls to
+ // sched_setscheduler() with "normal" policies.
+ const int nice = params_val["Nice"].asInt();
+
+ const int LINUX_MIN_NICE = -20;
+ const int LINUX_MAX_NICE = 19;
+ if (nice < LINUX_MIN_NICE || nice > LINUX_MAX_NICE) {
+ LOG(WARNING) << "SetSchedulerPolicy: Provided nice (" << nice
+ << ") appears out of range.";
+ }
+ profile->Add(std::make_unique<SetSchedulerPolicyAction>(policy, nice));
+ } else {
+ profile->Add(std::make_unique<SetSchedulerPolicyAction>(policy));
+ }
+ } else {
+ if (params_val.isMember("Nice")) {
+ LOG(WARNING) << "SetSchedulerPolicy: Real-time policies (" << policy_str
+ << ") use Priority values, not Nice values";
+ }
+
+ // This is a "virtual priority" as described by `man 2 sched_get_priority_min`
+ // that will be mapped onto the following range for the provided policy:
+ // [sched_get_priority_min(), sched_get_priority_max()]
+ const int virtual_priority = params_val["Priority"].asInt();
+
+ int priority;
+ if (SetSchedulerPolicyAction::toPriority(policy, virtual_priority, priority)) {
+ profile->Add(std::make_unique<SetSchedulerPolicyAction>(policy, priority));
+ }
+ }
} else {
LOG(WARNING) << "Unknown profile action: " << action_name;
}
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 782b3ff..d0b5043 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -21,6 +21,7 @@
#include <map>
#include <memory>
#include <mutex>
+#include <optional>
#include <span>
#include <string>
#include <string_view>
@@ -174,6 +175,25 @@
CacheUseResult UseCachedFd(ResourceCacheType cache_type, const std::string& value) const;
};
+// Set scheduler policy action
+class SetSchedulerPolicyAction : public ProfileAction {
+ public:
+ SetSchedulerPolicyAction(int policy)
+ : policy_(policy) {}
+ SetSchedulerPolicyAction(int policy, int priority_or_nice)
+ : policy_(policy), priority_or_nice_(priority_or_nice) {}
+
+ const char* Name() const override { return "SetSchedulerPolicy"; }
+ bool ExecuteForTask(pid_t tid) const override;
+
+ static bool isNormalPolicy(int policy);
+ static bool toPriority(int policy, int virtual_priority, int& priority_out);
+
+ private:
+ int policy_;
+ std::optional<int> priority_or_nice_;
+};
+
class TaskProfile {
public:
TaskProfile(const std::string& name) : name_(name), res_cached_(false) {}