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