1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "cpu_set.h"
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
34fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko#include <log/log.h>
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <algorithm>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <iomanip>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <iostream>
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sstream>
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <string>
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <android-base/file.h>
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "directory_reader.h"
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "stdio_filebuf.h"
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "task.h"
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "unique_file.h"
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace {
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconstexpr int kDirectoryFlags = O_RDONLY | O_DIRECTORY | O_CLOEXEC;
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconstexpr pid_t kKernelThreadDaemonPid = 2;
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // anonymous namespace
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace dvr {
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool CpuSet::prefix_enabled_ = false;
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid CpuSetManager::Load(const std::string& cpuset_root) {
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!root_set_)
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    root_set_ = Create(cpuset_root);
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::unique_ptr<CpuSet> CpuSetManager::Create(const std::string& path) {
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  base::unique_fd root_cpuset_fd(open(path.c_str(), kDirectoryFlags));
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (root_cpuset_fd.get() < 0) {
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("CpuSet::Create: Failed to open \"%s\": %s", path.c_str(),
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          strerror(errno));
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return nullptr;
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return Create(std::move(root_cpuset_fd), "/", nullptr);
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::unique_ptr<CpuSet> CpuSetManager::Create(base::unique_fd base_fd,
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                              const std::string& name,
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                              CpuSet* parent) {
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  DirectoryReader directory(base::unique_fd(dup(base_fd)));
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!directory) {
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("CpuSet::Create: Failed to opendir %s cpuset: %s", name.c_str(),
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          strerror(directory.GetError()));
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return nullptr;
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::unique_ptr<CpuSet> group(
57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      new CpuSet(parent, name, base::unique_fd(dup(base_fd))));
58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  path_map_.insert(std::make_pair(group->path(), group.get()));
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  while (dirent* entry = directory.Next()) {
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (entry->d_type == DT_DIR) {
62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      std::string directory_name(entry->d_name);
63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (directory_name == "." || directory_name == "..")
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        continue;
66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      base::unique_fd entry_fd(
68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          openat(base_fd.get(), directory_name.c_str(), kDirectoryFlags));
69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (entry_fd.get() >= 0) {
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        auto child =
71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            Create(std::move(entry_fd), directory_name.c_str(), group.get());
72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        if (child)
74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          group->AddChild(std::move(child));
75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        else
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          return nullptr;
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      } else {
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        ALOGE("CpuSet::Create: Failed to openat \"%s\": %s", entry->d_name,
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              strerror(errno));
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        return nullptr;
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return group;
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoCpuSet* CpuSetManager::Lookup(const std::string& path) {
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto search = path_map_.find(path);
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (search != path_map_.end())
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return search->second;
92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  else
93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return nullptr;
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::vector<CpuSet*> CpuSetManager::GetCpuSets() {
97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::vector<CpuSet*> sets(path_map_.size());
98e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
99e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  for (const auto& pair : path_map_) {
100e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    sets.push_back(pair.second);
101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return sets;
104e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::string CpuSetManager::DumpState() const {
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t max_path = 0;
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::vector<CpuSet*> sets;
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  for (const auto& pair : path_map_) {
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    max_path = std::max(max_path, pair.second->path().length());
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    sets.push_back(pair.second);
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::sort(sets.begin(), sets.end(), [](const CpuSet* a, const CpuSet* b) {
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return a->path() < b->path();
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  });
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::ostringstream stream;
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  stream << std::left;
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  stream << std::setw(max_path) << "Path";
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  stream << " ";
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  stream << std::setw(6) << "CPUs";
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  stream << " ";
126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  stream << std::setw(6) << "Tasks";
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  stream << std::endl;
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  stream << std::string(max_path, '_');
130e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  stream << " ";
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  stream << std::string(6, '_');
132e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  stream << " ";
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  stream << std::string(6, '_');
134e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  stream << std::endl;
135e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
136e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  for (const auto set : sets) {
137e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    stream << std::left;
138e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    stream << std::setw(max_path) << set->path();
139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    stream << " ";
140e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    stream << std::right;
141e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    stream << std::setw(6) << set->GetCpuList();
142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    stream << " ";
143e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    stream << std::setw(6) << set->GetTasks().size();
144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    stream << std::endl;
145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
146e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return stream.str();
148e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
149e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
150e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid CpuSetManager::MoveUnboundTasks(const std::string& target_set) {
151e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto root = Lookup("/");
152e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!root) {
153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("CpuSetManager::MoveUnboundTasks: Failed to find root cpuset!");
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return;
155e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto target = Lookup(target_set);
158e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!target) {
159e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE(
160e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "CpuSetManager::MoveUnboundTasks: Failed to find target cpuset \"%s\"!",
161e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        target_set.c_str());
162e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return;
163e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
164e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto cpu_list = root->GetCpuList();
166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
167e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  for (auto task_id : root->GetTasks()) {
168e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Task task(task_id);
169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Move only unbound kernel threads to the target cpuset.
171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (task.cpus_allowed_list() == cpu_list &&
172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        task.parent_process_id() == kKernelThreadDaemonPid) {
173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ALOGD_IF(TRACE,
174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko               "CpuSetManager::MoveUnboundTasks: Moving task_id=%d name=%s to "
175e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko               "target_set=%s tgid=%d ppid=%d.",
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko               task_id, task.name().c_str(), target_set.c_str(),
177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko               task.thread_group_id(), task.parent_process_id());
178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const int ret = target->AttachTask(task_id);
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ALOGW_IF(ret < 0 && ret != -EINVAL,
181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko               "CpuSetManager::MoveUnboundTasks: Failed to attach task_id=%d "
182e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko               "to cpuset=%s: %s",
183e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko               task_id, target_set.c_str(), strerror(-ret));
184e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else {
185e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ALOGD_IF(TRACE,
186e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko               "CpuSet::MoveUnboundTasks: Skipping task_id=%d name=%s cpus=%s.",
187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko               task_id, task.name().c_str(), task.cpus_allowed_list().c_str());
188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
190e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoCpuSet::CpuSet(CpuSet* parent, const std::string& name,
193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko               base::unique_fd&& cpuset_fd)
194e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    : parent_(parent), name_(name), cpuset_fd_(std::move(cpuset_fd)) {
195e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (parent_ == nullptr)
196e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    path_ = name_;
197e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  else if (parent_->IsRoot())
198e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    path_ = parent_->name() + name_;
199e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  else
200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    path_ = parent_->path() + "/" + name_;
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ALOGI("CpuSet::CpuSet: path=%s", path().c_str());
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
205e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobase::unique_fd CpuSet::OpenPropertyFile(const std::string& name) const {
206e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return OpenFile(prefix_enabled_ ? "cpuset." + name : name);
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
208e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
209e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoUniqueFile CpuSet::OpenPropertyFilePointer(const std::string& name) const {
210e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return OpenFilePointer(prefix_enabled_ ? "cpuset." + name : name);
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobase::unique_fd CpuSet::OpenFile(const std::string& name, int flags) const {
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const std::string relative_path = "./" + name;
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return base::unique_fd(
216e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      openat(cpuset_fd_.get(), relative_path.c_str(), flags));
217e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
218e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
219e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoUniqueFile CpuSet::OpenFilePointer(const std::string& name, int flags) const {
220e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const std::string relative_path = "./" + name;
221e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  base::unique_fd fd(openat(cpuset_fd_.get(), relative_path.c_str(), flags));
222e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (fd.get() < 0) {
223e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("CpuSet::OpenPropertyFilePointer: Failed to open %s/%s: %s",
224e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          path_.c_str(), name.c_str(), strerror(errno));
225e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return nullptr;
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  UniqueFile fp(fdopen(fd.release(), "r"));
229e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!fp)
230e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("CpuSet::OpenPropertyFilePointer: Failed to fdopen %s/%s: %s",
231e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          path_.c_str(), name.c_str(), strerror(errno));
232e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
233e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return fp;
234e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
235e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint CpuSet::AttachTask(pid_t task_id) const {
237e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto file = OpenFile("tasks", O_RDWR);
238e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (file.get() >= 0) {
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::ostringstream stream;
240e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    stream << task_id;
241e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::string value = stream.str();
242e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
243e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const bool ret = base::WriteStringToFd(value, file.get());
244e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return !ret ? -errno : 0;
245e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
246e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE("CpuSet::AttachTask: Failed to open %s/tasks: %s", path_.c_str(),
247e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          strerror(errno));
248e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return -errno;
249e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
250e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
251e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
252e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::vector<pid_t> CpuSet::GetTasks() const {
253e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::vector<pid_t> tasks;
254e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
255e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto file = OpenFilePointer("tasks")) {
256e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    stdio_filebuf<char> filebuf(file.get());
257e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::istream file_stream(&filebuf);
258e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
259e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    for (std::string line; std::getline(file_stream, line);) {
260e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      pid_t task_id = std::strtol(line.c_str(), nullptr, 10);
261e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      tasks.push_back(task_id);
262e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
263e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
264e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
265e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return tasks;
266e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
267e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::string CpuSet::GetCpuList() const {
269e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (auto file = OpenPropertyFilePointer("cpus")) {
270e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    stdio_filebuf<char> filebuf(file.get());
271e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::istream file_stream(&filebuf);
272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
273e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::string line;
274e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (std::getline(file_stream, line))
275e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return line;
276e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
277e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
278e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ALOGE("CpuSet::GetCpuList: Failed to read cpu list!!!");
279e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return "";
280e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
281e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid CpuSet::AddChild(std::unique_ptr<CpuSet> child) {
283e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  children_.push_back(std::move(child));
284e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
285e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
286e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace dvr
287e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
288