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 37 bool GetPathForTask(int tid, std::string* path) const; 38 39 private: 40 CgroupController controller_; 41 std::string file_name_; 42 }; 43 44 // Abstract profile element 45 class ProfileAction { 46 public: ~ProfileAction()47 virtual ~ProfileAction() {} 48 49 // Default implementations will fail ExecuteForProcess(uid_t,pid_t)50 virtual bool ExecuteForProcess(uid_t, pid_t) const { return false; }; ExecuteForTask(int)51 virtual bool ExecuteForTask(int) const { return false; }; 52 EnableResourceCaching()53 virtual void EnableResourceCaching() {} 54 }; 55 56 // Profile actions 57 class SetClampsAction : public ProfileAction { 58 public: SetClampsAction(int boost,int clamp)59 SetClampsAction(int boost, int clamp) noexcept : boost_(boost), clamp_(clamp) {} 60 61 virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; 62 virtual bool ExecuteForTask(int tid) const; 63 64 protected: 65 int boost_; 66 int clamp_; 67 }; 68 69 // To avoid issues in sdk_mac build 70 #if defined(__ANDROID__) 71 72 class SetTimerSlackAction : public ProfileAction { 73 public: SetTimerSlackAction(unsigned long slack)74 SetTimerSlackAction(unsigned long slack) noexcept : slack_(slack) {} 75 76 virtual bool ExecuteForTask(int tid) const; 77 78 private: 79 unsigned long slack_; 80 81 static bool IsTimerSlackSupported(int tid); 82 }; 83 84 #else 85 86 class SetTimerSlackAction : public ProfileAction { 87 public: SetTimerSlackAction(unsigned long)88 SetTimerSlackAction(unsigned long) noexcept {} 89 ExecuteForTask(int)90 virtual bool ExecuteForTask(int) const { return true; } 91 }; 92 93 #endif 94 95 // Set attribute profile element 96 class SetAttributeAction : public ProfileAction { 97 public: SetAttributeAction(const ProfileAttribute * attribute,const std::string & value)98 SetAttributeAction(const ProfileAttribute* attribute, const std::string& value) 99 : attribute_(attribute), value_(value) {} 100 101 virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; 102 virtual bool ExecuteForTask(int tid) const; 103 104 private: 105 const ProfileAttribute* attribute_; 106 std::string value_; 107 }; 108 109 // Set cgroup profile element 110 class SetCgroupAction : public ProfileAction { 111 public: 112 SetCgroupAction(const CgroupController& c, const std::string& p); 113 114 virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; 115 virtual bool ExecuteForTask(int tid) const; 116 virtual void EnableResourceCaching(); 117 controller()118 const CgroupController* controller() const { return &controller_; } path()119 std::string path() const { return path_; } 120 121 private: 122 enum FdState { 123 FDS_INACCESSIBLE = -1, 124 FDS_APP_DEPENDENT = -2, 125 FDS_NOT_CACHED = -3, 126 }; 127 128 CgroupController controller_; 129 std::string path_; 130 android::base::unique_fd fd_; 131 mutable std::mutex fd_mutex_; 132 133 static bool IsAppDependentPath(const std::string& path); 134 static bool AddTidToCgroup(int tid, int fd); 135 IsFdValid()136 bool IsFdValid() const { return fd_ > FDS_INACCESSIBLE; } 137 }; 138 139 class TaskProfile { 140 public: TaskProfile()141 TaskProfile() : res_cached_(false) {} 142 Add(std::unique_ptr<ProfileAction> e)143 void Add(std::unique_ptr<ProfileAction> e) { elements_.push_back(std::move(e)); } 144 145 bool ExecuteForProcess(uid_t uid, pid_t pid) const; 146 bool ExecuteForTask(int tid) const; 147 void EnableResourceCaching(); 148 149 private: 150 bool res_cached_; 151 std::vector<std::unique_ptr<ProfileAction>> elements_; 152 }; 153 154 class TaskProfiles { 155 public: 156 // Should be used by all users 157 static TaskProfiles& GetInstance(); 158 159 TaskProfile* GetProfile(const std::string& name) const; 160 const ProfileAttribute* GetAttribute(const std::string& name) const; 161 162 private: 163 std::map<std::string, std::unique_ptr<TaskProfile>> profiles_; 164 std::map<std::string, std::unique_ptr<ProfileAttribute>> attributes_; 165 166 TaskProfiles(); 167 168 bool Load(const CgroupMap& cg_map, const std::string& file_name); 169 }; 170