ThreadSchedule 3.0.0
Modern C++ thread management library
Loading...
Searching...
No Matches
posix.hpp
Go to the documentation of this file.
1#pragma once
2
11// --- shared implementation for pthread_t and pid_t scheduling ---
12
13inline auto
14pthread_call_result(int result) -> expected<void, std::error_code>
15{
16 if (result == 0)
17 return {};
18 return unexpected(std::error_code(result, std::generic_category()));
19}
20
21template <typename SetSchedFn>
22inline auto
23apply_sched_params(native_scheduling_policy policy, native_thread_priority priority, SetSchedFn&& set_sched)
24 -> expected<void, std::error_code>
25{
26 int const policy_int = static_cast<int>(policy);
27 auto params_result = scheduler_parameters::create_for_policy(policy, priority);
28 if (!params_result.has_value())
29 return unexpected(params_result.error());
30 if (set_sched(policy_int, &params_result.value()) == 0)
31 return {};
32 return unexpected(std::error_code(errno, std::generic_category()));
33}
34
35// --- pthread_t overloads used by std::thread::native_handle() ---
36
37inline auto
38apply_scheduling_policy(pthread_t handle, native_scheduling_policy policy, native_thread_priority priority)
39 -> expected<void, std::error_code>
40{
41 int const policy_int = static_cast<int>(policy);
42 auto params_result = scheduler_parameters::create_for_policy(policy, priority);
43 if (!params_result.has_value())
44 return unexpected(params_result.error());
45 int const result = pthread_setschedparam(handle, policy_int, &params_result.value());
46 return pthread_call_result(result);
47}
48
49inline auto
50apply_affinity(pthread_t handle, native_thread_affinity const& affinity) -> expected<void, std::error_code>
51{
52 int const result = pthread_setaffinity_np(handle, sizeof(cpu_set_t), &affinity.native_handle());
53 return pthread_call_result(result);
54}
55
56inline auto
57apply_name(pthread_t handle, std::string const& name) -> expected<void, std::error_code>
58{
59 if (name.length() > 15)
60 return unexpected(std::make_error_code(std::errc::invalid_argument));
61 int const result = pthread_setname_np(handle, name.c_str());
62 if (result == 0)
63 return {};
64 return unexpected(std::error_code(result, std::generic_category()));
65}
66
67inline auto
68read_name(pthread_t handle) -> expected<std::string, std::error_code>
69{
70 char name[16];
71 int const result = pthread_getname_np(handle, name, sizeof(name));
72 if (result == 0)
73 return std::string(name);
74 return unexpected(std::error_code(result, std::generic_category()));
75}
76
77inline auto
78read_affinity(pthread_t handle) -> expected<native_thread_affinity, std::error_code>
79{
80 cpu_set_t cpuset;
81 CPU_ZERO(&cpuset);
82 int const result = pthread_getaffinity_np(handle, sizeof(cpu_set_t), &cpuset);
83 if (result != 0)
84 return unexpected(std::error_code(result, std::generic_category()));
85
86 std::vector<int> cpus;
87 for (int i = 0; i < CPU_SETSIZE; ++i)
88 {
89 if (CPU_ISSET(i, &cpuset))
90 cpus.push_back(i);
91 }
92 return native_thread_affinity(cpus);
93}
94
95inline auto
96read_priority(pthread_t handle) -> std::optional<int>
97{
98 int policy = 0;
99 sched_param param{};
100 if (pthread_getschedparam(handle, &policy, &param) == 0)
101 return param.sched_priority;
102 return std::nullopt;
103}
104
105inline auto
106read_scheduling_policy(pthread_t handle) -> std::optional<native_scheduling_policy>
107{
108 int policy = 0;
109 sched_param param{};
110 if (pthread_getschedparam(handle, &policy, &param) == 0)
111 return static_cast<native_scheduling_policy>(policy);
112 return std::nullopt;
113}
114
115// --- pid_t / TID overloads (thread_by_name_view) ---
116
117inline auto
118apply_scheduling_policy(pid_t tid, native_scheduling_policy policy, native_thread_priority priority)
119 -> expected<void, std::error_code>
120{
121 return apply_sched_params(policy, priority, [tid](int p, sched_param* sp) { return sched_setscheduler(tid, p, sp); });
122}
123
124inline auto
125apply_nice_value(pid_t tid, int nice_value) -> expected<void, std::error_code>
126{
127 if (nice_value < -20 || nice_value > 19)
128 return unexpected(std::make_error_code(std::errc::invalid_argument));
129 if (tid <= 0)
130 return unexpected(std::make_error_code(std::errc::no_such_process));
131 if (setpriority(PRIO_PROCESS, static_cast<id_t>(tid), nice_value) == 0)
132 return {};
133 return unexpected(std::error_code(errno, std::generic_category()));
134}
135
136inline auto
137apply_affinity(pid_t tid, native_thread_affinity const& affinity) -> expected<void, std::error_code>
138{
139 if (sched_setaffinity(tid, sizeof(cpu_set_t), &affinity.native_handle()) == 0)
140 return {};
141 return unexpected(std::error_code(errno, std::generic_category()));
142}
143
144inline auto
145apply_name(pid_t tid, std::string const& name) -> expected<void, std::error_code>
146{
147 if (name.length() > 15)
148 return unexpected(std::make_error_code(std::errc::invalid_argument));
149
150 std::string const path = std::string("/proc/self/task/") + std::to_string(tid) + "/comm";
151 std::ofstream out(path);
152 if (!out)
153 return unexpected(std::error_code(errno, std::generic_category()));
154
155 out << name;
156 out.flush();
157 if (!out)
158 return unexpected(std::error_code(errno, std::generic_category()));
159 return {};
160}
161
162inline auto
163read_name(pid_t tid) -> expected<std::string, std::error_code>
164{
165 std::string const path = std::string("/proc/self/task/") + std::to_string(tid) + "/comm";
166 std::ifstream in(path);
167 if (!in)
168 return unexpected(std::error_code(errno, std::generic_category()));
169
170 std::string current;
171 std::getline(in, current);
172 if (in.bad())
173 return unexpected(std::error_code(errno, std::generic_category()));
174 if (!current.empty() && current.back() == '\n')
175 current.pop_back();
176 return current;
177}
178
179inline auto
180read_affinity(pid_t tid) -> expected<native_thread_affinity, std::error_code>
181{
182 cpu_set_t cpuset;
183 CPU_ZERO(&cpuset);
184 if (sched_getaffinity(tid, sizeof(cpu_set_t), &cpuset) != 0)
185 return unexpected(std::error_code(errno, std::generic_category()));
186
187 std::vector<int> cpus;
188 for (int i = 0; i < CPU_SETSIZE; ++i)
189 {
190 if (CPU_ISSET(i, &cpuset))
191 cpus.push_back(i);
192 }
193 return native_thread_affinity(cpus);
194}
195
196inline auto
197read_priority(pid_t tid) -> std::optional<int>
198{
199 sched_param param{};
200 if (sched_getparam(tid, &param) == 0)
201 return param.sched_priority;
202 return std::nullopt;
203}
204
205inline auto
206read_nice_value(pid_t tid) -> expected<int, std::error_code>
207{
208 if (tid <= 0)
209 return unexpected(std::make_error_code(std::errc::no_such_process));
210 errno = 0;
211 int const value = getpriority(PRIO_PROCESS, static_cast<id_t>(tid));
212 if (errno == 0)
213 return value;
214 return unexpected(std::error_code(errno, std::generic_category()));
215}
216
217inline auto
218read_scheduling_policy(pid_t tid) -> std::optional<native_scheduling_policy>
219{
220 int const policy = sched_getscheduler(tid);
221 if (policy == -1)
222 return std::nullopt;
223 return static_cast<native_scheduling_policy>(policy);
224}
auto read_scheduling_policy(pthread_t handle) -> std::optional< native_scheduling_policy >
Definition posix.hpp:106
auto pthread_call_result(int result) -> expected< void, std::error_code >
Definition posix.hpp:14
auto read_affinity(pthread_t handle) -> expected< native_thread_affinity, std::error_code >
Definition posix.hpp:78
auto apply_name(pthread_t handle, std::string const &name) -> expected< void, std::error_code >
Definition posix.hpp:57
auto apply_scheduling_policy(pthread_t handle, native_scheduling_policy policy, native_thread_priority priority) -> expected< void, std::error_code >
Definition posix.hpp:38
auto apply_nice_value(pid_t tid, int nice_value) -> expected< void, std::error_code >
Definition posix.hpp:125
auto apply_sched_params(native_scheduling_policy policy, native_thread_priority priority, SetSchedFn &&set_sched) -> expected< void, std::error_code >
Definition posix.hpp:23
auto read_priority(pthread_t handle) -> std::optional< int >
Definition posix.hpp:96
auto read_nice_value(pid_t tid) -> expected< int, std::error_code >
Definition posix.hpp:206
auto apply_affinity(pthread_t handle, native_thread_affinity const &affinity) -> expected< void, std::error_code >
Definition posix.hpp:50
auto read_name(pthread_t handle) -> expected< std::string, std::error_code >
Definition posix.hpp:68