Skip to content

Commit 209c580

Browse files
committed
Actually add the new files
1 parent eca7c94 commit 209c580

File tree

4 files changed

+296
-0
lines changed

4 files changed

+296
-0
lines changed

output_manager.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#include <cstdlib>
2+
#include <cstring>
3+
#include <sys/types.h>
4+
#include <sys/stat.h>
5+
#include <fcntl.h>
6+
#include <unistd.h>
7+
8+
#include "output_manager.hpp"
9+
#include "functions.hpp"
10+
11+
namespace tsp
12+
{
13+
Output_handler::Output_handler(bool disappear, bool separate_stderr, const char *jobid)
14+
{
15+
if (disappear)
16+
{
17+
stdout_fd = open("/dev/null", O_WRONLY | O_CREAT, 0666);
18+
stderr_fd = open("/dev/null", O_WRONLY | O_CREAT, 0666);
19+
}
20+
else
21+
{
22+
asprintf(&stdout_fn, "%s" OUTPUT_FILE_TEMPLATE "%s", get_tmp(), jobid);
23+
stdout_fd = open(stdout_fn, O_WRONLY | O_CREAT, 0600);
24+
dup2(stdout_fd, 1);
25+
if (separate_stderr)
26+
{
27+
asprintf(&stderr_fn, "%s" ERROR_FILE_TEMPLATE "%s", get_tmp(), jobid);
28+
dup2(stderr_fd, 2);
29+
stderr_fd = open(stderr_fn, O_WRONLY | O_CREAT, 0600);
30+
}
31+
else
32+
{
33+
dup2(stdout_fd, 2);
34+
}
35+
}
36+
}
37+
Output_handler::~Output_handler()
38+
{
39+
if (stdout_fn != nullptr)
40+
{
41+
free(stdout_fn);
42+
}
43+
if (stderr_fn != nullptr)
44+
{
45+
free(stderr_fn);
46+
}
47+
if (stdout_fd != -1)
48+
{
49+
close(stdout_fd);
50+
}
51+
if (stderr_fd != -1)
52+
{
53+
close(stderr_fd);
54+
}
55+
}
56+
}

output_manager.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#pragma once
2+
3+
#define OUTPUT_FILE_TEMPLATE "/tsp.o"
4+
#define ERROR_FILE_TEMPLATE "/tsp.e"
5+
6+
namespace tsp
7+
{
8+
class Output_handler
9+
{
10+
public:
11+
int stdout_fd;
12+
int stderr_fd;
13+
Output_handler(bool disappear, bool separate_stderr, const char *jobid);
14+
~Output_handler();
15+
16+
private:
17+
char *stdout_fn = nullptr;
18+
char *stderr_fn = nullptr;
19+
};
20+
}

