blob: 4c8aa6dd7586a3daea6f8c6c102d5bd3c6bde160 [file] [log] [blame]
Mark Salyzyn12717162014-04-29 15:49:14 -07001/*
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -08002 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
San Mehat493dad92009-09-12 10:06:57 -070016
Suren Baghdasaryan1bd127b2019-01-25 05:30:52 +000017#include <processgroup/sched_policy.h>
Elliott Hughes8e9aeb92017-11-10 10:22:07 -080018
Jeff Brownbff8f3f2012-05-08 15:05:42 -070019#define LOG_TAG "SchedPolicy"
20
San Mehat493dad92009-09-12 10:06:57 -070021#include <errno.h>
Mark Salyzyn12717162014-04-29 15:49:14 -070022#include <unistd.h>
23
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -080024#include <android-base/logging.h>
25#include <android-base/threads.h>
26#include <cgroup_map.h>
27#include <processgroup/processgroup.h>
28
29using android::base::GetThreadId;
Mark Salyzyn12717162014-04-29 15:49:14 -070030
Jeff Brownbff8f3f2012-05-08 15:05:42 -070031/* Re-map SP_DEFAULT to the system default policy, and leave other values unchanged.
32 * Call this any place a SchedPolicy is used as an input parameter.
33 * Returns the possibly re-mapped policy.
34 */
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -080035static inline SchedPolicy _policy(SchedPolicy p) {
36 return p == SP_DEFAULT ? SP_SYSTEM_DEFAULT : p;
Jeff Brownbff8f3f2012-05-08 15:05:42 -070037}
San Mehatd2e4e462009-10-29 11:48:00 -070038
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -080039int set_cpuset_policy(int tid, SchedPolicy policy) {
Glenn Kasten69bfb1f2012-03-16 09:43:19 -070040 if (tid == 0) {
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -080041 tid = GetThreadId();
Tim Murrayb769c8d2015-06-08 14:56:29 -070042 }
43 policy = _policy(policy);
Tim Murrayb769c8d2015-06-08 14:56:29 -070044
Tim Murrayb769c8d2015-06-08 14:56:29 -070045 switch (policy) {
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -080046 case SP_BACKGROUND:
47 return SetTaskProfiles(tid,
48 {"HighEnergySaving", "ProcessCapacityLow", "TimerSlackHigh"})
49 ? 0
50 : -1;
51 case SP_FOREGROUND:
52 case SP_AUDIO_APP:
53 case SP_AUDIO_SYS:
54 return SetTaskProfiles(tid,
55 {"HighPerformance", "ProcessCapacityHigh", "TimerSlackNormal"})
56 ? 0
57 : -1;
58 case SP_TOP_APP:
59 return SetTaskProfiles(tid,
60 {"MaxPerformance", "ProcessCapacityMax", "TimerSlackNormal"})
61 ? 0
62 : -1;
63 case SP_SYSTEM:
64 return SetTaskProfiles(tid, {"ServiceCapacityLow", "TimerSlackNormal"}) ? 0 : -1;
65 case SP_RESTRICTED:
66 return SetTaskProfiles(tid, {"ServiceCapacityRestricted", "TimerSlackNormal"}) ? 0 : -1;
67 default:
68 break;
Todd Kjosba8a4752015-10-26 16:22:11 -070069 }
70
Tim Murray99910262015-06-22 14:00:56 -070071 return 0;
Tim Murrayb769c8d2015-06-08 14:56:29 -070072}
73
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -080074int set_sched_policy(int tid, SchedPolicy policy) {
Glenn Kasten69bfb1f2012-03-16 09:43:19 -070075 if (tid == 0) {
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -080076 tid = GetThreadId();
Glenn Kasten69bfb1f2012-03-16 09:43:19 -070077 }
Glenn Kasten69bfb1f2012-03-16 09:43:19 -070078 policy = _policy(policy);
San Mehat493dad92009-09-12 10:06:57 -070079
San Mehatd2e4e462009-10-29 11:48:00 -070080#if POLICY_DEBUG
81 char statfile[64];
82 char statline[1024];
83 char thread_name[255];
San Mehatd2e4e462009-10-29 11:48:00 -070084
Raja Ma2f37e42016-04-19 23:55:14 +053085 snprintf(statfile, sizeof(statfile), "/proc/%d/stat", tid);
San Mehatd2e4e462009-10-29 11:48:00 -070086 memset(thread_name, 0, sizeof(thread_name));
87
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -080088 unique_fd fd(TEMP_FAILURE_RETRY(open(statfile, O_RDONLY | O_CLOEXEC)));
San Mehatd2e4e462009-10-29 11:48:00 -070089 if (fd >= 0) {
90 int rc = read(fd, statline, 1023);
San Mehatd2e4e462009-10-29 11:48:00 -070091 statline[rc] = 0;
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -080092 char* p = statline;
93 char* q;
San Mehatd2e4e462009-10-29 11:48:00 -070094
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -080095 for (p = statline; *p != '('; p++)
96 ;
San Mehatd2e4e462009-10-29 11:48:00 -070097 p++;
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -080098 for (q = p; *q != ')'; q++)
99 ;
San Mehatd2e4e462009-10-29 11:48:00 -0700100
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -0800101 strncpy(thread_name, p, (q - p));
San Mehatd2e4e462009-10-29 11:48:00 -0700102 }
Glenn Kasten10ec3c72012-04-19 15:25:58 -0700103 switch (policy) {
Tim Murrayb769c8d2015-06-08 14:56:29 -0700104 case SP_BACKGROUND:
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -0800105 SLOGD("vvv tid %d (%s)", tid, thread_name);
Tim Murrayb769c8d2015-06-08 14:56:29 -0700106 break;
107 case SP_FOREGROUND:
108 case SP_AUDIO_APP:
109 case SP_AUDIO_SYS:
Tim Murray6647bb52016-01-11 16:16:35 -0800110 case SP_TOP_APP:
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -0800111 SLOGD("^^^ tid %d (%s)", tid, thread_name);
112 break;
113 case SP_SYSTEM:
114 SLOGD("/// tid %d (%s)", tid, thread_name);
Tim Murrayb769c8d2015-06-08 14:56:29 -0700115 break;
Joel Fernandes88ef9f02017-03-25 22:46:10 -0700116 case SP_RT_APP:
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -0800117 SLOGD("RT tid %d (%s)", tid, thread_name);
Tim Murrayb769c8d2015-06-08 14:56:29 -0700118 break;
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -0800119 default:
120 SLOGD("??? tid %d (%s)", tid, thread_name);
121 break;
122 }
123#endif
Tim Murrayb769c8d2015-06-08 14:56:29 -0700124
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -0800125 switch (policy) {
126 case SP_BACKGROUND:
127 return SetTaskProfiles(tid, {"HighEnergySaving", "TimerSlackHigh"}) ? 0 : -1;
128 case SP_FOREGROUND:
129 case SP_AUDIO_APP:
130 case SP_AUDIO_SYS:
131 return SetTaskProfiles(tid, {"HighPerformance", "TimerSlackNormal"}) ? 0 : -1;
132 case SP_TOP_APP:
133 return SetTaskProfiles(tid, {"MaxPerformance", "TimerSlackNormal"}) ? 0 : -1;
134 case SP_RT_APP:
135 return SetTaskProfiles(tid, {"RealtimePerformance", "TimerSlackNormal"}) ? 0 : -1;
136 default:
137 return SetTaskProfiles(tid, {"TimerSlackNormal"}) ? 0 : -1;
San Mehat493dad92009-09-12 10:06:57 -0700138 }
139
140 return 0;
141}
Raphael0384a982009-09-15 17:10:17 -0700142
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -0800143bool cpusets_enabled() {
144 static bool enabled = (CgroupMap::GetInstance().FindController("cpuset") != nullptr);
145 return enabled;
146}
Jeff Brownbff8f3f2012-05-08 15:05:42 -0700147
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -0800148bool schedboost_enabled() {
149 static bool enabled = (CgroupMap::GetInstance().FindController("schedtune") != nullptr);
150 return enabled;
151}
Jeff Brownbff8f3f2012-05-08 15:05:42 -0700152
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -0800153static int getCGroupSubsys(int tid, const char* subsys, std::string& subgroup) {
154 const CgroupController* controller = CgroupMap::GetInstance().FindController(subsys);
155
156 if (!controller) return -1;
157
158 if (!controller->GetTaskGroup(tid, &subgroup)) {
159 PLOG(ERROR) << "Failed to find cgroup for tid " << tid;
160 return -1;
161 }
Jeff Brownbff8f3f2012-05-08 15:05:42 -0700162 return 0;
163}
164
Suren Baghdasaryan82b72a52018-12-21 11:41:50 -0800165int get_sched_policy(int tid, SchedPolicy* policy) {
166 if (tid == 0) {
167 tid = GetThreadId();
168 }
169
170 std::string group;
171 if (schedboost_enabled()) {
172 if (getCGroupSubsys(tid, "schedtune", group) < 0) return -1;
173 }
174 if (group.empty() && cpusets_enabled()) {
175 if (getCGroupSubsys(tid, "cpuset", group) < 0) return -1;
176 }
177
178 // TODO: replace hardcoded directories
179 if (group.empty()) {
180 *policy = SP_FOREGROUND;
181 } else if (group == "foreground") {
182 *policy = SP_FOREGROUND;
183 } else if (group == "system-background") {
184 *policy = SP_SYSTEM;
185 } else if (group == "background") {
186 *policy = SP_BACKGROUND;
187 } else if (group == "top-app") {
188 *policy = SP_TOP_APP;
189 } else if (group == "restricted") {
190 *policy = SP_RESTRICTED;
191 } else {
192 errno = ERANGE;
193 return -1;
194 }
Jeff Brownbff8f3f2012-05-08 15:05:42 -0700195 return 0;
196}
197
Elliott Hughes9f495082018-04-25 14:52:50 -0700198const char* get_sched_policy_name(SchedPolicy policy) {
Glenn Kasten69bfb1f2012-03-16 09:43:19 -0700199 policy = _policy(policy);
Elliott Hughes9f495082018-04-25 14:52:50 -0700200 static const char* const kSchedPolicyNames[] = {
Tim Murray419ba9e2018-04-13 10:15:49 -0700201 [SP_BACKGROUND] = "bg", [SP_FOREGROUND] = "fg", [SP_SYSTEM] = " ",
202 [SP_AUDIO_APP] = "aa", [SP_AUDIO_SYS] = "as", [SP_TOP_APP] = "ta",
203 [SP_RT_APP] = "rt", [SP_RESTRICTED] = "rs",
Glenn Kasten86c7cc82012-03-05 16:14:39 -0800204 };
Elliott Hughes9f495082018-04-25 14:52:50 -0700205 static_assert(arraysize(kSchedPolicyNames) == SP_CNT, "missing name");
206 if (policy < SP_BACKGROUND || policy >= SP_CNT) {
Glenn Kasten86c7cc82012-03-05 16:14:39 -0800207 return "error";
Elliott Hughes9f495082018-04-25 14:52:50 -0700208 }
209 return kSchedPolicyNames[policy];
Glenn Kasten86c7cc82012-03-05 16:14:39 -0800210}