aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHu Tao <hutao@cn.fujitsu.com>2012-09-14 15:46:59 +0800
committerLaine Stump <laine@laine.org>2012-09-17 14:59:37 -0400
commitf1a43a8e4139b028257ef4ed05a81cfb5f8a8741 (patch)
treed67f4bd112448c6044bcd86c56ec706811c8dffc
parentuse virBitmap to store cpupin info (diff)
downloadlibvirt-f1a43a8e4139b028257ef4ed05a81cfb5f8a8741.tar.gz
libvirt-f1a43a8e4139b028257ef4ed05a81cfb5f8a8741.tar.bz2
libvirt-f1a43a8e4139b028257ef4ed05a81cfb5f8a8741.zip
use virBitmap to store cpu affinity info
-rw-r--r--src/lxc/lxc_controller.c23
-rw-r--r--src/qemu/qemu_driver.c62
-rw-r--r--src/qemu/qemu_process.c85
-rw-r--r--src/util/processinfo.c36
-rw-r--r--src/util/processinfo.h9
5 files changed, 84 insertions, 131 deletions
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index e5aea1171..dc45a6a04 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -493,8 +493,7 @@ static int virLXCControllerSetupCpuAffinity(virLXCControllerPtr ctrl)
{
int i, hostcpus, maxcpu = CPU_SETSIZE;
virNodeInfo nodeinfo;
- unsigned char *cpumap;
- int cpumaplen;
+ virBitmapPtr cpumap;
VIR_DEBUG("Setting CPU affinity");
@@ -507,37 +506,33 @@ static int virLXCControllerSetupCpuAffinity(virLXCControllerPtr ctrl)
if (maxcpu > hostcpus)
maxcpu = hostcpus;
- cpumaplen = VIR_CPU_MAPLEN(maxcpu);
- if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) {
- virReportOOMError();
+ cpumap = virBitmapNew(maxcpu);
+ if (!cpumap)
return -1;
- }
if (ctrl->def->cpumask) {
/* XXX why don't we keep 'cpumask' in the libvirt cpumap
* format to start with ?!?! */
for (i = 0 ; i < maxcpu && i < ctrl->def->cpumasklen ; i++)
if (ctrl->def->cpumask[i])
- VIR_USE_CPU(cpumap, i);
+ ignore_value(virBitmapSetBit(cpumap, i));
} else {
/* You may think this is redundant, but we can't assume libvirtd
* itself is running on all pCPUs, so we need to explicitly set
* the spawned LXC instance to all pCPUs if no map is given in
* its config file */
- for (i = 0 ; i < maxcpu ; i++)
- VIR_USE_CPU(cpumap, i);
+ virBitmapSetAll(cpumap);
}
- /* We are pressuming we are running between fork/exec of LXC
+ /* We are presuming we are running between fork/exec of LXC
* so use '0' to indicate our own process ID. No threads are
* running at this point
*/
- if (virProcessInfoSetAffinity(0, /* Self */
- cpumap, cpumaplen, maxcpu) < 0) {
- VIR_FREE(cpumap);
+ if (virProcessInfoSetAffinity(0 /* Self */, cpumap) < 0) {
+ virBitmapFree(cpumap);
return -1;
}
- VIR_FREE(cpumap);
+ virBitmapFree(cpumap);
return 0;
}
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e1729fa16..df3a802d8 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -92,6 +92,7 @@
#include "virnodesuspend.h"
#include "virtime.h"
#include "virtypedparam.h"
+#include "bitmap.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -3715,10 +3716,10 @@ qemudDomainPinVcpuFlags(virDomainPtr dom,
virNodeInfo nodeinfo;
int ret = -1;
qemuDomainObjPrivatePtr priv;
- bool canResetting = true;
+ bool doReset = false;
int newVcpuPinNum = 0;
virDomainVcpuPinDefPtr *newVcpuPin = NULL;
- int pcpu;
+ virBitmapPtr pcpumap = NULL;
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
VIR_DOMAIN_AFFECT_CONFIG, -1);
@@ -3754,15 +3755,16 @@ qemudDomainPinVcpuFlags(virDomainPtr dom,
maxcpu = maplen * 8;
if (maxcpu > hostcpus)
maxcpu = hostcpus;
+
+ pcpumap = virBitmapNewData(cpumap, maplen);
+ if (!pcpumap)
+ goto cleanup;
+
/* pinning to all physical cpus means resetting,
* so check if we can reset setting.
*/
- for (pcpu = 0; pcpu < hostcpus; pcpu++) {
- if ((cpumap[pcpu/8] & (1 << (pcpu % 8))) == 0) {
- canResetting = false;
- break;
- }
- }
+ if (virBitmapIsAllSet(pcpumap))
+ doReset = true;
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
@@ -3805,8 +3807,7 @@ qemudDomainPinVcpuFlags(virDomainPtr dom,
goto cleanup;
}
} else {
- if (virProcessInfoSetAffinity(priv->vcpupids[vcpu],
- cpumap, maplen, maxcpu) < 0) {
+ if (virProcessInfoSetAffinity(priv->vcpupids[vcpu], pcpumap) < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR,
_("failed to set cpu affinity for vcpu %d"),
vcpu);
@@ -3814,7 +3815,7 @@ qemudDomainPinVcpuFlags(virDomainPtr dom,
}
}
- if (canResetting) {
+ if (doReset) {
if (virDomainVcpuPinDel(vm->def, vcpu) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to delete vcpupin xml of "
@@ -3839,7 +3840,7 @@ qemudDomainPinVcpuFlags(virDomainPtr dom,
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
- if (canResetting) {
+ if (doReset) {
if (virDomainVcpuPinDel(persistentDef, vcpu) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to delete vcpupin xml of "
@@ -3879,6 +3880,7 @@ cleanup:
virCgroupFree(&cgroup_dom);
if (vm)
virDomainObjUnlock(vm);
+ virBitmapFree(pcpumap);
return ret;
}
@@ -3997,10 +3999,10 @@ qemudDomainPinEmulator(virDomainPtr dom,
virNodeInfo nodeinfo;
int ret = -1;
qemuDomainObjPrivatePtr priv;
- bool canResetting = true;
- int pcpu;
+ bool doReset = false;
int newVcpuPinNum = 0;
virDomainVcpuPinDefPtr *newVcpuPin = NULL;
+ virBitmapPtr pcpumap = NULL;
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
VIR_DOMAIN_AFFECT_CONFIG, -1);
@@ -4029,15 +4031,16 @@ qemudDomainPinEmulator(virDomainPtr dom,
maxcpu = maplen * 8;
if (maxcpu > hostcpus)
maxcpu = hostcpus;
+
+ pcpumap = virBitmapNewData(cpumap, maplen);
+ if (!pcpumap)
+ goto cleanup;
+
/* pinning to all physical cpus means resetting,
* so check if we can reset setting.
*/
- for (pcpu = 0; pcpu < hostcpus; pcpu++) {
- if ((cpumap[pcpu/8] & (1 << (pcpu % 8))) == 0) {
- canResetting = false;
- break;
- }
- }
+ if (virBitmapIsAllSet(pcpumap))
+ doReset = true;
pid = vm->pid;
@@ -4075,7 +4078,7 @@ qemudDomainPinEmulator(virDomainPtr dom,
}
}
} else {
- if (virProcessInfoSetAffinity(pid, cpumap, maplen, maxcpu) < 0) {
+ if (virProcessInfoSetAffinity(pid, pcpumap) < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
_("failed to set cpu affinity for "
"emulator threads"));
@@ -4083,7 +4086,7 @@ qemudDomainPinEmulator(virDomainPtr dom,
}
}
- if (canResetting) {
+ if (doReset) {
if (virDomainEmulatorPinDel(vm->def) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to delete emulatorpin xml of "
@@ -4110,7 +4113,7 @@ qemudDomainPinEmulator(virDomainPtr dom,
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
- if (canResetting) {
+ if (doReset) {
if (virDomainEmulatorPinDel(persistentDef) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("failed to delete emulatorpin xml of "
@@ -4137,6 +4140,7 @@ cleanup:
virCgroupFree(&cgroup_emulator);
if (cgroup_dom)
virCgroupFree(&cgroup_dom);
+ virBitmapFree(pcpumap);
if (vm)
virDomainObjUnlock(vm);
@@ -4291,10 +4295,20 @@ qemudDomainGetVcpus(virDomainPtr dom,
if (priv->vcpupids != NULL) {
for (v = 0 ; v < maxinfo ; v++) {
unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v);
+ virBitmapPtr map = NULL;
+ unsigned char *tmpmap = NULL;
+ int tmpmapLen = 0;
if (virProcessInfoGetAffinity(priv->vcpupids[v],
- cpumap, maplen, maxcpu) < 0)
+ &map, maxcpu) < 0)
goto cleanup;
+ virBitmapToData(map, &tmpmap, &tmpmapLen);
+ if (tmpmapLen > maplen)
+ tmpmapLen = maplen;
+ memcpy(cpumap, tmpmap, tmpmapLen);
+
+ VIR_FREE(tmpmap);
+ virBitmapFree(map);
}
} else {
virReportError(VIR_ERR_OPERATION_INVALID,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 4a42956e7..17e7cea5e 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1853,8 +1853,7 @@ qemuProcessInitCpuAffinity(struct qemud_driver *driver,
int ret = -1;
int i, hostcpus, maxcpu = QEMUD_CPUMASK_LEN;
virNodeInfo nodeinfo;
- unsigned char *cpumap;
- int cpumaplen;
+ virBitmapPtr cpumap;
VIR_DEBUG("Setting CPU affinity");
@@ -1867,8 +1866,8 @@ qemuProcessInitCpuAffinity(struct qemud_driver *driver,
if (maxcpu > hostcpus)
maxcpu = hostcpus;
- cpumaplen = VIR_CPU_MAPLEN(maxcpu);
- if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) {
+ cpumap = virBitmapNew(maxcpu);
+ if (!cpumap) {
virReportOOMError();
return -1;
}
@@ -1881,7 +1880,8 @@ qemuProcessInitCpuAffinity(struct qemud_driver *driver,
int cur_ncpus = driver->caps->host.numaCell[i]->ncpus;
if (nodemask[i]) {
for (j = 0; j < cur_ncpus; j++)
- VIR_USE_CPU(cpumap, driver->caps->host.numaCell[i]->cpus[j]);
+ ignore_value(virBitmapSetBit(cpumap,
+ driver->caps->host.numaCell[i]->cpus[j]));
}
}
} else {
@@ -1891,14 +1891,13 @@ qemuProcessInitCpuAffinity(struct qemud_driver *driver,
* format to start with ?!?! */
for (i = 0 ; i < maxcpu && i < vm->def->cpumasklen ; i++)
if (vm->def->cpumask[i])
- VIR_USE_CPU(cpumap, i);
+ ignore_value(virBitmapSetBit(cpumap, i));
} else {
/* You may think this is redundant, but we can't assume libvirtd
* itself is running on all pCPUs, so we need to explicitly set
* the spawned QEMU instance to all pCPUs if no map is given in
* its config file */
- for (i = 0 ; i < maxcpu ; i++)
- VIR_USE_CPU(cpumap, i);
+ virBitmapSetAll(cpumap);
}
}
@@ -1906,14 +1905,13 @@ qemuProcessInitCpuAffinity(struct qemud_driver *driver,
* so use '0' to indicate our own process ID. No threads are
* running at this point
*/
- if (virProcessInfoSetAffinity(0, /* Self */
- cpumap, cpumaplen, maxcpu) < 0)
+ if (virProcessInfoSetAffinity(0 /* Self */, cpumap) < 0)
goto cleanup;
ret = 0;
cleanup:
- VIR_FREE(cpumap);
+ virBitmapFree(cpumap);
return ret;
}
@@ -1958,10 +1956,7 @@ qemuProcessSetVcpuAffinites(virConnectPtr conn,
qemuDomainObjPrivatePtr priv = vm->privateData;
virDomainDefPtr def = vm->def;
virNodeInfo nodeinfo;
- pid_t vcpupid;
- virBitmapPtr cpumask;
- int vcpu, cpumaplen, hostcpus, maxcpu, n;
- unsigned char *cpumap = NULL;
+ int vcpu, n;
int ret = -1;
if (virNodeGetInfo(conn, &nodeinfo) != 0) {
@@ -1977,41 +1972,17 @@ qemuProcessSetVcpuAffinites(virConnectPtr conn,
return -1;
}
- hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
- cpumaplen = VIR_CPU_MAPLEN(hostcpus);
- maxcpu = cpumaplen * 8;
-
- if (maxcpu > hostcpus)
- maxcpu = hostcpus;
-
- if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) {
- virReportOOMError();
- return -1;
- }
-
for (n = 0; n < def->cputune.nvcpupin; n++) {
- int i;
vcpu = def->cputune.vcpupin[n]->vcpuid;
- memset(cpumap, 0, cpumaplen);
- cpumask = def->cputune.vcpupin[n]->cpumask;
- vcpupid = priv->vcpupids[vcpu];
-
- i = -1;
- while ((i = virBitmapNextSetBit(cpumask, i)) >= 0)
- VIR_USE_CPU(cpumap, i);
-
- if (virProcessInfoSetAffinity(vcpupid,
- cpumap,
- cpumaplen,
- maxcpu) < 0) {
+ if (virProcessInfoSetAffinity(priv->vcpupids[vcpu],
+ def->cputune.vcpupin[n]->cpumask) < 0) {
goto cleanup;
}
}
ret = 0;
cleanup:
- VIR_FREE(cpumap);
return ret;
}
@@ -2021,13 +1992,8 @@ qemuProcessSetEmulatorAffinites(virConnectPtr conn,
virDomainObjPtr vm)
{
virDomainDefPtr def = vm->def;
- pid_t pid = vm->pid;
- virBitmapPtr cpumask = NULL;
- unsigned char *cpumap = NULL;
virNodeInfo nodeinfo;
- int cpumaplen, hostcpus, maxcpu, i;
int ret = -1;
- bool result;
if (virNodeGetInfo(conn, &nodeinfo) != 0)
return -1;
@@ -2035,36 +2001,13 @@ qemuProcessSetEmulatorAffinites(virConnectPtr conn,
if (!def->cputune.emulatorpin)
return 0;
- hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
- cpumaplen = VIR_CPU_MAPLEN(hostcpus);
- maxcpu = cpumaplen * CHAR_BIT;
-
- if (maxcpu > hostcpus)
- maxcpu = hostcpus;
-
- if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) {
- virReportOOMError();
- return -1;
- }
-
- cpumask = def->cputune.emulatorpin->cpumask;
- for (i = 0; i < VIR_DOMAIN_CPUMASK_LEN; i++) {
- if (virBitmapGetBit(cpumask, i, &result) < 0)
- goto cleanup;
- if (result)
- VIR_USE_CPU(cpumap, i);
- }
-
- if (virProcessInfoSetAffinity(pid,
- cpumap,
- cpumaplen,
- maxcpu) < 0) {
+ if (virProcessInfoSetAffinity(vm->pid,
+ def->cputune.emulatorpin->cpumask) < 0) {
goto cleanup;
}
ret = 0;
cleanup:
- VIR_FREE(cpumap);
return ret;
}
diff --git a/src/util/processinfo.c b/src/util/processinfo.c
index 16ab8af63..7af95e6fb 100644
--- a/src/util/processinfo.c
+++ b/src/util/processinfo.c
@@ -30,12 +30,10 @@
#if HAVE_SCHED_GETAFFINITY
-int virProcessInfoSetAffinity(pid_t pid,
- const unsigned char *map,
- size_t maplen,
- int maxcpu)
+int virProcessInfoSetAffinity(pid_t pid, virBitmapPtr map)
{
int i;
+ bool set = false;
# ifdef CPU_ALLOC
/* New method dynamically allocates cpu mask, allowing unlimted cpus */
int numcpus = 1024;
@@ -59,8 +57,10 @@ realloc:
}
CPU_ZERO_S(masklen, mask);
- for (i = 0 ; i < maxcpu ; i++) {
- if (VIR_CPU_USABLE(map, maplen, 0, i))
+ for (i = 0 ; i < virBitmapSize(map); i++) {
+ if (virBitmapGetBit(map, i, &set) < 0)
+ return -1;
+ if (set)
CPU_SET_S(i, masklen, mask);
}
@@ -81,8 +81,10 @@ realloc:
cpu_set_t mask;
CPU_ZERO(&mask);
- for (i = 0 ; i < maxcpu ; i++) {
- if (VIR_CPU_USABLE(map, maplen, 0, i))
+ for (i = 0 ; i < virBitmapSize(map); i++) {
+ if (virBitmapGetBit(map, i, &set) < 0)
+ return -1;
+ if (set)
CPU_SET(i, &mask);
}
@@ -97,8 +99,7 @@ realloc:
}
int virProcessInfoGetAffinity(pid_t pid,
- unsigned char *map,
- size_t maplen ATTRIBUTE_UNUSED,
+ virBitmapPtr *map,
int maxcpu)
{
int i;
@@ -137,9 +138,15 @@ realloc:
return -1;
}
+ *map = virBitmapNew(maxcpu);
+ if (!map) {
+ virReportOOMError();
+ return -1;
+ }
+
for (i = 0 ; i < maxcpu ; i++)
if (CPU_ISSET_S(i, masklen, mask))
- VIR_USE_CPU(map, i);
+ ignore_value(virBitmapSetBit(*map, i));
CPU_FREE(mask);
# else
/* Legacy method uses a fixed size cpu mask, only allows upto 1024 cpus */
@@ -163,9 +170,7 @@ realloc:
#else /* HAVE_SCHED_GETAFFINITY */
int virProcessInfoSetAffinity(pid_t pid ATTRIBUTE_UNUSED,
- const unsigned char *map ATTRIBUTE_UNUSED,
- size_t maplen ATTRIBUTE_UNUSED,
- int maxcpu ATTRIBUTE_UNUSED)
+ virBitmapPtr map ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s",
_("Process CPU affinity is not supported on this platform"));
@@ -173,8 +178,7 @@ int virProcessInfoSetAffinity(pid_t pid ATTRIBUTE_UNUSED,
}
int virProcessInfoGetAffinity(pid_t pid ATTRIBUTE_UNUSED,
- unsigned char *map ATTRIBUTE_UNUSED,
- size_t maplen ATTRIBUTE_UNUSED,
+ virBitmapPtr *map ATTRIBUTE_UNUSED,
int maxcpu ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s",
diff --git a/src/util/processinfo.h b/src/util/processinfo.h
index a648bb8f8..04246437d 100644
--- a/src/util/processinfo.h
+++ b/src/util/processinfo.h
@@ -23,15 +23,12 @@
# define __VIR_PROCESSINFO_H__
# include "internal.h"
+# include "bitmap.h"
-int virProcessInfoSetAffinity(pid_t pid,
- const unsigned char *map,
- size_t maplen,
- int maxcpu);
+int virProcessInfoSetAffinity(pid_t pid, virBitmapPtr map);
int virProcessInfoGetAffinity(pid_t pid,
- unsigned char *map,
- size_t maplen,
+ virBitmapPtr *map,
int maxcpu);
#endif /* __VIR_PROCESSINFO_H__ */