proc_manager.cpp

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
#include <fstream>
2+
#include <algorithm>
3+
#include <numeric>
4+
5+
#include "proc_manager.hpp"
6+
#include "functions.hpp"
7+
#include "semaphore.hpp"
8+
9+
namespace tsp
10+
{
11+
12+
Tsp_Proc::Tsp_Proc(uint32_t np) : pid(getpid()), nslots(np), my_path(std::filesystem::read_symlink("/proc/self/exe")), cpuset_from_cgroup(get_cgroup())
13+
{
14+
// Open cgroups file
15+
if (nslots > cpuset_from_cgroup.size())
16+
{
17+
die_with_err("More slots requested than available on the system, this process can never run.", -1);
18+
}
19+
refresh_allowed_cores();
20+
}
21+
22+
bool Tsp_Proc::allowed_to_run()
23+
{
24+
return allowed_cores.size() > nslots;
25+
}
26+
27+
void Tsp_Proc::refresh_allowed_cores()
28+
{
29+
auto sibling_pids = get_siblings();
30+
std::vector<uint32_t> siblings_affinity;
31+
for (auto i : sibling_pids)
32+
{
33+
auto tmp = get_sibling_affinity(i);
34+
siblings_affinity.insert(siblings_affinity.end(), tmp.begin(), tmp.end());
35+
}
36+
std::sort(siblings_affinity.begin(), siblings_affinity.end());
37+
allowed_cores.clear();
38+
std::set_difference(cpuset_from_cgroup.begin(), cpuset_from_cgroup.end(),
39+
siblings_affinity.begin(), siblings_affinity.end(),
40+
std::inserter(allowed_cores, allowed_cores.begin()));
41+
}
42+
43+
std::vector<pid_t> Tsp_Proc::get_siblings()
44+
{
45+
std::vector<pid_t> out;
46+
std::vector<std::string> skip_paths = {std::to_string(pid), "self", "thread-self"};
47+
// Find all the other versions of this application running
48+
for (const auto &entry : std::filesystem::directory_iterator("/proc"))
49+
{
50+
if (std::find(skip_paths.begin(), skip_paths.end(), entry.path().filename()) != skip_paths.end())
51+
{
52+
continue;
53+
}
54+
if (std::filesystem::exists(entry.path() / "exe"))
55+
{
56+
try
57+
{
58+
if (std::filesystem::read_symlink(entry.path() / "exe") == my_path)
59+
{
60+
out.push_back(std::stoul(entry.path().filename()));
61+
}
62+
}
63+
catch (std::filesystem::filesystem_error &e)
64+
{
65+
// process went away
66+
continue;
67+
}
68+
}
69+
}
70+
return out;
71+
};
72+
73+
std::vector<std::uint32_t> Tsp_Proc::parse_cpuset_range(std::string in)
74+
{
75+
std::stringstream ss1(in);
76+
std::string token;
77+
std::vector<std::uint32_t> out;
78+
while (std::getline(ss1, token, ','))
79+
{
80+
if (token.find('-') == std::string::npos)
81+
{
82+
out.push_back(std::stoul(token));
83+
}
84+
else
85+
{
86+
std::stringstream ss2(token);
87+
std::string starts, ends;
88+
std::getline(ss2, starts, '-');
89+
std::getline(ss2, ends, '-');
90+
std::vector<std::uint32_t> tmp(std::stoul(ends) - std::stoul(starts) + 1);
91+
std::iota(tmp.begin(), tmp.end(), std::stoul(starts));
92+
out.insert(out.end(), tmp.begin(), tmp.end());
93+
}
94+
}
95+
return out;
96+
};
97+
98+
std::vector<uint32_t> Tsp_Proc::get_sibling_affinity(pid_t pid)
99+
{
100+
std::vector<uint32_t> out;
101+
cpu_set_t mask;
102+
// Just return an empty vector if the semaphore file is present
103+
try
104+
{
105+
for (const auto &entry : std::filesystem::directory_iterator("/proc/" + std::to_string(pid) + "/fd"))
106+
if (std::filesystem::read_symlink(entry).string().find(SEMAPHORE_FILE_TEMPLATE) != std::string::npos)
107+
{
108+
// Semaphore present, ignore
109+
return out;
110+
}
111+
}
112+
113+
catch (std::filesystem::filesystem_error &e)
114+
{
115+
// Process went away
116+
return out;
117+
}
118+
if (sched_getaffinity(pid, sizeof(mask), &mask) == -1)
119+
{
120+
// Process may have been killed - so it isn't taking
121+
// resources any more
122+
return out;
123+
}
124+
for (const auto &i : cpuset_from_cgroup)
125+
{
126+
if (CPU_ISSET(i, &mask))
127+
{
128+
out.push_back(i);
129+
}
130+
}
131+
return out;
132+
};
133+
134+
std::vector<uint32_t> Tsp_Proc::get_cgroup()
135+
{
136+
std::filesystem::path cgroup_fn(std::string("/proc/" + std::to_string(pid) + "/cgroup"));
137+
if (!std::filesystem::exists(cgroup_fn))
138+
{
139+
throw std::runtime_error("Cgroup file for process " + std::to_string(pid) + " not found");
140+
}
141+
std::string line;
142+
std::filesystem::path cpuset_path;
143+
// get cpuset path
144+
std::ifstream cgroup_file(cgroup_fn);
145+
if (cgroup_file.is_open())
146+
{
147+
while (std::getline(cgroup_file, line))
148+
{
149+
std::vector<std::string> seglist;
150+
std::string segment;
151+
std::stringstream ss(line);
152+
while (std::getline(ss, segment, ':'))
153+
{
154+
seglist.push_back(segment);
155+
};
156+
if (seglist[1] == "cpuset")
157+
{
158+
cpuset_path = CGROUP_CPUSET_PATH_PREFIX;
159+
cpuset_path += seglist[2];
160+
cpuset_path += CPUSET_FILE;
161+
}
162+
if (!cpuset_path.empty())
163+
{
164+
break;
165+
}
166+
}
167+
cgroup_file.close();
168+
}
169+
else
170+
{
171+
throw std::runtime_error("Unable to open cgroup file " + cgroup_fn.string());
172+
}
173+
// read cpuset file
174+
std::ifstream cpuset_file(cpuset_path);
175+
if (cpuset_file.is_open())
176+
{
177+
std::getline(cpuset_file, line);
178+
return parse_cpuset_range(line);
179+
}
180+
else
181+
{
182+
throw std::runtime_error("Unable to open cpuset file " + cpuset_path.string());
183+
}
184+
}
185+
};

proc_manager.hpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#pragma once
2+
3+
#include <vector>
4+
#include <cstdlib>
5+
#include <cstdint>
6+
#include <string>
7+
#include <unistd.h>
8+
#include <filesystem>
9+
#include <sys/types.h>
10+
11+
#define CGROUP_CPUSET_PATH_PREFIX "/sys/fs/cgroup/cpuset"
12+
#define CPUSET_FILE "/cpuset.cpus"
13+
14+
namespace tsp
15+
{
16+
class Tsp_Proc
17+
{
18+
public:
19+
const pid_t pid;
20+
std::vector<uint32_t> allowed_cores;
21+
Tsp_Proc(uint32_t nslots);
22+
bool allowed_to_run();
23+
void refresh_allowed_cores();
24+
~Tsp_Proc() {};
25+
26+
private:
27+
const uint32_t nslots;
28+
const std::filesystem::path my_path;
29+
const std::vector<uint32_t> cpuset_from_cgroup;
30+
std::vector<pid_t> get_siblings();
31+
std::vector<std::uint32_t> parse_cpuset_range(std::string in);
32+
std::vector<uint32_t> get_sibling_affinity(pid_t pid);
33+
std::vector<uint32_t> get_cgroup();
34+
};
35+
}

0 commit comments

Comments
 (0)