[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/3] add some vcpu-pin related functions.
From: |
Benyu Xu |
Subject: |
[Qemu-devel] [PATCH 1/3] add some vcpu-pin related functions. |
Date: |
Sat, 1 Jul 2017 22:57:08 +0800 |
Signed-off-by: Benyu Xu <address@hidden>
---
cpus.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/qom/cpu.h | 9 ++++
include/sysemu/cpus.h | 2 +
3 files changed, 137 insertions(+)
diff --git a/cpus.c b/cpus.c
index 14bb8d5..40c3abf 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1648,6 +1648,132 @@ void cpu_remove(CPUState *cpu)
qemu_cpu_kick(cpu);
}
+int get_pcpu_num(bool pin_auto, int *pcpu_id_array)
+{
+ int pcpu_num = 0;
+#ifdef _GNU_SOURCE
+ int pcpu_range = 1024;
+ int pcpu_id = 0;
+ int ret;
+ cpu_set_t *pcpu_set;
+ size_t setsize;
+
+ pcpu_set = CPU_ALLOC(pcpu_range);
+ if (pcpu_set == NULL) {
+ pcpu_num = -1;
+ return pcpu_num;
+ }
+
+ setsize = CPU_ALLOC_SIZE(pcpu_range);
+
+ for ( ; ; ) {
+ CPU_ZERO_S(setsize, pcpu_set);
+ ret = sched_getaffinity(0, setsize, pcpu_set);
+ if (ret < 0 && errno == EINVAL && pcpu_range < 131072) {
+ CPU_FREE(pcpu_set);
+ pcpu_range *= 2;
+ pcpu_set = CPU_ALLOC(pcpu_range);
+ if (pcpu_set == NULL) {
+ pcpu_num = -1;
+ return pcpu_num;
+ }
+ setsize = CPU_ALLOC_SIZE(pcpu_range);
+ continue;
+ }
+
+ if (ret == 0) {
+ for ( ; pcpu_id < 131072; pcpu_id++) {
+ if (CPU_ISSET_S(pcpu_id, setsize, pcpu_set)) {
+ pcpu_num++;
+ if (pin_auto == true) {
+ pcpu_id_array[0] = pcpu_num;
+ pcpu_id_array[pcpu_num] = pcpu_id;
+ }
+ }
+ }
+ CPU_FREE(pcpu_set);
+ return pcpu_num;
+ }
+ CPU_FREE(pcpu_set);
+ }
+#else
+ pcpu_num = -2;
+ return pcpu_num;
+#endif
+}
+
+void cpu_pin(CPUState *cpu, int pcpu_id)
+{
+ cpu_set_t *pcpu_id_mask;
+ size_t masksize;
+ pid_t vcpu_pid;
+ int num_cpus;
+
+ if (pcpu_id == 0) {
+ num_cpus = pcpu_id + 1;
+ } else {
+ num_cpus = pcpu_id;
+ }
+
+ pcpu_id_mask = CPU_ALLOC(num_cpus);
+ if (pcpu_id_mask == NULL) {
+ error_report("warning: can not alloc cpu set! pcpu #%d",
+ pcpu_id);
+ return ;
+ }
+ masksize = CPU_ALLOC_SIZE(num_cpus);
+ CPU_ZERO_S(masksize, pcpu_id_mask);
+ CPU_SET_S(pcpu_id, masksize, pcpu_id_mask);
+
+ vcpu_pid = cpu->thread_id;
+
+ if (sched_setaffinity(vcpu_pid, masksize, pcpu_id_mask) != 0) {
+ error_report("warning: set affinity failed! vcpu pid=%d, pcpu #%d",
+ vcpu_pid, pcpu_id);
+ CPU_FREE(pcpu_id_mask);
+ return ;
+ }
+
+ if (sched_getaffinity(vcpu_pid, masksize, pcpu_id_mask) != 0) {
+ error_report("warning: get affinity failed! vcpu pid=%d, pcpu #%d",
+ vcpu_pid, pcpu_id);
+ CPU_FREE(pcpu_id_mask);
+ return ;
+ }
+
+ CPU_FREE(pcpu_id_mask);
+}
+
+/* *
+ * pcpu_id_array: content the host processor's id array to pin
+ * pcpu_id_array[0]: the processor count
+ * pcpu_id_array[1...]: the processor id to pin
+ * */
+void pin_all_vcpus(int smp_cpus_num, const int *pcpu_id_array, Error **errp)
+{
+ int pcpu_id = 0;
+ int pcpu_num = pcpu_id_array[0];
+ int vcpu_id = 0;
+ CPUState *cpu;
+
+ if (pcpu_num <= 0) {
+ return;
+ }
+
+ if (smp_cpus_num > pcpu_num) {
+ error_setg(errp,
+ "pcpu id list only has %d pcpu(s), less than smp_cpus_num %d",
+ pcpu_num, smp_cpus_num);
+ return;
+ }
+
+ CPU_FOREACH(cpu) {
+ pcpu_id = pcpu_id_array[vcpu_id + 1];
+ cpu_pin(cpu, pcpu_id);
+ vcpu_id++;
+ }
+}
+
void cpu_remove_sync(CPUState *cpu)
{
cpu_remove(cpu);
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 89ddb68..8f14295 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -869,6 +869,15 @@ void cpu_exit(CPUState *cpu);
void cpu_resume(CPUState *cpu);
/**
+ * cpu_pin:
+ * @cpu: The vitual CPU to pin.
+ * @pcpu_id: The host's physical or logical processor's id.
+ *
+ * pin CPU, i.e. set the CPU's affinity.
+ */
+void cpu_pin(CPUState *cpu, int pcpu_id);
+
+/**
* cpu_remove:
* @cpu: The CPU to remove.
*
diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h
index 731756d..513a0c6 100644
--- a/include/sysemu/cpus.h
+++ b/include/sysemu/cpus.h
@@ -7,6 +7,8 @@
bool qemu_in_vcpu_thread(void);
void qemu_init_cpu_loop(void);
void resume_all_vcpus(void);
+int get_pcpu_num(bool pin_default, int *pcpu_id_array);
+void pin_all_vcpus(int smp_cpu_num, const int *pcpu_id_array, Error **errp);
void pause_all_vcpus(void);
void cpu_stop_current(void);
void cpu_ticks_init(void);
--
1.8.3.1