#include "path.h"
#define _PATH_SYS_CPU "/sys/devices/system/cpu"
+#define _PATH_SYS_CPU_ONLINE _PATH_SYS_CPU "/online"
#define _PATH_SYS_CPU_RESCAN _PATH_SYS_CPU "/rescan"
#define _PATH_SYS_CPU_DISPATCH _PATH_SYS_CPU "/dispatching"
+static cpu_set_t *onlinecpus;
+static size_t maxcpus;
+
+#define is_cpu_online(cpu) (CPU_ISSET_S((cpu), CPU_ALLOC_SIZE(maxcpus), onlinecpus))
+#define num_online_cpus() (CPU_COUNT_S(CPU_ALLOC_SIZE(maxcpus), onlinecpus))
+
enum {
CMD_CPU_ENABLE = 0,
CMD_CPU_DISABLE,
{
unsigned int cpu;
int online, rc;
+ int configured = -1;
for (cpu = 0; cpu < setsize; cpu++) {
if (!CPU_ISSET(cpu, cpu_set))
printf(_("CPU %d is already disabled\n"), cpu);
continue;
}
+ if (path_exist(_PATH_SYS_CPU "/cpu%d/configure", cpu))
+ configured = path_getnum(_PATH_SYS_CPU "/cpu%d/configure", cpu);
if (enable) {
rc = path_writestr("1", _PATH_SYS_CPU "/cpu%d/online", cpu);
- if (rc == -1)
+ if ((rc == -1) && (configured == 0))
+ printf(_("CPU %d enable failed "
+ "(CPU is deconfigured)\n"), cpu);
+ else if (rc == -1)
printf(_("CPU %d enable failed (%s)\n"), cpu,
strerror(errno));
else
printf(_("CPU %d enabled\n"), cpu);
} else {
+ if (onlinecpus && num_online_cpus() == 1) {
+ printf(_("CPU %d disable failed "
+ "(last enabled CPU)\n"), cpu);
+ continue;
+ }
rc = path_writestr("0", _PATH_SYS_CPU "/cpu%d/online", cpu);
if (rc == -1)
printf(_("CPU %d disable failed (%s)\n"), cpu,
strerror(errno));
- else
+ else {
printf(_("CPU %d disabled\n"), cpu);
+ if (onlinecpus)
+ CPU_CLR(cpu, onlinecpus);
+ }
}
}
return EXIT_SUCCESS;
errx(EXIT_FAILURE, _("This system does not support rescanning of CPUs"));
if (path_writestr("1", _PATH_SYS_CPU_RESCAN) == -1)
err(EXIT_FAILURE, _("Failed to trigger rescan of CPUs"));
+ printf(_("Triggered rescan of CPUs\n"));
return EXIT_SUCCESS;
}
printf(_("CPU %d is already deconfigured\n"), cpu);
continue;
}
+ if ((current == 1) && (configure == 0) && onlinecpus &&
+ is_cpu_online(cpu)) {
+ printf(_("CPU %d deconfigure failed "
+ "(CPU is enabled)\n"), cpu);
+ continue;
+ }
if (configure) {
rc = path_writestr("1", _PATH_SYS_CPU "/cpu%d/configure", cpu);
if (rc == -1)
int main(int argc, char *argv[])
{
cpu_set_t *cpu_set;
- unsigned int ncpus;
size_t setsize;
int cmd = -1;
int c;
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- ncpus = get_max_number_of_cpus();
- if (ncpus <= 0)
+ maxcpus = get_max_number_of_cpus();
+ if (maxcpus <= 0)
errx(EXIT_FAILURE, _("cannot determine NR_CPUS; aborting"));
- setsize = CPU_ALLOC_SIZE(ncpus);
- cpu_set = CPU_ALLOC(ncpus);
+ if (path_exist(_PATH_SYS_CPU_ONLINE))
+ onlinecpus = path_cpulist(maxcpus, _PATH_SYS_CPU_ONLINE);
+ setsize = CPU_ALLOC_SIZE(maxcpus);
+ cpu_set = CPU_ALLOC(maxcpus);
if (!cpu_set)
err(EXIT_FAILURE, _("cpuset_alloc failed"));
switch (cmd) {
case CMD_CPU_ENABLE:
- return cpu_enable(cpu_set, ncpus, 1);
+ return cpu_enable(cpu_set, maxcpus, 1);
case CMD_CPU_DISABLE:
- return cpu_enable(cpu_set, ncpus, 0);
+ return cpu_enable(cpu_set, maxcpus, 0);
case CMD_CPU_CONFIGURE:
- return cpu_configure(cpu_set, ncpus, 1);
+ return cpu_configure(cpu_set, maxcpus, 1);
case CMD_CPU_DECONFIGURE:
- return cpu_configure(cpu_set, ncpus, 0);
+ return cpu_configure(cpu_set, maxcpus, 0);
case CMD_CPU_RESCAN:
return cpu_rescan();
case CMD_CPU_DISPATCH_HORIZONTAL: