From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33130) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZTfZ9-000736-8p for qemu-devel@nongnu.org; Sun, 23 Aug 2015 20:24:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZTfZ6-0000n7-Tc for qemu-devel@nongnu.org; Sun, 23 Aug 2015 20:24:47 -0400 Received: from out4-smtp.messagingengine.com ([66.111.4.28]:34404) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZTfZ6-0000ml-Cr for qemu-devel@nongnu.org; Sun, 23 Aug 2015 20:24:44 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.nyi.internal (Postfix) with ESMTP id 444DE20A18 for ; Sun, 23 Aug 2015 20:24:44 -0400 (EDT) From: "Emilio G. Cota" Date: Sun, 23 Aug 2015 20:24:01 -0400 Message-Id: <1440375847-17603-33-git-send-email-cota@braap.org> In-Reply-To: <1440375847-17603-1-git-send-email-cota@braap.org> References: <1440375847-17603-1-git-send-email-cota@braap.org> Subject: [Qemu-devel] [RFC 32/38] cpu list: convert to RCU QLIST List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org, mttcg@listserver.greensocs.com Cc: mark.burton@greensocs.com, a.rigo@virtualopensystems.com, guillaume.delbergue@greensocs.com, pbonzini@redhat.com, alex.bennee@linaro.org, Frederic Konrad 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 --- exec.c | 16 ++++++++++++++-- include/qom/cpu.h | 15 +++++++-------- linux-user/main.c | 2 +- linux-user/syscall.c | 2 +- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/exec.c b/exec.c index ae6f416..58cd096 100644 --- a/exec.c +++ b/exec.c @@ -87,7 +87,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; @@ -596,7 +596,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) cpu_list_unlock(); #endif diff --git a/include/qom/cpu.h b/include/qom/cpu.h index f383c24..ab484be 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -30,6 +30,7 @@ #include "qemu/seqlock.h" #include "qemu/thread.h" #include "qemu/typedefs.h" +#include "qemu/rcu_queue.h" typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size, void *opaque); @@ -300,7 +301,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; @@ -338,15 +339,13 @@ struct CPUState { volatile sig_atomic_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 98ebe19..3e10bd8 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -121,7 +121,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, thread_cpu, node); + QLIST_REMOVE_RCU(thread_cpu, node); } } pending_cpus = 0; diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 732936f..e166313 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -5604,7 +5604,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(cpu, node); cpu_list_unlock(); ts = cpu->opaque; if (ts->child_tidptr) { -- 1.9.1