dev/cpp/affinity/affinity.cpp

127 lines
3.7 KiB
C++

/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
(c) 2011 Emanuele Oriani - ema at fastwebnet dot it
*/
#include <iostream>
#include <cerrno>
#include <cstdlib>
#include <cstdio>
static pid_t pid = -1;
static int cpu = -1;
static bool reset = false;
static bool cpunum = false;
// To get the number of available CPUs we run this
// getaffinity BEFORE setting any affinity mask.
// We will get all the available CPUs.
static int num_cpus(void) {
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
const int max_cpus = 8*sizeof(cpu_set);
if (0 == sched_getaffinity(getpid(), sizeof(cpu_set_t), &cpu_set)) {
for(int i = 0; i < max_cpus; ++i)
if (!CPU_ISSET(i, &cpu_set)) return i;
}
return max_cpus;
}
const int NCPUS = num_cpus();
static void usage(const char *img) {
std::cerr << img << ", a simple program to set CPU affinity on Linux." << std::endl;
std::cerr << "(c) 2011 Emanuele Oriani - ema at fastwebnet dot it" << std::endl;
std::cerr << "\nUsage:" << std::endl;
std::cerr << " " << img << " [-p pid] [-c cpu] [-r]" << std::endl;
std::cerr << " p: specify a process pid" << std::endl;
std::cerr << " c: specify a cpu id (0-n)" << std::endl;
std::cerr << " r: reset (enable all cpus)" << std::endl;
std::cerr << " g: print cpus number" << std::endl;
}
static void opts(int argc, char *argv[]) {
extern char *optarg;
int res = -1;
while(EOF != (res = getopt(argc, argv, "p:c:rhg"))) {
switch((char)res) {
case 'p':
pid = (pid_t)std::atoi(optarg);
break;
case 'c':
cpu = std::atoi(optarg);
break;
case 'r':
reset = true;
break;
case 'g':
cpunum = true;
break;
case 'h':
default:
usage(argv[0]);
std::exit(-2);
break;
}
}
}
int main(int argc, char *argv[]) {
opts(argc, argv);
cpu_set_t cpu_set;
if (cpunum) std::cout << "Available cpus: " << NCPUS << '.' << std::endl;
if (-1 == pid) pid = getpid();
if (reset || (-1 != cpu)) {
CPU_ZERO(&cpu_set);
if (reset) {
for(int i = 0; i < NCPUS; ++i)
CPU_SET(i, &cpu_set);
}
else CPU_SET(cpu, &cpu_set);
if (-1 == sched_setaffinity(pid, sizeof(cpu_set_t), &cpu_set)) {
std::cerr << "Error : ";
switch(errno) {
case EFAULT:
std::cerr << "A supplied memory address was invalid." << std::endl;
std::exit(-1);
break;
case EINVAL:
std::cerr << "The affinity bitmask mask contains no processors that are physically on the system, or cpusetsize is smaller than the size of the affinity mask used by the kernel." << std::endl;
std::exit(-1);
break;
case EPERM:
std::cerr << "The calling process does not have appropriate privileges." << std::endl;
std::exit(-1);
break;
case ESRCH:
std::cerr << "The process whose ID is " << pid << " could not be found." << std::endl;
std::exit(-1);
break;
default:
std::cerr << "Unknown error." << std::endl;
std::exit(-1);
break;
}
}
}
CPU_ZERO(&cpu_set);
if (0 == sched_getaffinity(pid, sizeof(cpu_set_t), &cpu_set)) {
std::cout << "Report:" << std::endl;
for(int i = 0; i < NCPUS; ++i)
if (CPU_ISSET(i, &cpu_set)) std::cout << "Cpu " << i << " is set." << std::endl;
}
}