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 // Set cgroup profile element 112 class SetCgroupAction : public ProfileAction { 113 public: 114 SetCgroupAction(const CgroupController& c, const std::string& p); 115 116 virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; 117 virtual bool ExecuteForTask(int tid) const; 118 virtual void EnableResourceCaching(); 119 virtual void DropResourceCaching(); 120 controller()121 const CgroupController* controller() const { return &controller_; } path()122 std::string path() const { return path_; } 123 124 private: 125 enum FdState { 126 FDS_INACCESSIBLE = -1, 127 FDS_APP_DEPENDENT = -2, 128 FDS_NOT_CACHED = -3, 129 }; 130 131 CgroupController controller_; 132 std::string path_; 133 android::base::unique_fd fd_; 134 mutable std::mutex fd_mutex_; 135 136 static bool IsAppDependentPath(const std::string& path); 137 static bool AddTidToCgroup(int tid, int fd); 138 IsFdValid()139 bool IsFdValid() const { return fd_ > FDS_INACCESSIBLE; } 140 }; 141 142 // Write to file action 143 class WriteFileAction : public ProfileAction { 144 public: WriteFileAction(const std::string & filepath,const std::string & value,bool logfailures)145 WriteFileAction(const std::string& filepath, const std::string& value, 146 bool logfailures) noexcept 147 : filepath_(filepath), value_(value), logfailures_(logfailures) {} 148 149 virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; 150 virtual bool ExecuteForTask(int tid) const; 151 152 private: 153 std::string filepath_, value_; 154 bool logfailures_; 155 }; 156 157 class TaskProfile { 158 public: TaskProfile()159 TaskProfile() : res_cached_(false) {} 160 Add(std::unique_ptr<ProfileAction> e)161 void Add(std::unique_ptr<ProfileAction> e) { elements_.push_back(std::move(e)); } 162 void MoveTo(TaskProfile* profile); 163 164 bool ExecuteForProcess(uid_t uid, pid_t pid) const; 165 bool ExecuteForTask(int tid) const; 166 void EnableResourceCaching(); 167 void DropResourceCaching(); 168 169 private: 170 bool res_cached_; 171 std::vector<std::unique_ptr<ProfileAction>> elements_; 172 }; 173 174 // Set aggregate profile element 175 class ApplyProfileAction : public ProfileAction { 176 public: ApplyProfileAction(const std::vector<std::shared_ptr<TaskProfile>> & profiles)177 ApplyProfileAction(const std::vector<std::shared_ptr<TaskProfile>>& profiles) 178 : profiles_(profiles) {} 179 180 virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; 181 virtual bool ExecuteForTask(int tid) const; 182 virtual void EnableResourceCaching(); 183 virtual void DropResourceCaching(); 184 185 private: 186 std::vector<std::shared_ptr<TaskProfile>> profiles_; 187 }; 188 189 class TaskProfiles { 190 public: 191 // Should be used by all users 192 static TaskProfiles& GetInstance(); 193 194 TaskProfile* GetProfile(const std::string& name) const; 195 const ProfileAttribute* GetAttribute(const std::string& name) const; 196 void DropResourceCaching() const; 197 bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles); 198 bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache); 199 200 private: 201 std::map<std::string, std::shared_ptr<TaskProfile>> profiles_; 202 std::map<std::string, std::unique_ptr<ProfileAttribute>> attributes_; 203 204 TaskProfiles(); 205 206 bool Load(const CgroupMap& cg_map, const std::string& file_name); 207 }; 208