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