8#include "../../expected.hpp"
18#include <system_error>
22# include "../unique_handle.hpp"
23# include "../windows_api.hpp"
27# if defined(__MINGW32__)
33# include <sys/resource.h>
34# include <sys/types.h>
100# ifdef SCHED_DEADLINE
101 deadline = SCHED_DEADLINE
143 : priority_(
std::clamp(priority, min_priority, max_priority))
147 [[nodiscard]]
constexpr auto
152 [[nodiscard]]
constexpr auto
155 return priority_ >= min_priority && priority_ <= max_priority;
158 [[nodiscard]]
static constexpr auto
163 [[nodiscard]]
static constexpr auto
168 [[nodiscard]]
static constexpr auto
173 [[nodiscard]]
static constexpr auto
178 [[nodiscard]]
static constexpr auto
184 [[nodiscard]]
constexpr auto
187 return priority_ ==
other.priority_;
189 [[nodiscard]]
constexpr auto
192 return priority_ !=
other.priority_;
194 [[nodiscard]]
constexpr auto
197 return priority_ <
other.priority_;
199 [[nodiscard]]
constexpr auto
202 return priority_ <=
other.priority_;
204 [[nodiscard]]
constexpr auto
207 return priority_ >
other.priority_;
209 [[nodiscard]]
constexpr auto
212 return priority_ >=
other.priority_;
218 std::ostringstream oss;
219 oss <<
"native_thread_priority(" << priority_ <<
")";
224 static constexpr int min_nice_priority = -20;
225 static constexpr int max_nice_priority = 19;
226 static constexpr int min_realtime_priority = 1;
227 static constexpr int max_realtime_priority = 99;
228 static constexpr int min_priority = min_nice_priority;
229 static constexpr int max_priority = max_realtime_priority;
268namespace native_schedule
270[[nodiscard]]
constexpr auto
277[[nodiscard]]
constexpr auto
284[[nodiscard]]
constexpr auto
291[[nodiscard]]
constexpr auto
298[[nodiscard]]
constexpr auto
305[[nodiscard]]
constexpr auto
312[[nodiscard]]
constexpr auto
319[[nodiscard]]
constexpr auto
325[[nodiscard]]
constexpr auto
329 bool const valid = priority == THREAD_PRIORITY_IDLE || priority == THREAD_PRIORITY_LOWEST
330 || priority == THREAD_PRIORITY_BELOW_NORMAL || priority == THREAD_PRIORITY_NORMAL
331 || priority == THREAD_PRIORITY_ABOVE_NORMAL || priority == THREAD_PRIORITY_HIGHEST
332 || priority == THREAD_PRIORITY_TIME_CRITICAL;
334 bool const valid =
false;
352[[nodiscard]]
constexpr auto
358 return { policy, config.priority, config.model, config.valid };
362 return { config.policy, config.priority, config.model, config.valid };
364 switch (config.intent)
374 config.model, config.valid };
383map_priority_to_win32(
int prio_val) ->
int
386 return THREAD_PRIORITY_HIGHEST;
388 return THREAD_PRIORITY_ABOVE_NORMAL;
390 return THREAD_PRIORITY_NORMAL;
392 return THREAD_PRIORITY_BELOW_NORMAL;
394 return THREAD_PRIORITY_LOWEST;
395 return THREAD_PRIORITY_IDLE;
461 WORD g =
static_cast<WORD
>(cpu / 64);
472 mask_ |= (
static_cast<unsigned long long>(1) << bit);
474 if (cpu >= 0 && cpu < CPU_SETSIZE)
476 CPU_SET(cpu, &cpuset_);
487 WORD g =
static_cast<WORD
>(cpu / 64);
491 mask_ &= ~(
static_cast<unsigned long long>(1) << bit);
494 if (cpu >= 0 && cpu < CPU_SETSIZE)
496 CPU_CLR(cpu, &cpuset_);
507 WORD g =
static_cast<WORD
>(cpu / 64);
509 return g == group_ && (mask_ & (
static_cast<unsigned long long>(1) << bit)) != 0;
511 return cpu >= 0 && cpu < CPU_SETSIZE && CPU_ISSET(cpu, &cpuset_);
534 std::vector<int> cpus;
536 for (
int i = 0; i < 64; ++i)
538 if (mask_ & (
static_cast<unsigned long long>(1) << i))
540 cpus.push_back(
static_cast<int>(group_) * 64 + i);
544 for (
int i = 0; i < CPU_SETSIZE; ++i)
546 if (CPU_ISSET(i, &cpuset_))
556 [[nodiscard]]
unsigned long long
583 std::ostringstream oss;
584 oss <<
"native_thread_affinity({";
585 for (
size_t i = 0; i < cpus.size(); ++i)
598 unsigned long long mask_;
606 std::optional<std::string>
name;
655 struct sched_param_win
663 sched_param_win param{};
666 if (priority.value() >= 75 || priority.value() <= -10)
667 param.sched_priority = THREAD_PRIORITY_HIGHEST;
669 param.sched_priority = THREAD_PRIORITY_ABOVE_NORMAL;
673 param.sched_priority = detail::map_priority_to_win32(priority.value());
690# ifdef SCHED_DEADLINE
691 if (policy == native_scheduling_policy::deadline)
692 return unexpected(std::make_error_code(std::errc::function_not_supported));
695 int const policy_int =
static_cast<int>(policy);
696 int const min_prio = sched_get_priority_min(policy_int);
697 int const max_prio = sched_get_priority_max(policy_int);
699 if (min_prio == -1 || max_prio == -1)
701 return unexpected(std::make_error_code(std::errc::invalid_argument));
704 if (min_prio == max_prio)
706 param.sched_priority = min_prio;
712 param.sched_priority = std::clamp(priority.value(), min_prio, max_prio);
716 constexpr int highest_nice_value = -20;
717 constexpr int lowest_nice_value = 19;
718 constexpr int user_span = lowest_nice_value - highest_nice_value;
719 int const native_span = max_prio - min_prio;
720 int const offset = std::clamp(priority.value(), highest_nice_value, lowest_nice_value) - highest_nice_value;
721 param.sched_priority = max_prio - (((offset * native_span) + (user_span / 2)) / user_span);
728# ifdef SCHED_DEADLINE
729 if (policy == native_scheduling_policy::deadline)
730 return unexpected(std::make_error_code(std::errc::function_not_supported));
733 int const policy_int =
static_cast<int>(policy);
734 int const min_prio = sched_get_priority_min(policy_int);
735 int const max_prio = sched_get_priority_max(policy_int);
737 if (min_prio == -1 || max_prio == -1)
739 return unexpected(std::make_error_code(std::errc::invalid_argument));
742 return max_prio - min_prio;
765#if defined(SCHED_DEADLINE) && !defined(_WIN32)
766 case native_scheduling_policy::deadline:
788template <
typename NativeHandle>
801 if (effective && effective->get_cpus() == affinity.get_cpus())
806 return unexpected(std::make_error_code(std::errc::state_not_recoverable));
809 return unexpected(std::make_error_code(std::errc::invalid_argument));
812template <
typename NativeHandle>
818 if (!scheduling.valid)
819 return unexpected(std::make_error_code(std::errc::invalid_argument));
833 return unexpected(std::make_error_code(std::errc::operation_not_supported));
837 return policy_result;
845template <
typename NativeHandle>
854 return unexpected(std::make_error_code(std::errc::operation_not_supported));
856 if (!policy.has_value())
857 return unexpected(std::make_error_code(std::errc::no_such_process));
861 return unexpected(std::make_error_code(std::errc::operation_not_supported));
Manages a set of CPU indices to which a thread may be bound.
auto to_string() const -> std::string
auto is_set(int cpu) const -> bool
auto get_cpus() const -> std::vector< int >
auto native_handle() const -> cpu_set_t const &
native_thread_affinity(std::vector< int > const &cpus)
auto has_cpu(int cpu) const -> bool
Value-semantic wrapper for a thread scheduling priority.
constexpr auto operator>(native_thread_priority const &other) const noexcept -> bool
static constexpr auto realtime_lowest() noexcept -> native_thread_priority
constexpr auto operator!=(native_thread_priority const &other) const noexcept -> bool
constexpr auto operator==(native_thread_priority const &other) const noexcept -> bool
static constexpr auto highest() noexcept -> native_thread_priority
static constexpr auto lowest() noexcept -> native_thread_priority
constexpr native_thread_priority(int priority=0)
constexpr auto operator>=(native_thread_priority const &other) const noexcept -> bool
constexpr auto is_valid() const noexcept -> bool
constexpr auto operator<(native_thread_priority const &other) const noexcept -> bool
static constexpr auto normal() noexcept -> native_thread_priority
constexpr auto operator<=(native_thread_priority const &other) const noexcept -> bool
static constexpr auto realtime_highest() noexcept -> native_thread_priority
constexpr auto value() const noexcept -> int
auto to_string() const -> std::string
Static utility class for constructing OS-native scheduling parameters.
static auto create_for_policy(native_scheduling_policy policy, native_thread_priority priority) -> expected< sched_param, std::error_code >
static auto get_priority_range(native_scheduling_policy policy) -> expected< int, std::error_code >
Strongly-typed nice value in the POSIX range $[-20, 19]$.
constexpr auto native(native_scheduling_policy policy, native_thread_priority priority) noexcept -> native_scheduling_config
constexpr auto interactive() noexcept -> native_scheduling_config
constexpr auto low_latency() noexcept -> native_scheduling_config
constexpr auto normal() noexcept -> native_scheduling_config
constexpr auto native_windows_priority(int priority) noexcept -> native_scheduling_config
constexpr auto realtime_rr(int priority=80) noexcept -> native_scheduling_config
constexpr auto background() noexcept -> native_scheduling_config
Aggregates multiple thread_registry_backend instances into a single queryable view.
auto read_effective_nice(NativeHandle handle, native_thread_id tid) -> expected< int, std::error_code >
native_scheduling_policy
Enumeration of available thread scheduling policies.
@ other
Standard round-robin time-sharing.
@ fifo
First in, first out.
@ batch
For batch style execution.
@ idle
For very low priority background tasks.
auto apply_affinity_checked(NativeHandle handle, native_thread_affinity const &affinity) -> expected< void, std::error_code >
constexpr auto uses_nice_value(native_scheduling_policy policy) noexcept -> bool
constexpr auto is_realtime_policy(native_scheduling_policy policy) noexcept -> bool
constexpr auto resolve_scheduling_config(native_scheduling_config const &config) noexcept -> resolved_scheduling
auto apply_scheduling_config(NativeHandle handle, native_thread_id tid, native_scheduling_config const &config) -> expected< void, std::error_code >
auto to_string(native_scheduling_policy policy) -> std::string
String conversion utilities.
@ realtime_fifo
Request POSIX FIFO realtime scheduling.
POSIX and Linux native thread-control implementation fragment.
auto read_scheduling_policy(pthread_t handle) -> std::optional< native_scheduling_policy >
auto read_affinity(pthread_t handle) -> expected< native_thread_affinity, std::error_code >
auto apply_scheduling_policy(pthread_t handle, native_scheduling_policy policy, native_thread_priority priority) -> expected< void, std::error_code >
auto apply_nice_value(pid_t tid, int nice_value) -> expected< void, std::error_code >
auto read_nice_value(pid_t tid) -> expected< int, std::error_code >
auto apply_affinity(pthread_t handle, native_thread_affinity const &affinity) -> expected< void, std::error_code >
native_thread_priority priority
native_priority_model model
native_scheduling_intent intent
native_scheduling_policy policy
std::optional< native_scheduling_config > scheduling
std::optional< native_thread_affinity > affinity
std::optional< std::string > name
native_scheduling_policy policy
native_thread_priority priority
native_priority_model model
Windows and MinGW native thread-control implementation fragment.
auto apply_windows_thread_priority(HANDLE handle, int priority) -> expected< void, std::error_code >