NUMA++ 0.11.0
Loading...
Searching...
No Matches
lowlevel.cpp
1/**
2 * @cond Impl
3 * @file
4 * @ingroup numapp
5 * @copyright ESO 2024 - European Southern Observatory
6 *
7 * @brief Definition of scheduler classes
8 */
9#include <cassert>
10
11#include <numa.h>
12#include <numaif.h>
13#include <sys/resource.h>
14#include <sys/syscall.h>
15#include <sys/types.h>
16#include <unistd.h>
17
18#include <numapp/lowlevel.hpp>
19
20namespace numapp::ll {
21
22#ifndef UNIT_TEST
23std::error_code
24SetSchedulerPolicy(pid_t pid, int policy, int static_priority, int dynamic_priority) NUMAPP_NOEXCEPT {
25 // Set scheduler first, and only then set nice-value if used in policy.
26 struct sched_param param = {0};
27 switch (policy) {
28 case SCHED_FIFO:
29 case SCHED_RR:
30 param.sched_priority = static_priority;
31 break;
32 default:
33 break;
34 };
35 if (sched_setscheduler(pid, policy, &param) != 0) {
36 return std::make_error_code(static_cast<std::errc>(errno));
37 }
38 switch (policy) {
39 case SCHED_BATCH:
40 case SCHED_OTHER:
41 // Note: posix spec of setpriority mandates a process-wide nice-value, whereas Linux
42 // deviates and supports a per-thread nice value.
43 if (setpriority(PRIO_PROCESS, pid, dynamic_priority) != 0) {
44 return std::make_error_code(static_cast<std::errc>(errno));
45 }
46 break;
47 default:
48 break;
49 };
50 return {};
51}
52
53std::error_code GetSchedulerPolicy(pid_t pid,
54 int* policy,
55 int* static_priority,
56 int* dynamic_priority) NUMAPP_NOEXCEPT {
57 assert(policy != nullptr);
58 assert(static_priority != nullptr);
59 assert(dynamic_priority != nullptr);
60 if (int ret = sched_getscheduler(pid); ret == -1) {
61 return std::make_error_code(static_cast<std::errc>(errno));
62 } else {
63 *policy = ret;
64 }
65 switch (*policy) {
66 case SCHED_FIFO:
67 case SCHED_RR: {
68 struct sched_param param = {0};
69 if (sched_getparam(pid, &param) != 0) {
70 return std::make_error_code(static_cast<std::errc>(errno));
71 }
72 *static_priority = param.sched_priority;
73 break;
74 }
75 case SCHED_BATCH:
76 case SCHED_OTHER: {
77 errno = 0;
78 int prio = getpriority(PRIO_PROCESS, pid);
79 // Prio can be -1 so also check errno.
80 if (errno != 0) {
81 return std::make_error_code(static_cast<std::errc>(errno));
82 }
83 *dynamic_priority = prio;
84 }
85 case SCHED_IDLE:
86 break;
87 default:
88 return std::make_error_code(std::errc::not_supported);
89 }
90 return {};
91}
92
93std::error_code GetCpuAffinity(pid_t ttid, Cpumask& mask) NUMAPP_NOEXCEPT {
94 if (numa_sched_getaffinity(ttid, mask.GetNative()) < 0) {
95 return std::make_error_code(static_cast<std::errc>(errno));
96 }
97 return {};
98}
99
100std::error_code SetCpuAffinity(pid_t ttid, Cpumask const& mask) NUMAPP_NOEXCEPT {
101 if (numa_sched_setaffinity(ttid, const_cast<Cpumask&>(mask).GetNative()) < 0) {
102 return std::make_error_code(static_cast<std::errc>(errno));
103 }
104 return {};
105}
106
107std::error_code NumaNodeToCpumask(int node, Cpumask& mask) NUMAPP_NOEXCEPT {
108 if (numa_node_to_cpus(node, mask.GetNative()) < 0) {
109 return std::make_error_code(static_cast<std::errc>(errno));
110 }
111 return {};
112}
113
114std::error_code SetMemPolicy(int mode, Nodemask const& mask) NUMAPP_NOEXCEPT {
115 if (auto err = set_mempolicy(mode, mask.GetNative()->maskp, mask.GetNative()->size + 1);
116 err != 0) {
117 return std::make_error_code(static_cast<std::errc>(errno));
118 } else {
119 return {};
120 }
121}
122
123std::error_code
124SetMemPolicy(void* addr, std::size_t len, int mode, Nodemask const& mask, unsigned flags)
125 NUMAPP_NOEXCEPT {
126 if (auto err =
127 mbind(addr, len, mode, mask.GetNative()->maskp, mask.GetNative()->size + 1, flags);
128 err != 0) {
129 return std::make_error_code(static_cast<std::errc>(errno));
130 } else {
131 return {};
132 }
133}
134
135std::error_code
136GetMemPolicy(int& mode, Nodemask& mask, void* addr, unsigned flags) NUMAPP_NOEXCEPT {
137 if (auto err =
138 get_mempolicy(&mode, mask.GetNative()->maskp, mask.GetNative()->size + 1, addr, flags);
139 err != 0) {
140 return std::make_error_code(static_cast<std::errc>(errno));
141 } else {
142 return {};
143 }
144}
145
146#endif
147
148} // namespace numapp
149/// @endcond Impl
Contains low-level functions.
Defines lowlevel functions that should not be used directly.
Definition lowlevel.hpp:24
std::error_code GetCpuAffinity(pid_t ttid, Cpumask &mask) noexcept
Get CPU affinity.
std::error_code SetMemPolicy(int mode, Nodemask const &mask) noexcept
Set active memory policy for calling thread.
std::error_code SetSchedulerPolicy(pid_t pid, int policy, int static_priority, int dynamic_priority) noexcept
A low-level, and error prone function to set policy.
std::error_code GetMemPolicy(int &mode, Nodemask &mask, void *addr, unsigned flags) noexcept
Get memory policy for calling thread or an address.
std::error_code NumaNodeToCpumask(int node, Cpumask &mask) noexcept
Convert NUMA node number to corresponding CPU mask.
std::error_code GetSchedulerPolicy(pid_t pid, int *policy, int *static_priority, int *dynamic_priority) noexcept
A low-level, and error prone function to get policy.
std::error_code SetCpuAffinity(pid_t ttid, Cpumask const &mask) noexcept
Set CPU affinity.