127 lines
3.7 KiB
C++
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;
|
||
|
}
|
||
|
}
|