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