123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include <processgroup/sched_policy.h>
- #define LOG_TAG "SchedPolicy"
- #include <errno.h>
- #include <unistd.h>
- #include <android-base/logging.h>
- #include <android-base/threads.h>
- #include <cgroup_map.h>
- #include <processgroup/processgroup.h>
- using android::base::GetThreadId;
- /* Re-map SP_DEFAULT to the system default policy, and leave other values unchanged.
- * Call this any place a SchedPolicy is used as an input parameter.
- * Returns the possibly re-mapped policy.
- */
- static inline SchedPolicy _policy(SchedPolicy p) {
- return p == SP_DEFAULT ? SP_SYSTEM_DEFAULT : p;
- }
- #if defined(__ANDROID__)
- int set_cpuset_policy(int tid, SchedPolicy policy) {
- if (tid == 0) {
- tid = GetThreadId();
- }
- policy = _policy(policy);
- switch (policy) {
- case SP_BACKGROUND:
- return SetTaskProfiles(tid,
- {"HighEnergySaving", "ProcessCapacityLow", "LowIoPriority",
- "TimerSlackHigh"},
- true)
- ? 0
- : -1;
- case SP_FOREGROUND:
- case SP_AUDIO_APP:
- case SP_AUDIO_SYS:
- return SetTaskProfiles(tid,
- {"HighPerformance", "ProcessCapacityHigh", "HighIoPriority",
- "TimerSlackNormal"},
- true)
- ? 0
- : -1;
- case SP_TOP_APP:
- return SetTaskProfiles(tid,
- {"MaxPerformance", "ProcessCapacityMax", "MaxIoPriority",
- "TimerSlackNormal"},
- true)
- ? 0
- : -1;
- case SP_SYSTEM:
- return SetTaskProfiles(tid, {"ServiceCapacityLow", "TimerSlackNormal"}, true) ? 0 : -1;
- case SP_RESTRICTED:
- return SetTaskProfiles(tid, {"ServiceCapacityRestricted", "TimerSlackNormal"}, true)
- ? 0
- : -1;
- default:
- break;
- }
- return 0;
- }
- int set_sched_policy(int tid, SchedPolicy policy) {
- if (tid == 0) {
- tid = GetThreadId();
- }
- policy = _policy(policy);
- #if POLICY_DEBUG
- char statfile[64];
- char statline[1024];
- char thread_name[255];
- snprintf(statfile, sizeof(statfile), "/proc/%d/stat", tid);
- memset(thread_name, 0, sizeof(thread_name));
- unique_fd fd(TEMP_FAILURE_RETRY(open(statfile, O_RDONLY | O_CLOEXEC)));
- if (fd >= 0) {
- int rc = read(fd, statline, 1023);
- statline[rc] = 0;
- char* p = statline;
- char* q;
- for (p = statline; *p != '('; p++)
- ;
- p++;
- for (q = p; *q != ')'; q++)
- ;
- strncpy(thread_name, p, (q - p));
- }
- switch (policy) {
- case SP_BACKGROUND:
- SLOGD("vvv tid %d (%s)", tid, thread_name);
- break;
- case SP_FOREGROUND:
- case SP_AUDIO_APP:
- case SP_AUDIO_SYS:
- case SP_TOP_APP:
- SLOGD("^^^ tid %d (%s)", tid, thread_name);
- break;
- case SP_SYSTEM:
- SLOGD("/// tid %d (%s)", tid, thread_name);
- break;
- case SP_RT_APP:
- SLOGD("RT tid %d (%s)", tid, thread_name);
- break;
- default:
- SLOGD("??? tid %d (%s)", tid, thread_name);
- break;
- }
- #endif
- switch (policy) {
- case SP_BACKGROUND:
- return SetTaskProfiles(tid, {"HighEnergySaving", "TimerSlackHigh"}, true) ? 0 : -1;
- case SP_FOREGROUND:
- case SP_AUDIO_APP:
- case SP_AUDIO_SYS:
- return SetTaskProfiles(tid, {"HighPerformance", "TimerSlackNormal"}, true) ? 0 : -1;
- case SP_TOP_APP:
- return SetTaskProfiles(tid, {"MaxPerformance", "TimerSlackNormal"}, true) ? 0 : -1;
- case SP_RT_APP:
- return SetTaskProfiles(tid, {"RealtimePerformance", "TimerSlackNormal"}, true) ? 0 : -1;
- default:
- return SetTaskProfiles(tid, {"TimerSlackNormal"}, true) ? 0 : -1;
- }
- return 0;
- }
- bool cpusets_enabled() {
- static bool enabled = (CgroupMap::GetInstance().FindController("cpuset").IsUsable());
- return enabled;
- }
- bool schedboost_enabled() {
- static bool enabled = (CgroupMap::GetInstance().FindController("schedtune").IsUsable());
- return enabled;
- }
- static int getCGroupSubsys(int tid, const char* subsys, std::string& subgroup) {
- auto controller = CgroupMap::GetInstance().FindController(subsys);
- if (!controller.IsUsable()) return -1;
- if (!controller.GetTaskGroup(tid, &subgroup)) {
- LOG(ERROR) << "Failed to find cgroup for tid " << tid;
- return -1;
- }
- return 0;
- }
- int get_sched_policy(int tid, SchedPolicy* policy) {
- if (tid == 0) {
- tid = GetThreadId();
- }
- std::string group;
- if (schedboost_enabled()) {
- if (getCGroupSubsys(tid, "schedtune", group) < 0) return -1;
- }
- if (group.empty() && cpusets_enabled()) {
- if (getCGroupSubsys(tid, "cpuset", group) < 0) return -1;
- }
- // TODO: replace hardcoded directories
- if (group.empty()) {
- *policy = SP_FOREGROUND;
- } else if (group == "foreground") {
- *policy = SP_FOREGROUND;
- } else if (group == "system-background") {
- *policy = SP_SYSTEM;
- } else if (group == "background") {
- *policy = SP_BACKGROUND;
- } else if (group == "top-app") {
- *policy = SP_TOP_APP;
- } else if (group == "restricted") {
- *policy = SP_RESTRICTED;
- } else {
- errno = ERANGE;
- return -1;
- }
- return 0;
- }
- #else
- /* Stubs for non-Android targets. */
- int set_sched_policy(int, SchedPolicy) {
- return 0;
- }
- int get_sched_policy(int, SchedPolicy* policy) {
- *policy = SP_SYSTEM_DEFAULT;
- return 0;
- }
- #endif
- const char* get_sched_policy_name(SchedPolicy policy) {
- policy = _policy(policy);
- static const char* const kSchedPolicyNames[] = {
- [SP_BACKGROUND] = "bg", [SP_FOREGROUND] = "fg", [SP_SYSTEM] = " ",
- [SP_AUDIO_APP] = "aa", [SP_AUDIO_SYS] = "as", [SP_TOP_APP] = "ta",
- [SP_RT_APP] = "rt", [SP_RESTRICTED] = "rs",
- };
- static_assert(arraysize(kSchedPolicyNames) == SP_CNT, "missing name");
- if (policy < SP_BACKGROUND || policy >= SP_CNT) {
- return "error";
- }
- return kSchedPolicyNames[policy];
- }
|