From patchwork Wed Mar 22 15:07:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 665899 Delivered-To: patch@linaro.org Received: by 2002:a5d:4d08:0:0:0:0:0 with SMTP id z8csp203273wrt; Wed, 22 Mar 2023 08:08:30 -0700 (PDT) X-Google-Smtp-Source: AK7set/45qJEDfOY+iysddq7oT1SMuDeS6i35TmgWB1OdikRJkORXEYoqig8eMjvlJX4EmJ6vhPK X-Received: by 2002:a05:6214:508f:b0:5b4:1d9a:75e7 with SMTP id kk15-20020a056214508f00b005b41d9a75e7mr6476382qvb.13.1679497709982; Wed, 22 Mar 2023 08:08:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1679497709; cv=none; d=google.com; s=arc-20160816; b=VqdvmGrhfCtvIrhEWdwYvRbsp/k5iyHu2rwNXZmQnudeHpH29UsQBrMVJ84xuGtYnj tvpx1sATtQd9uYM9HYa5X6i6EOICvFFXfogPdUAJDGtrjmrXs/cnUqO5Jyt8ODRaTgyi H9LLE7CekxPvc52Nwp0HRML+qA642ixe10vmRQ1VNk+nXCIn3fqe4SMvKjpHPaNyPnu4 CxS9Mf5xrYmygia/g6kdr0jEGRNqmTnn7Hutb6GYBTSqnY8VjTlKrWu8skSUJhz6zHfG v0pKspOk/I/mwIeR2TcsLtfFzmHNRXo4Mi8h60RaCbATYrfNHzAwfI/z7zW8kPp3KBIO aDrg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=NMY/vAWySJgtF4AXv2RQlxqwdk/wExvFK2+RnIza0g8=; b=NvxNBJXgDnUoVmzVCMC0IXd0Wt6YR4rLt1j0g1E1cCLDek9vXNtfwSU9cmuFugj+HC M0f7p3vRs0AvI1CpOHu8k+8TWlmzrqizrct33aoM7SUBsuexW3rPEcj47YcZjdxXcfps EJeyfM/DZAGZzAPm0NL8hzgNiT6m1LlZ4wq9mxwXi7h/OupsNiRZycLs11S25YBZDQNJ zOwKZR86PoMbSsTkLBudk0Al5cf5XGcMzQIENcXXme0jN150IL7bD/a6Lq010uj/RZt5 Zr1qzyn6NvdYK/f1gmrAegTLjtvRt4YjA7EIQQTHuB0G5U0nAplX2Qjheq+GKKXk+Hk5 HgZg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=lnhhn9gp; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id i17-20020a0cf951000000b005abf1b68250si9848084qvo.547.2023.03.22.08.08.29 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Wed, 22 Mar 2023 08:08:29 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=lnhhn9gp; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pf049-0002hL-FP; Wed, 22 Mar 2023 11:07:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pf048-0002gP-0d for qemu-devel@nongnu.org; Wed, 22 Mar 2023 11:07:52 -0400 Received: from mail-pl1-x634.google.com ([2607:f8b0:4864:20::634]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pf046-0007Fk-0A for qemu-devel@nongnu.org; Wed, 22 Mar 2023 11:07:51 -0400 Received: by mail-pl1-x634.google.com with SMTP id w4so11476142plg.9 for ; Wed, 22 Mar 2023 08:07:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1679497669; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=NMY/vAWySJgtF4AXv2RQlxqwdk/wExvFK2+RnIza0g8=; b=lnhhn9gp2CzztoUq0/u5Gsck2jBo+71aCIXsHlR8OzvmCY4SjYHlHfCZwdXt254fBD ej2tclNAbLyoVmhoZbseQ0p+0/mGFgI3VzigzDtQ8q9C0opl12mGnEiaV3TpxsNYFs25 5HkpOYVjUGrcmrSJ0OPkb290ttwo1QaWL/XlbfyctbaVhOsvLVhMQBbUFUEtmibFxooJ 9rFyWDTmrajWP/LHP4uPdT+OM1j2tnsy9Un8Zh9hrffAFGj+crTQLI4D7q6UvXnkLt4s xy3ktFj5XoK35CjiXXUBrhJyZWq00qCQAnRIiRjsDUe/X6jbuZAwmo4JWswujH4REq/c xgvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679497669; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NMY/vAWySJgtF4AXv2RQlxqwdk/wExvFK2+RnIza0g8=; b=wbgyYpyWVFt/jvdGH22YfrFYuXc9+wHvkCi/HJ4gmzu9FVNgioeAy+yk1dChkJRWkK Ynp2k2hXPOI7rnd5X6XyHgsmZighqo6sqQi5uPG2a4eFsMxoMfZdcthBzHBARcz4I1h+ S+2Wtypsp1uZYcQudZESaE56Z5ZzPdE3XMZHemHzJv5RNsnPN4HjS/gHMSOyxrkXpYRx +qoNR/FPLtKaiRNkcP/ERJwI9bZog90x3hXC1IhZUENpH0Ipw3f8sM/kN+XBTUKc7tvE it5obYkDEeGc6/RWgIF5y3DrHAczg6YRe/7N96Zd826e7wNK9TTMiF6gjxxiRz/+B/pQ nFiA== X-Gm-Message-State: AO0yUKV04rrzAnc0OC77ZQsCVCrm+BZGd4fxMa1MMRBqItrTBnEYLbtp j8lUxhYS0XRUKIO2nRsil3frBwkKCdBVgWqFoz0= X-Received: by 2002:a17:90b:3149:b0:23f:7dfb:7dc1 with SMTP id ip9-20020a17090b314900b0023f7dfb7dc1mr4139973pjb.33.1679497668696; Wed, 22 Mar 2023 08:07:48 -0700 (PDT) Received: from stoup.. (24-113-166-229.wavecable.com. [24.113.166.229]) by smtp.gmail.com with ESMTPSA id 17-20020a170902ee5100b0019339f3368asm10757555plo.3.2023.03.22.08.07.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Mar 2023 08:07:48 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Cc: cota@braap.org, peter.maydell@linaro.org, Valentin David , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= Subject: [PATCH for-8.0 02/11] tcg: use QTree instead of GTree Date: Wed, 22 Mar 2023 08:07:35 -0700 Message-Id: <20230322150744.175010-3-richard.henderson@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230322150744.175010-1-richard.henderson@linaro.org> References: <20230322150744.175010-1-richard.henderson@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::634; envelope-from=richard.henderson@linaro.org; helo=mail-pl1-x634.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org From: Emilio Cota qemu-user can hang in a multi-threaded fork. One common reason is that when creating a TB, between fork and exec we manipulate a GTree whose memory allocator (GSlice) is not fork-safe. Although POSIX does not mandate it, the system's allocator (e.g. tcmalloc, libc malloc) is probably fork-safe. Fix some of these hangs by using QTree, which uses the system's allocator regardless of the Glib version that we used at configuration time. Tested with the test program in the original bug report, i.e.: ``` void garble() { int pid = fork(); if (pid == 0) { exit(0); } else { int wstatus; waitpid(pid, &wstatus, 0); } } void supragarble(unsigned depth) { if (depth == 0) return ; std::thread a(supragarble, depth-1); std::thread b(supragarble, depth-1); garble(); a.join(); b.join(); } int main() { supragarble(10); } ``` Resolves: https://gitlab.com/qemu-project/qemu/-/issues/285 Reported-by: Valentin David Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Emilio Cota Message-Id: <20230205163758.416992-3-cota@braap.org> [rth: Add QEMU_DISABLE_CFI for all callback using functions.] Signed-off-by: Richard Henderson --- accel/tcg/tb-maint.c | 17 +++++++++-------- tcg/region.c | 19 ++++++++++--------- util/qtree.c | 8 ++++---- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c index 7246c1c46b..a173db17e6 100644 --- a/accel/tcg/tb-maint.c +++ b/accel/tcg/tb-maint.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu/interval-tree.h" +#include "qemu/qtree.h" #include "exec/cputlb.h" #include "exec/log.h" #include "exec/exec-all.h" @@ -314,7 +315,7 @@ struct page_entry { * See also: page_collection_lock(). */ struct page_collection { - GTree *tree; + QTree *tree; struct page_entry *max; }; @@ -467,7 +468,7 @@ static bool page_trylock_add(struct page_collection *set, tb_page_addr_t addr) struct page_entry *pe; PageDesc *pd; - pe = g_tree_lookup(set->tree, &index); + pe = q_tree_lookup(set->tree, &index); if (pe) { return false; } @@ -478,7 +479,7 @@ static bool page_trylock_add(struct page_collection *set, tb_page_addr_t addr) } pe = page_entry_new(pd, index); - g_tree_insert(set->tree, &pe->index, pe); + q_tree_insert(set->tree, &pe->index, pe); /* * If this is either (1) the first insertion or (2) a page whose index @@ -525,13 +526,13 @@ static struct page_collection *page_collection_lock(tb_page_addr_t start, end >>= TARGET_PAGE_BITS; g_assert(start <= end); - set->tree = g_tree_new_full(tb_page_addr_cmp, NULL, NULL, + set->tree = q_tree_new_full(tb_page_addr_cmp, NULL, NULL, page_entry_destroy); set->max = NULL; assert_no_pages_locked(); retry: - g_tree_foreach(set->tree, page_entry_lock, NULL); + q_tree_foreach(set->tree, page_entry_lock, NULL); for (index = start; index <= end; index++) { TranslationBlock *tb; @@ -542,7 +543,7 @@ static struct page_collection *page_collection_lock(tb_page_addr_t start, continue; } if (page_trylock_add(set, index << TARGET_PAGE_BITS)) { - g_tree_foreach(set->tree, page_entry_unlock, NULL); + q_tree_foreach(set->tree, page_entry_unlock, NULL); goto retry; } assert_page_locked(pd); @@ -551,7 +552,7 @@ static struct page_collection *page_collection_lock(tb_page_addr_t start, (tb_page_addr1(tb) != -1 && page_trylock_add(set, tb_page_addr1(tb)))) { /* drop all locks, and reacquire in order */ - g_tree_foreach(set->tree, page_entry_unlock, NULL); + q_tree_foreach(set->tree, page_entry_unlock, NULL); goto retry; } } @@ -562,7 +563,7 @@ static struct page_collection *page_collection_lock(tb_page_addr_t start, static void page_collection_unlock(struct page_collection *set) { /* entries are unlocked and freed via page_entry_destroy */ - g_tree_destroy(set->tree); + q_tree_destroy(set->tree); g_free(set); } diff --git a/tcg/region.c b/tcg/region.c index 88d6bb273f..bef4c4756f 100644 --- a/tcg/region.c +++ b/tcg/region.c @@ -28,6 +28,7 @@ #include "qemu/mprotect.h" #include "qemu/memalign.h" #include "qemu/cacheinfo.h" +#include "qemu/qtree.h" #include "qapi/error.h" #include "exec/exec-all.h" #include "tcg/tcg.h" @@ -36,7 +37,7 @@ struct tcg_region_tree { QemuMutex lock; - GTree *tree; + QTree *tree; /* padding to avoid false sharing is computed at run-time */ }; @@ -163,7 +164,7 @@ static void tcg_region_trees_init(void) struct tcg_region_tree *rt = region_trees + i * tree_size; qemu_mutex_init(&rt->lock); - rt->tree = g_tree_new_full(tb_tc_cmp, NULL, NULL, tb_destroy); + rt->tree = q_tree_new_full(tb_tc_cmp, NULL, NULL, tb_destroy); } } @@ -202,7 +203,7 @@ void tcg_tb_insert(TranslationBlock *tb) g_assert(rt != NULL); qemu_mutex_lock(&rt->lock); - g_tree_insert(rt->tree, &tb->tc, tb); + q_tree_insert(rt->tree, &tb->tc, tb); qemu_mutex_unlock(&rt->lock); } @@ -212,7 +213,7 @@ void tcg_tb_remove(TranslationBlock *tb) g_assert(rt != NULL); qemu_mutex_lock(&rt->lock); - g_tree_remove(rt->tree, &tb->tc); + q_tree_remove(rt->tree, &tb->tc); qemu_mutex_unlock(&rt->lock); } @@ -232,7 +233,7 @@ TranslationBlock *tcg_tb_lookup(uintptr_t tc_ptr) } qemu_mutex_lock(&rt->lock); - tb = g_tree_lookup(rt->tree, &s); + tb = q_tree_lookup(rt->tree, &s); qemu_mutex_unlock(&rt->lock); return tb; } @@ -267,7 +268,7 @@ void tcg_tb_foreach(GTraverseFunc func, gpointer user_data) for (i = 0; i < region.n; i++) { struct tcg_region_tree *rt = region_trees + i * tree_size; - g_tree_foreach(rt->tree, func, user_data); + q_tree_foreach(rt->tree, func, user_data); } tcg_region_tree_unlock_all(); } @@ -281,7 +282,7 @@ size_t tcg_nb_tbs(void) for (i = 0; i < region.n; i++) { struct tcg_region_tree *rt = region_trees + i * tree_size; - nb_tbs += g_tree_nnodes(rt->tree); + nb_tbs += q_tree_nnodes(rt->tree); } tcg_region_tree_unlock_all(); return nb_tbs; @@ -296,8 +297,8 @@ static void tcg_region_tree_reset_all(void) struct tcg_region_tree *rt = region_trees + i * tree_size; /* Increment the refcount first so that destroy acts as a reset */ - g_tree_ref(rt->tree); - g_tree_destroy(rt->tree); + q_tree_ref(rt->tree); + q_tree_destroy(rt->tree); } tcg_region_tree_unlock_all(); } diff --git a/util/qtree.c b/util/qtree.c index deb46c187f..31f0b46182 100644 --- a/util/qtree.c +++ b/util/qtree.c @@ -310,7 +310,7 @@ q_tree_node_next(QTreeNode *node) * * Since: 2.70 in GLib. Internal in Qtree, i.e. not in the public API. */ -static void +static void QEMU_DISABLE_CFI q_tree_remove_all(QTree *tree) { QTreeNode *node; @@ -532,7 +532,7 @@ q_tree_replace(QTree *tree, } /* internal insert routine */ -static QTreeNode * +static QTreeNode * QEMU_DISABLE_CFI q_tree_insert_internal(QTree *tree, gpointer key, gpointer value, @@ -721,7 +721,7 @@ q_tree_steal(QTree *tree, } /* internal remove routine */ -static gboolean +static gboolean QEMU_DISABLE_CFI q_tree_remove_internal(QTree *tree, gconstpointer key, gboolean steal) @@ -1182,7 +1182,7 @@ q_tree_node_balance(QTreeNode *node) return node; } -static QTreeNode * +static QTreeNode * QEMU_DISABLE_CFI q_tree_find_node(QTree *tree, gconstpointer key) {