Merge "libprocessgroup: Add SetSchedulerPolicy Action" into main
This commit is contained in:
commit
5424402b13
2 changed files with 136 additions and 4 deletions
|
|
@ -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;
|
||||
|
|
@ -649,6 +654,57 @@ bool WriteFileAction::IsValidForTask(int) const {
|
|||
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);
|
||||
|
|
@ -936,6 +992,62 @@ bool TaskProfiles::Load(const CgroupMap& cg_map, const std::string& file_name) {
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
|
@ -187,6 +188,25 @@ class WriteFileAction : public ProfileAction {
|
|||
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) {}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue