From patchwork Wed Aug 24 22:17:56 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Emilio Cota X-Patchwork-Id: 9298435 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5BFF2607F0 for ; Wed, 24 Aug 2016 22:19:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2E09E2913F for ; Wed, 24 Aug 2016 22:19:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1E46129143; Wed, 24 Aug 2016 22:19:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2B50B2913F for ; Wed, 24 Aug 2016 22:19:20 +0000 (UTC) Received: from localhost ([::1]:53581 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bcgVz-00070c-Dx for patchwork-qemu-devel@patchwork.kernel.org; Wed, 24 Aug 2016 18:19:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52936) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bcgVD-0006pG-GX for qemu-devel@nongnu.org; Wed, 24 Aug 2016 18:18:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bcgUy-0004K4-UW for qemu-devel@nongnu.org; Wed, 24 Aug 2016 18:18:31 -0400 Received: from out2-smtp.messagingengine.com ([66.111.4.26]:33543) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bcgUw-0004FA-5P for qemu-devel@nongnu.org; Wed, 24 Aug 2016 18:18:16 -0400 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 3DDC6203A9; Wed, 24 Aug 2016 18:18:04 -0400 (EDT) Received: from frontend2 ([10.202.2.161]) by compute1.internal (MEProxy); Wed, 24 Aug 2016 18:18:04 -0400 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-sasl-enc:x-sasl-enc; s=mesmtp; bh=RP/s1Y2hQUSnJ01GhuuwkA2ZHo0 =; b=G7fXfs5SXLf2xhIz/35XNlOcA3wVhVUCdBzqXwvQmEwWtj/Fdlz5Pw76B2h yw6YgQyvXbH5aWyS2MDv+zqcFKMswGbhW9w6A4AktwdjElr8b4BK3Ji3ciOiXbby 9NFKvk5Nmyg7t1lwy2UGbovjbh5e8sS0EYYfYAVSEI7+WouA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-sasl-enc:x-sasl-enc; s=smtpout; bh=RP/s 1Y2hQUSnJ01GhuuwkA2ZHo0=; b=jElNOADPSNnPPo7sFOd2y3AAfQPDqFWNUKdd lkOC+eiJScnwv1B7tAcs4YuPRl5/bqBFRKIvE/sahZsN7gw4FOEiyS85Q/y6fbbJ K9Q2kG9/hPYAG75Or7uF2lFoGy13WbySEiT0S8GQpvPPBA0ortti4dmRy/OTIv4I j43wr+c= X-Sasl-enc: +W8/otjuHbLEd118V2eiJ8sdsYXaWcgimyDjWBiTpVFw 1472077083 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id E5B62CCE67; Wed, 24 Aug 2016 18:18:03 -0400 (EDT) From: "Emilio G. Cota" To: Richard Henderson Date: Wed, 24 Aug 2016 18:17:56 -0400 Message-Id: <1472077083-15022-1-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: <20160824211240.GA26546@flamenco> References: <20160824211240.GA26546@flamenco> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 66.111.4.26 Subject: [Qemu-devel] [PATCH 1/8] cpu list: convert to RCU QLIST X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mttcg@greensocs.com, peter.maydell@linaro.org, claudio.fontana@huawei.com, nikunj@linux.vnet.ibm.com, crosthwaite.peter@gmail.com, jan.kiszka@siemens.com, mark.burton@greensocs.com, a.rigo@virtualopensystems.com, qemu-devel@nongnu.org, serge.fdrv@gmail.com, pbonzini@redhat.com, bobby.prani@gmail.com, alex.bennee@linaro.org, dgilbert@redhat.com, fred.konrad@greensocs.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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) {