1 /* 2 * 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 */ 16 17 #pragma once 18 19 #include <sys/cdefs.h> 20 #include <sys/types.h> 21 #include <map> 22 #include <mutex> 23 #include <string> 24 #include <vector> 25 26 #include <android-base/unique_fd.h> 27 #include <cgroup_map.h> 28 29 class ProfileAttribute { 30 public: ProfileAttribute(const CgroupController & controller,const std::string & file_name)31 ProfileAttribute(const CgroupController& controller, const std::string& file_name) 32 : controller_(controller), file_name_(file_name) {} 33 controller()34 const CgroupController* controller() const { return &controller_; } file_name()35 const std::string& file_name() const { return file_name_; } 36 void Reset(const CgroupController& controller, const std::string& file_name); 37 38 bool GetPathForTask(int tid, std::string* path) const; 39 40 private: 41 CgroupController controller_; 42 std::string file_name_; 43 }; 44 45 // Abstract profile element 46 class ProfileAction { 47 public: ~ProfileAction()48 virtual ~ProfileAction() {} 49 50 // Default implementations will fail ExecuteForProcess(uid_t,pid_t)51 virtual bool ExecuteForProcess(uid_t, pid_t) const { return false; }; ExecuteForTask(int)52 virtual bool ExecuteForTask(int) const { return false; }; 53 EnableResourceCaching()54 virtual void EnableResourceCaching() {} DropResourceCaching()55 virtual void DropResourceCaching() {} 56 }; 57 58 // Profile actions 59 class SetClampsAction : public ProfileAction { 60 public: SetClampsAction(int boost,int clamp)61 SetClampsAction(int boost, int clamp) noexcept : boost_(boost), clamp_(clamp) {} 62 63 virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; 64 virtual bool ExecuteForTask(int tid) const; 65 66 protected: 67 int boost_; 68 int clamp_; 69 }; 70 71 // To avoid issues in sdk_mac build 72 #if defined(__ANDROID__) 73 74 class SetTimerSlackAction : public ProfileAction { 75 public: SetTimerSlackAction(unsigned long slack)76 SetTimerSlackAction(unsigned long slack) noexcept : slack_(slack) {} 77 78 virtual bool ExecuteForTask(int tid) const; 79 80 private: 81 unsigned long slack_; 82 83 static bool IsTimerSlackSupported(int tid); 84 }; 85 86 #else 87 88 class SetTimerSlackAction : public ProfileAction { 89 public: SetTimerSlackAction(unsigned long)90 SetTimerSlackAction(unsigned long) noexcept {} 91 ExecuteForTask(int)92 virtual bool ExecuteForTask(int) const { return true; } 93 }; 94 95 #endif 96 97 // Set attribute profile element 98 class SetAttributeAction : public ProfileAction { 99 public: SetAttributeAction(const ProfileAttribute * attribute,const std::string & value)100 SetAttributeAction(const ProfileAttribute* attribute, const std::string& value) 101 : attribute_(attribute), value_(value) {} 102 103 virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; 104 virtual bool ExecuteForTask(int tid) const; 105 106 private: 107 const ProfileAttribute* attribute_; 108 std::string value_; 109 }; 110 111 // Abstract profile element for cached fd 112 class CachedFdProfileAction : public ProfileAction { 113 public: 114 virtual void EnableResourceCaching(); 115 virtual void DropResourceCaching(); 116 117 protected: 118 enum FdState { 119 FDS_INACCESSIBLE = -1, 120 FDS_APP_DEPENDENT = -2, 121 FDS_NOT_CACHED = -3, 122 }; 123 124 android::base::unique_fd fd_; 125 mutable std::mutex fd_mutex_; 126 127 static bool IsAppDependentPath(const std::string& path); 128 129 void InitFd(const std::string& path); IsFdValid()130 bool IsFdValid() const { return fd_ > FDS_INACCESSIBLE; } 131 132 virtual const std::string GetPath() const = 0; 133 }; 134 135 // Set cgroup profile element 136 class SetCgroupAction : public CachedFdProfileAction { 137 public: 138 SetCgroupAction(const CgroupController& c, const std::string& p); 139 140 virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; 141 virtual bool ExecuteForTask(int tid) const; 142 controller()143 const CgroupController* controller() const { return &controller_; } 144 145 protected: GetPath()146 const std::string GetPath() const override { return controller_.GetTasksFilePath(path_); } 147 148 private: 149 CgroupController controller_; 150 std::string path_; 151 152 static bool AddTidToCgroup(int tid, int fd, const char* controller_name); 153 }; 154 155 // Write to file action 156 class WriteFileAction : public CachedFdProfileAction { 157 public: 158 WriteFileAction(const std::string& path, const std::string& value, bool logfailures); 159 160 virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; 161 virtual bool ExecuteForTask(int tid) const; 162 163 protected: GetPath()164 const std::string GetPath() const override { return path_; } 165 166 private: 167 std::string path_, value_; 168 bool logfailures_; 169 170 static bool WriteValueToFile(const std::string& value, const std::string& path, 171 bool logfailures); 172 }; 173 174 class TaskProfile { 175 public: TaskProfile()176 TaskProfile() : res_cached_(false) {} 177 Add(std::unique_ptr<ProfileAction> e)178 void Add(std::unique_ptr<ProfileAction> e) { elements_.push_back(std::move(e)); } 179 void MoveTo(TaskProfile* profile); 180 181 bool ExecuteForProcess(uid_t uid, pid_t pid) const; 182 bool ExecuteForTask(int tid) const; 183 void EnableResourceCaching(); 184 void DropResourceCaching(); 185 186 private: 187 bool res_cached_; 188 std::vector<std::unique_ptr<ProfileAction>> elements_; 189 }; 190 191 // Set aggregate profile element 192 class ApplyProfileAction : public ProfileAction { 193 public: ApplyProfileAction(const std::vector<std::shared_ptr<TaskProfile>> & profiles)194 ApplyProfileAction(const std::vector<std::shared_ptr<TaskProfile>>& profiles) 195 : profiles_(profiles) {} 196 197 virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; 198 virtual bool ExecuteForTask(int tid) const; 199 virtual void EnableResourceCaching(); 200 virtual void DropResourceCaching(); 201 202 private: 203 std::vector<std::shared_ptr<TaskProfile>> profiles_; 204 }; 205 206 class TaskProfiles { 207 public: 208 // Should be used by all users 209 static TaskProfiles& GetInstance(); 210 211 TaskProfile* GetProfile(const std::string& name) const; 212 const ProfileAttribute* GetAttribute(const std::string& name) const; 213 void DropResourceCaching() const; 214 bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles); 215 bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache); 216 217 private: 218 std::map<std::string, std::shared_ptr<TaskProfile>> profiles_; 219 std::map<std::string, std::unique_ptr<ProfileAttribute>> attributes_; 220 221 TaskProfiles(); 222 223 bool Load(const CgroupMap& cg_map, const std::string& file_name); 224 }; 225