[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/8] cpu list: convert to RCU QLIST
From: |
Emilio G. Cota |
Subject: |
[Qemu-devel] [PATCH 1/8] cpu list: convert to RCU QLIST |
Date: |
Wed, 24 Aug 2016 18:17:56 -0400 |
This avoids the chance of reading a corrupted list of CPUs in usermode.
Note: this breaks hw/ppc/spapr due to the removal of CPU_FOREACH_REVERSE.
Signed-off-by: Emilio G. Cota <address@hidden>
---
cpus.c | 2 +-
exec.c | 18 +++++++++++++++---
include/qom/cpu.h | 16 +++++++---------
linux-user/main.c | 2 +-
linux-user/syscall.c | 2 +-
5 files changed, 25 insertions(+), 15 deletions(-)
diff --git a/cpus.c b/cpus.c
index a01bbbd..bc573be 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1177,7 +1177,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
}
}
- qemu_tcg_wait_io_event(QTAILQ_FIRST(&cpus));
+ qemu_tcg_wait_io_event(first_cpu);
CPU_FOREACH(cpu) {
if (cpu->unplug && !cpu_can_run(cpu)) {
remove_cpu = cpu;
diff --git a/exec.c b/exec.c
index 806e2fe..70dd869 100644
--- a/exec.c
+++ b/exec.c
@@ -93,7 +93,7 @@ static MemoryRegion io_mem_unassigned;
#endif
-struct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus);
+struct CPUTailQ cpus = QLIST_HEAD_INITIALIZER(cpus);
/* current CPU in the current thread. It is only valid inside
cpu_exec() */
__thread CPUState *current_cpu;
@@ -651,7 +651,7 @@ void cpu_exec_exit(CPUState *cpu)
return;
}
- QTAILQ_REMOVE(&cpus, cpu, node);
+ QLIST_REMOVE_RCU(cpu, node);
cpu_release_index(cpu);
cpu->cpu_index = -1;
#if defined(CONFIG_USER_ONLY)
@@ -703,7 +703,19 @@ void cpu_exec_init(CPUState *cpu, Error **errp)
#endif
return;
}
- QTAILQ_INSERT_TAIL(&cpus, cpu, node);
+ /* poor man's QLIST_INSERT_TAIL_RCU */
+ if (QLIST_EMPTY_RCU(&cpus)) {
+ QLIST_INSERT_HEAD_RCU(&cpus, cpu, node);
+ } else {
+ CPUState *some_cpu;
+
+ CPU_FOREACH(some_cpu) {
+ if (QLIST_NEXT_RCU(some_cpu, node) == NULL) {
+ QLIST_INSERT_AFTER_RCU(some_cpu, cpu, node);
+ break;
+ }
+ }
+ }
#if defined(CONFIG_USER_ONLY)
(void) cc;
cpu_list_unlock();
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 32f3af3..eba48ed 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -24,7 +24,7 @@
#include "disas/bfd.h"
#include "exec/hwaddr.h"
#include "exec/memattrs.h"
-#include "qemu/queue.h"
+#include "qemu/rcu_queue.h"
#include "qemu/thread.h"
typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
@@ -319,7 +319,7 @@ struct CPUState {
struct GDBRegisterState *gdb_regs;
int gdb_num_regs;
int gdb_num_g_regs;
- QTAILQ_ENTRY(CPUState) node;
+ QLIST_ENTRY(CPUState) node;
/* ice debug support */
QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints;
@@ -362,15 +362,13 @@ struct CPUState {
uint32_t tcg_exit_req;
};
-QTAILQ_HEAD(CPUTailQ, CPUState);
+QLIST_HEAD(CPUTailQ, CPUState);
extern struct CPUTailQ cpus;
-#define CPU_NEXT(cpu) QTAILQ_NEXT(cpu, node)
-#define CPU_FOREACH(cpu) QTAILQ_FOREACH(cpu, &cpus, node)
+#define CPU_NEXT(cpu) QLIST_NEXT_RCU(cpu, node)
+#define CPU_FOREACH(cpu) QLIST_FOREACH_RCU(cpu, &cpus, node)
#define CPU_FOREACH_SAFE(cpu, next_cpu) \
- QTAILQ_FOREACH_SAFE(cpu, &cpus, node, next_cpu)
-#define CPU_FOREACH_REVERSE(cpu) \
- QTAILQ_FOREACH_REVERSE(cpu, &cpus, CPUTailQ, node)
-#define first_cpu QTAILQ_FIRST(&cpus)
+ QLIST_FOREACH_SAFE_RCU(cpu, &cpus, node, next_cpu)
+#define first_cpu QLIST_FIRST_RCU(&cpus)
extern __thread CPUState *current_cpu;
diff --git a/linux-user/main.c b/linux-user/main.c
index f2f7422..9880505 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -131,7 +131,7 @@ void fork_end(int child)
Discard information about the parent threads. */
CPU_FOREACH_SAFE(cpu, next_cpu) {
if (cpu != thread_cpu) {
- QTAILQ_REMOVE(&cpus, cpu, node);
+ QLIST_REMOVE_RCU(cpu, node);
}
}
pending_cpus = 0;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 1c17b74..2911319 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6710,7 +6710,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
cpu_list_lock();
/* Remove the CPU from the list. */
- QTAILQ_REMOVE(&cpus, cpu, node);
+ QLIST_REMOVE_RCU(cpu, node);
cpu_list_unlock();
ts = cpu->opaque;
if (ts->child_tidptr) {
--
2.5.0
- Re: [Qemu-devel] MTTCG status updates, benchmark results and KVM forum plans, (continued)
- Re: [Qemu-devel] MTTCG status updates, benchmark results and KVM forum plans, Peter Maydell, 2016/08/15
- Re: [Qemu-devel] MTTCG status updates, benchmark results and KVM forum plans, Emilio G. Cota, 2016/08/15
- [Qemu-devel] [PATCH] aarch64: use TSX for ldrex/strex, Emilio G. Cota, 2016/08/15
- Re: [Qemu-devel] [PATCH] aarch64: use TSX for ldrex/strex, Richard Henderson, 2016/08/17
- Re: [Qemu-devel] [PATCH] aarch64: use TSX for ldrex/strex, Emilio G. Cota, 2016/08/17
- Re: [Qemu-devel] [PATCH] aarch64: use TSX for ldrex/strex, Emilio G. Cota, 2016/08/17
- Re: [Qemu-devel] [PATCH] aarch64: use TSX for ldrex/strex, Richard Henderson, 2016/08/17
- Re: [Qemu-devel] [PATCH] aarch64: use TSX for ldrex/strex, Richard Henderson, 2016/08/18
- Re: [Qemu-devel] [PATCH] aarch64: use TSX for ldrex/strex, Emilio G. Cota, 2016/08/24
- [Qemu-devel] [PATCH 1/8] cpu list: convert to RCU QLIST,
Emilio G. Cota <=
- [Qemu-devel] [PATCH 3/8] rcu: add rcu_read_lock_held(), Emilio G. Cota, 2016/08/24
- [Qemu-devel] [PATCH 7/8] htm: add powerpc64 intrinsics, Emilio G. Cota, 2016/08/24
- [Qemu-devel] [PATCH 6/8] htm: add header to abstract Hardware Transactional Memory intrinsics, Emilio G. Cota, 2016/08/24
- [Qemu-devel] [PATCH 8/8] target-arm/a64: use HTM with stop-the-world fall-back path, Emilio G. Cota, 2016/08/24
- [Qemu-devel] [PATCH 2/8] cpu-exec: remove tb_lock from hot path, Emilio G. Cota, 2016/08/24
- [Qemu-devel] [PATCH 4/8] target-arm: helper fixup for paired atomics, Emilio G. Cota, 2016/08/24
- [Qemu-devel] [PATCH 5/8] linux-user: add stop-the-world to be called from CPU loop, Emilio G. Cota, 2016/08/24
Re: [Qemu-devel] MTTCG status updates, benchmark results and KVM forum plans, Alex Bennée, 2016/08/16