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