libxl_bitmap_init(&ptr->cpumap);
if (libxl_cpu_bitmap_alloc(ctx, &ptr->cpumap, 0))
goto err;
+ libxl_bitmap_init(&ptr->cpumap_soft);
+ if (libxl_cpu_bitmap_alloc(ctx, &ptr->cpumap_soft, 0))
+ goto err;
if (xc_vcpu_getinfo(ctx->xch, domid, *nr_vcpus_out, &vcpuinfo) == -1) {
LOGE(ERROR, "getting vcpu info");
goto err;
}
+
if (xc_vcpu_getaffinity(ctx->xch, domid, *nr_vcpus_out,
- ptr->cpumap.map, NULL,
- XEN_VCPUAFFINITY_HARD) == -1) {
+ ptr->cpumap.map, ptr->cpumap_soft.map,
+ XEN_VCPUAFFINITY_SOFT|XEN_VCPUAFFINITY_HARD) == -1) {
LOGE(ERROR, "getting vcpu affinity");
goto err;
}
err:
libxl_bitmap_dispose(&ptr->cpumap);
+ libxl_bitmap_dispose(&ptr->cpumap_soft);
free(ret);
GC_FREE;
return NULL;
}
int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid,
- libxl_bitmap *cpumap)
+ const libxl_bitmap *cpumap_hard,
+ const libxl_bitmap *cpumap_soft)
{
- if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid, cpumap->map, NULL,
- XEN_VCPUAFFINITY_HARD)) {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting vcpu affinity");
- return ERROR_FAIL;
+ GC_INIT(ctx);
+ libxl_bitmap hard, soft;
+ int rc, flags = 0;
+
+ libxl_bitmap_init(&hard);
+ libxl_bitmap_init(&soft);
+
+ if (!cpumap_hard && !cpumap_soft) {
+ rc = ERROR_INVAL;
+ goto out;
}
- return 0;
+
+ /*
+ * Xen wants writable hard and/or soft cpumaps, to put back in them
+ * the effective hard and/or soft affinity that will be used.
+ */
+ if (cpumap_hard) {
+ rc = libxl_cpu_bitmap_alloc(ctx, &hard, 0);
+ if (rc)
+ goto out;
+
+ libxl_bitmap_copy(ctx, &hard, cpumap_hard);
+ flags = XEN_VCPUAFFINITY_HARD;
+ }
+ if (cpumap_soft) {
+ rc = libxl_cpu_bitmap_alloc(ctx, &soft, 0);
+ if (rc)
+ goto out;
+
+ libxl_bitmap_copy(ctx, &soft, cpumap_soft);
+ flags |= XEN_VCPUAFFINITY_SOFT;
+ }
+
+ if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid,
+ cpumap_hard ? hard.map : NULL,
+ cpumap_soft ? soft.map : NULL,
+ flags)) {
+ LOGE(ERROR, "setting vcpu affinity");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ /*
+ * Let's check the results. Hard affinity will never be empty, but it
+ * is possible that Xen will use something different from what we asked
+ * for various reasons. If that's the case, report it.
+ */
+ if (cpumap_hard &&
+ !libxl_bitmap_equal(cpumap_hard, &hard, 0))
+ LOG(DEBUG, "New hard affinity for vcpu %d has unreachable cpus",
+ vcpuid);
+ /*
+ * Soft affinity can both be different from what asked and empty. Check
+ * for (and report) both.
+ */
+ if (cpumap_soft) {
+ if (!libxl_bitmap_equal(cpumap_soft, &soft, 0))
+ LOG(DEBUG, "New soft affinity for vcpu %d has unreachable cpus",
+ vcpuid);
+ if (libxl_bitmap_is_empty(&soft))
+ LOG(WARN, "all cpus in soft affinity of vcpu %d are unreachable."
+ " Only hard affinity will be considered for scheduling",
+ vcpuid);
+ }
+
+ rc = 0;
+ out:
+ libxl_bitmap_dispose(&hard);
+ libxl_bitmap_dispose(&soft);
+ GC_FREE;
+ return rc;
}
int libxl_set_vcpuaffinity_all(libxl_ctx *ctx, uint32_t domid,
- unsigned int max_vcpus, libxl_bitmap *cpumap)
+ unsigned int max_vcpus,
+ const libxl_bitmap *cpumap_hard,
+ const libxl_bitmap *cpumap_soft)
{
+ GC_INIT(ctx);
int i, rc = 0;
for (i = 0; i < max_vcpus; i++) {
- if (libxl_set_vcpuaffinity(ctx, domid, i, cpumap)) {
- LIBXL__LOG(ctx, LIBXL__LOG_WARNING,
- "failed to set affinity for %d", i);
+ if (libxl_set_vcpuaffinity(ctx, domid, i, cpumap_hard, cpumap_soft)) {
+ LOG(WARN, "failed to set affinity for %d", i);
rc = ERROR_FAIL;
}
}
+
+ GC_FREE;
return rc;
}
*/
#define LIBXL_HAVE_BUILDINFO_EVENT_CHANNELS 1
+/*
+ * LIBXL_HAVE_VCPUINFO_SOFT_AFFINITY indicates that a 'cpumap_soft'
+ * field (of libxl_bitmap type) is present in libxl_vcpuinfo,
+ * containing the soft affinity of a vcpu.
+ */
+#define LIBXL_HAVE_VCPUINFO_SOFT_AFFINITY 1
+
/*
* LIBXL_HAVE_DEVICE_DISK_DIRECT_IO_SAFE indicates that a
* 'direct_io_safe' field (of boolean type) is present in
int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo);
int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid,
- libxl_bitmap *cpumap);
+ const libxl_bitmap *cpumap_hard,
+ const libxl_bitmap *cpumap_soft);
int libxl_set_vcpuaffinity_all(libxl_ctx *ctx, uint32_t domid,
- unsigned int max_vcpus, libxl_bitmap *cpumap);
+ unsigned int max_vcpus,
+ const libxl_bitmap *cpumap_hard,
+ const libxl_bitmap *cpumap_soft);
+
+#if defined (LIBXL_API_VERSION) && LIBXL_API_VERSION < 0x040500
+
+#define libxl_set_vcpuaffinity(ctx, domid, vcpuid, map) \
+ libxl_set_vcpuaffinity((ctx), (domid), (vcpuid), (map), NULL)
+#define libxl_set_vcpuaffinity_all(ctx, domid, max_vcpus, map) \
+ libxl_set_vcpuaffinity_all((ctx), (domid), (max_vcpus), (map), NULL)
+
+#endif
+
int libxl_domain_set_nodeaffinity(libxl_ctx *ctx, uint32_t domid,
libxl_bitmap *nodemap);
int libxl_domain_get_nodeaffinity(libxl_ctx *ctx, uint32_t domid,
return rc;
}
libxl_domain_set_nodeaffinity(ctx, domid, &info->nodemap);
- libxl_set_vcpuaffinity_all(ctx, domid, info->max_vcpus, &info->cpumap);
+ libxl_set_vcpuaffinity_all(ctx, domid, info->max_vcpus,
+ &info->cpumap, NULL);
if (xc_domain_setmaxmem(ctx->xch, domid, info->target_memkb +
LIBXL_MAXMEM_CONSTANT) < 0) {
("blocked", bool),
("running", bool),
("vcpu_time", uint64), # total vcpu time ran (ns)
- ("cpumap", libxl_bitmap), # current cpu's affinities
+ ("cpumap", libxl_bitmap), # current hard cpu affinity
+ ("cpumap_soft", libxl_bitmap), # current soft cpu affinity
], dir=DIR_OUT)
libxl_physinfo = Struct("physinfo", [
#define libxl_for_each_set_bit(v, m) for (v = 0; v < (m).size * 8; v++) \
if (libxl_bitmap_test(&(m), v))
+/*
+ * Compares two bitmaps bit by bit, up to nr_bits or, if nr_bits is 0, up
+ * to the size of the largest bitmap. If sizes does not match, bits past the
+ * of a bitmap are considered as being 0, which matches with the semantic and
+ * implementation of libxl_bitmap_test I think().
+ *
+ * So, basically, [0,1,0] and [0,1] are considered equal, while [0,1,1] and
+ * [0,1] are different.
+ */
+static inline int libxl_bitmap_equal(const libxl_bitmap *ba,
+ const libxl_bitmap *bb,
+ int nr_bits)
+{
+ int i;
+
+ if (nr_bits == 0)
+ nr_bits = ba->size > bb->size ? ba->size * 8 : bb->size * 8;
+
+ for (i = 0; i < nr_bits; i++) {
+ if (libxl_bitmap_test(ba, i) != libxl_bitmap_test(bb, i))
+ return 0;
+ }
+ return 1;
+}
+
int libxl_cpu_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *cpumap, int max_cpus);
int libxl_node_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *nodemap,
int max_nodes);
} else {
libxl_bitmap_set_any(&vcpu_cpumap);
}
- if (libxl_set_vcpuaffinity(ctx, domid, i, &vcpu_cpumap)) {
+ if (libxl_set_vcpuaffinity(ctx, domid, i, &vcpu_cpumap, NULL)) {
fprintf(stderr, "setting affinity failed on vcpu `%d'.\n", i);
libxl_bitmap_dispose(&vcpu_cpumap);
free(vcpu_to_pcpu);
}
if (vcpuid != -1) {
- if (libxl_set_vcpuaffinity(ctx, domid, vcpuid, &cpumap) == -1) {
+ if (libxl_set_vcpuaffinity(ctx, domid, vcpuid, &cpumap, NULL)) {
fprintf(stderr, "Could not set affinity for vcpu `%u'.\n", vcpuid);
goto out;
}
}
for (i = 0; i < nb_vcpu; i++) {
if (libxl_set_vcpuaffinity(ctx, domid, vcpuinfo[i].vcpuid,
- &cpumap) == -1) {
+ &cpumap, NULL)) {
fprintf(stderr, "libxl_set_vcpuaffinity failed"
" on vcpu `%u'.\n", vcpuinfo[i].vcpuid);
}