1 #ifndef ANDROID_DVR_PERFORMANCED_CPU_SET_H_
2 #define ANDROID_DVR_PERFORMANCED_CPU_SET_H_
3 
4 #include <fcntl.h>
5 
6 #include <memory>
7 #include <mutex>
8 #include <sstream>
9 #include <string>
10 #include <unordered_map>
11 #include <vector>
12 
13 #include <android-base/unique_fd.h>
14 
15 #include <pdx/status.h>
16 
17 #include "unique_file.h"
18 
19 namespace android {
20 namespace dvr {
21 
22 class CpuSet {
23  public:
24   // Returns the parent group for this group, if any. This pointer is owned by
25   // the group hierarchy and is only valid as long as the hierarchy is valid.
parent()26   CpuSet* parent() const { return parent_; }
name()27   std::string name() const { return name_; }
path()28   std::string path() const { return path_; }
29 
IsRoot()30   bool IsRoot() const { return parent_ == nullptr; }
31 
32   std::string GetCpuList() const;
33 
34   pdx::Status<void> AttachTask(pid_t task_id) const;
35   std::vector<pid_t> GetTasks() const;
36 
37  private:
38   friend class CpuSetManager;
39 
40   CpuSet(CpuSet* parent, const std::string& name, base::unique_fd&& cpuset_fd);
41 
42   void AddChild(std::unique_ptr<CpuSet> child);
43 
44   base::unique_fd OpenPropertyFile(const std::string& name) const;
45   UniqueFile OpenPropertyFilePointer(const std::string& name) const;
46 
47   base::unique_fd OpenFile(const std::string& name, int flags = O_RDONLY) const;
48   UniqueFile OpenFilePointer(const std::string& name,
49                              int flags = O_RDONLY) const;
50 
51   CpuSet* parent_;
52   std::string name_;
53   std::string path_;
54   base::unique_fd cpuset_fd_;
55   std::vector<std::unique_ptr<CpuSet>> children_;
56 
SetPrefixEnabled(bool enabled)57   static void SetPrefixEnabled(bool enabled) { prefix_enabled_ = enabled; }
58   static bool prefix_enabled_;
59 
60   CpuSet(const CpuSet&) = delete;
61   void operator=(const CpuSet&) = delete;
62 };
63 
64 class CpuSetManager {
65  public:
CpuSetManager()66   CpuSetManager() {}
67 
68   // Creats a CpuSet hierarchy by walking the directory tree starting at
69   // |cpuset_root|. This argument must be the path to the root cpuset for the
70   // system, which is usually /dev/cpuset.
71   void Load(const std::string& cpuset_root);
72 
73   // Lookup and return a CpuSet from a cpuset path. Ownership of the pointer
74   // DOES NOT pass to the caller; the pointer remains valid as long as the
75   // CpuSet hierarchy is valid.
76   CpuSet* Lookup(const std::string& path);
77 
78   // Returns a vector of all the cpusets found at initializaiton. Ownership of
79   // the pointers to CpuSets DOES NOT pass to the caller; the pointers remain
80   // valid as long as the CpuSet hierarchy is valid.
81   std::vector<CpuSet*> GetCpuSets();
82 
83   // Moves all unbound tasks from the root set into the target set. This is used
84   // to shield the system from interference from unbound kernel threads.
85   void MoveUnboundTasks(const std::string& target_set);
86 
87   void DumpState(std::ostringstream& stream) const;
88 
89   operator bool() const { return root_set_ != nullptr; }
90 
91  private:
92   // Creates a CpuSet from a path to a cpuset cgroup directory. Recursively
93   // creates child groups for each directory found under |path|.
94   std::unique_ptr<CpuSet> Create(const std::string& path);
95   std::unique_ptr<CpuSet> Create(base::unique_fd base_fd,
96                                  const std::string& name, CpuSet* parent);
97 
98   std::unique_ptr<CpuSet> root_set_;
99   std::unordered_map<std::string, CpuSet*> path_map_;
100 
101   CpuSetManager(const CpuSetManager&) = delete;
102   void operator=(const CpuSetManager&) = delete;
103 };
104 
105 }  // namespace dvr
106 }  // namespace android
107 
108 #endif  // ANDROID_DVR_PERFORMANCED_CPU_SET_H_
109