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 class TaskProfile { 143 public: TaskProfile()144 TaskProfile() : res_cached_(false) {} 145 Add(std::unique_ptr<ProfileAction> e)146 void Add(std::unique_ptr<ProfileAction> e) { elements_.push_back(std::move(e)); } 147 void MoveTo(TaskProfile* profile); 148 149 bool ExecuteForProcess(uid_t uid, pid_t pid) const; 150 bool ExecuteForTask(int tid) const; 151 void EnableResourceCaching(); 152 void DropResourceCaching(); 153 154 private: 155 bool res_cached_; 156 std::vector<std::unique_ptr<ProfileAction>> elements_; 157 }; 158 159 // Set aggregate profile element 160 class ApplyProfileAction : public ProfileAction { 161 public: ApplyProfileAction(const std::vector<std::shared_ptr<TaskProfile>> & profiles)162 ApplyProfileAction(const std::vector<std::shared_ptr<TaskProfile>>& profiles) 163 : profiles_(profiles) {} 164 165 virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; 166 virtual bool ExecuteForTask(int tid) const; 167 virtual void EnableResourceCaching(); 168 virtual void DropResourceCaching(); 169 170 private: 171 std::vector<std::shared_ptr<TaskProfile>> profiles_; 172 }; 173 174 class TaskProfiles { 175 public: 176 // Should be used by all users 177 static TaskProfiles& GetInstance(); 178 179 TaskProfile* GetProfile(const std::string& name) const; 180 const ProfileAttribute* GetAttribute(const std::string& name) const; 181 void DropResourceCaching() const; 182 bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles); 183 bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache); 184 185 private: 186 std::map<std::string, std::shared_ptr<TaskProfile>> profiles_; 187 std::map<std::string, std::unique_ptr<ProfileAttribute>> attributes_; 188 189 TaskProfiles(); 190 191 bool Load(const CgroupMap& cg_map, const std::string& file_name); 192 }; 193