1+ #include < fstream>
2+ #include < algorithm>
3+ #include < numeric>
4+
5+ #include " proc_affinity.hpp"
6+ #include " functions.hpp"
7+ #include " semaphore.hpp"
8+
9+ namespace tsp
10+ {
11+
12+ Proc_affinity::Proc_affinity (uint32_t nslots, pid_t pid) : nslots(nslots), pid(pid), 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+ CPU_ZERO (&mask);
20+
21+ }
22+
23+ std::vector<uint32_t > Proc_affinity::bind ()
24+ {
25+ auto sibling_pids = get_siblings ();
26+ std::vector<uint32_t > siblings_affinity;
27+ std::vector<uint32_t > out;
28+ for (auto i : sibling_pids)
29+ {
30+ auto tmp = get_sibling_affinity (i);
31+ siblings_affinity.insert (siblings_affinity.end (), tmp.begin (), tmp.end ());
32+ }
33+ std::sort (siblings_affinity.begin (), siblings_affinity.end ());
34+ std::vector<uint32_t > allowed_cores;
35+ std::set_difference (cpuset_from_cgroup.begin (), cpuset_from_cgroup.end (),
36+ siblings_affinity.begin (), siblings_affinity.end (),
37+ std::inserter (allowed_cores, allowed_cores.begin ()));
38+
39+ if (allowed_cores.size () < nslots)
40+ {
41+ // Something has beaten us to the punch, report failed and
42+ // try again the next time
43+ return out;
44+ }
45+ for (uint32_t i = 0 ; i < nslots; i++)
46+ {
47+ CPU_SET (allowed_cores[i], &mask);
48+ out.push_back (allowed_cores[i]);
49+ }
50+ if (sched_setaffinity (0 , sizeof (cpu_set_t ), &mask) == -1 )
51+ {
52+ die_with_err (" Unable to set CPU affinity" , -1 );
53+ }
54+ return out;
55+ }
56+
57+ std::vector<pid_t > Proc_affinity::get_siblings ()
58+ {
59+ std::vector<pid_t > out;
60+ // Find all the other versions of this application running
61+ for (const auto &entry : std::filesystem::directory_iterator (" /proc" ))
62+ {
63+ if (std::find (skip_paths.begin (), skip_paths.end (), entry.path ().filename ()) != skip_paths.end ())
64+ {
65+ continue ;
66+ }
67+ if (std::filesystem::exists (entry.path () / " exe" ))
68+ {
69+ try
70+ {
71+ if (std::filesystem::read_symlink (entry.path () / " exe" ) == my_path)
72+ {
73+ out.push_back (std::stoul (entry.path ().filename ()));
74+ }
75+ }
76+ catch (std::filesystem::filesystem_error &e)
77+ {
78+ // process went away
79+ continue ;
80+ }
81+ }
82+ }
83+ return out;
84+ };
85+
86+ std::vector<uint32_t > Proc_affinity::get_sibling_affinity (pid_t pid)
87+ {
88+ std::vector<uint32_t > out;
89+ cpu_set_t mask;
90+ // Just return an empty vector if the semaphore file is present
91+ try
92+ {
93+ for (const auto &entry : std::filesystem::directory_iterator (" /proc/" + std::to_string (pid) + " /fd" ))
94+ if (std::filesystem::read_symlink (entry).string ().find (SEMAPHORE_FILE_TEMPLATE) != std::string::npos)
95+ {
96+ // Semaphore present, ignore
97+ return out;
98+ }
99+ }
100+
101+ catch (std::filesystem::filesystem_error &e)
102+ {
103+ // Process went away
104+ return out;
105+ }
106+ if (sched_getaffinity (pid, sizeof (mask), &mask) == -1 )
107+ {
108+ // Process may have been killed - so it isn't taking
109+ // resources any more
110+ return out;
111+ }
112+ for (const auto &i : cpuset_from_cgroup)
113+ {
114+ if (CPU_ISSET (i, &mask))
115+ {
116+ out.push_back (i);
117+ }
118+ }
119+ return out;
120+ };
121+ };
0 commit comments