Received: by 2002:a05:7412:8d10:b0:f3:1519:9f41 with SMTP id bj16csp2629875rdb; Fri, 8 Dec 2023 14:06:43 -0800 (PST) X-Google-Smtp-Source: AGHT+IHFupkvCMynDYSb7VTUXaCdc697cgaOZ6hpMg6QKPIsVlk1X/p0FdhU4g+JegZhmDPPx0yb X-Received: by 2002:a17:90a:684e:b0:286:6cc1:2cc0 with SMTP id e14-20020a17090a684e00b002866cc12cc0mr722736pjm.74.1702073203531; Fri, 08 Dec 2023 14:06:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1702073203; cv=none; d=google.com; s=arc-20160816; b=Evpx35L+D+a7sA8pHeaoCYAjrvwGHDaYODD5SJDiJ+LnwkOjRkP13NJdnflwn4Q9Kq OMTXkOhFcADOUxdAw86E2tpCWjo9LMcAPCnnSfzcy0c/7ultHFC8bchXjuNVq+YFKMj8 CiGNuXvZ3KVpJWeIkAUDDqq05YHNx8AJcC/PRLiE98ENPOfNANOsR9Hlmqh3TcY6WkxP K6HUesmyJIa95de3bpJWM3wld5tt/nSdXBkpva/SAlNbjiPddxb4OZkJ/oMbounbIYYd 0udnnkgr6n9sVq7IZ5uV5OJX7CO7GvOCx6kXlWglHqCdgK/Y+KxdUi7kUrk4qNeieK4p DDfQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=FDr+17Y2V04UNhgKomw+j1ldjACcpn9xX1Zj7UWo4nE=; fh=ruOaVEkAbEh3t4sLFZXGQmBwM4c1/V/LLnMggyZGb4c=; b=FRM/gZ2azKgFZCxT165iTZ2OckyoLPjKLG0VdjwssCioDI5sEcCXK4O0/GmRoO0KJY bsTwFLaGdTmDLmq4OXnPW38DrCay5CtD2/kxc59ZT5pe/1v5HdHnFY2N5ejTWf/Hz3rX 3zC+KukGwu8uHD18D5ZvMIFI1aUHBesc5Edsy10dhFJqcz869HIhy75qpS7PgE9FnVH2 id2E/CQF3hnxjSA6vwM96qdrwN7qq2pTCit36T+RERAXfAU1J3Aqw8k5NmGdmofE2qBv G6KuYKTnpD7YdQyymCmX8mc3Fncp71QYPqOyXKSOIPps+iFuTHRXzzPJsjD6g+Lk6Vrs V5iw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=LM2juQ6E; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from snail.vger.email (snail.vger.email. [2620:137:e000::3:7]) by mx.google.com with ESMTPS id x64-20020a17090a6c4600b0028718591fc7si3480020pjj.136.2023.12.08.14.06.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 08 Dec 2023 14:06:43 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) client-ip=2620:137:e000::3:7; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=LM2juQ6E; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by snail.vger.email (Postfix) with ESMTP id 3A18C81068CF; Fri, 8 Dec 2023 14:06:24 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at snail.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1574860AbjLHWGL (ORCPT + 99 others); Fri, 8 Dec 2023 17:06:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41424 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1574872AbjLHWFw (ORCPT ); Fri, 8 Dec 2023 17:05:52 -0500 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9FB2210E0 for ; Fri, 8 Dec 2023 14:05:58 -0800 (PST) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 18B5AC433CA; Fri, 8 Dec 2023 22:05:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1702073158; bh=qpg9fNbGNVyk64uMzemypMgJeLqksx8712MtUIEzckQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LM2juQ6EmRrOhvmyxHcXE3u2bwlmf2LzZdDUGrE5xSqLOVXm54u1x1In7oUrGl6oT c9G0m8dOHtHGQDbm0FUaYZQp8gANhIj15K6wJzxHBiCj4kYxvfHGQZA66ALO4rfqdf XXD8u+yq8Wd4uuahIMkSI8AZPHQHzP3sfI0wHaW8ne8VD7r7rvFqPITcqs1NCsnpe9 z4Sy9vQjMsCAyZqrPaor5wHUA4J6uduTMXEACDNVy7qYIBIdUD7evm9w5PMFuk4EaX ry/xrNwEj7c0JQgnfWcEE5EeJ0TS+Z0aDZx/OtcVjhH8XevhLnsXLacLB02Tv/YCVM 9/P2mxaJgYV/Q== From: Frederic Weisbecker To: LKML Cc: Frederic Weisbecker , Boqun Feng , Joel Fernandes , Neeraj Upadhyay , "Paul E . McKenney" , Uladzislau Rezki , Zqiang , rcu Subject: [PATCH 2/8] rcu/nocb: Re-arrange call_rcu() NOCB specific code Date: Fri, 8 Dec 2023 23:05:39 +0100 Message-ID: <20231208220545.7452-3-frederic@kernel.org> X-Mailer: git-send-email 2.42.1 In-Reply-To: <20231208220545.7452-1-frederic@kernel.org> References: <20231208220545.7452-1-frederic@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (snail.vger.email [0.0.0.0]); Fri, 08 Dec 2023 14:06:24 -0800 (PST) Currently the call_rcu() function interleaves NOCB and !NOCB enqueue code in a complicated way such that: * The bypass enqueue code may or may not have enqueued and may or may not have locked the ->nocb_lock. Everything that follows is in a Schrödinger locking state for the unwary reviewer's eyes. * The was_alldone is always set but only used in NOCB related code. * The NOCB wake up is distantly related to the locking hopefully performed by the bypass enqueue code that did not enqueue on the bypass list. Unconfuse the whole and gather NOCB and !NOCB specific enqueue code to their own functions. Signed-off-by: Frederic Weisbecker --- kernel/rcu/tree.c | 44 +++++++++++++++++++----------------------- kernel/rcu/tree.h | 5 ++--- kernel/rcu/tree_nocb.h | 18 ++++++++++++++--- 3 files changed, 37 insertions(+), 30 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 74159c6d3bdf..82f8130d3fe3 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -2559,12 +2559,26 @@ static int __init rcu_spawn_core_kthreads(void) return 0; } +static void rcutree_enqueue(struct rcu_data *rdp, struct rcu_head *head, rcu_callback_t func) +{ + rcu_segcblist_enqueue(&rdp->cblist, head); + if (__is_kvfree_rcu_offset((unsigned long)func)) + trace_rcu_kvfree_callback(rcu_state.name, head, + (unsigned long)func, + rcu_segcblist_n_cbs(&rdp->cblist)); + else + trace_rcu_callback(rcu_state.name, head, + rcu_segcblist_n_cbs(&rdp->cblist)); + trace_rcu_segcb_stats(&rdp->cblist, TPS("SegCBQueued")); +} + /* * Handle any core-RCU processing required by a call_rcu() invocation. */ -static void __call_rcu_core(struct rcu_data *rdp, struct rcu_head *head, - unsigned long flags) +static void call_rcu_core(struct rcu_data *rdp, struct rcu_head *head, + rcu_callback_t func, unsigned long flags) { + rcutree_enqueue(rdp, head, func); /* * If called from an extended quiescent state, invoke the RCU * core in order to force a re-evaluation of RCU's idleness. @@ -2660,7 +2674,6 @@ __call_rcu_common(struct rcu_head *head, rcu_callback_t func, bool lazy_in) unsigned long flags; bool lazy; struct rcu_data *rdp; - bool was_alldone; /* Misaligned rcu_head! */ WARN_ON_ONCE((unsigned long)head & (sizeof(void *) - 1)); @@ -2697,28 +2710,11 @@ __call_rcu_common(struct rcu_head *head, rcu_callback_t func, bool lazy_in) } check_cb_ovld(rdp); - if (rcu_nocb_try_bypass(rdp, head, &was_alldone, flags, lazy)) { - local_irq_restore(flags); - return; // Enqueued onto ->nocb_bypass, so just leave. - } - // If no-CBs CPU gets here, rcu_nocb_try_bypass() acquired ->nocb_lock. - rcu_segcblist_enqueue(&rdp->cblist, head); - if (__is_kvfree_rcu_offset((unsigned long)func)) - trace_rcu_kvfree_callback(rcu_state.name, head, - (unsigned long)func, - rcu_segcblist_n_cbs(&rdp->cblist)); + + if (unlikely(rcu_rdp_is_offloaded(rdp))) + call_rcu_nocb(rdp, head, func, flags, lazy); else - trace_rcu_callback(rcu_state.name, head, - rcu_segcblist_n_cbs(&rdp->cblist)); - - trace_rcu_segcb_stats(&rdp->cblist, TPS("SegCBQueued")); - - /* Go handle any RCU core processing required. */ - if (unlikely(rcu_rdp_is_offloaded(rdp))) { - __call_rcu_nocb_wake(rdp, was_alldone, flags); /* unlocks */ - } else { - __call_rcu_core(rdp, head, flags); - } + call_rcu_core(rdp, head, func, flags); local_irq_restore(flags); } diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h index e9821a8422db..e0e70b663cbf 100644 --- a/kernel/rcu/tree.h +++ b/kernel/rcu/tree.h @@ -467,9 +467,8 @@ static void rcu_init_one_nocb(struct rcu_node *rnp); static bool wake_nocb_gp(struct rcu_data *rdp, bool force); static bool rcu_nocb_flush_bypass(struct rcu_data *rdp, struct rcu_head *rhp, unsigned long j, bool lazy); -static bool rcu_nocb_try_bypass(struct rcu_data *rdp, struct rcu_head *rhp, - bool *was_alldone, unsigned long flags, - bool lazy); +static void call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *head, + rcu_callback_t func, unsigned long flags, bool lazy); static void __call_rcu_nocb_wake(struct rcu_data *rdp, bool was_empty, unsigned long flags); static int rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp, int level); diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h index 3f70fd0a2db4..868063621c2f 100644 --- a/kernel/rcu/tree_nocb.h +++ b/kernel/rcu/tree_nocb.h @@ -622,6 +622,18 @@ static void __call_rcu_nocb_wake(struct rcu_data *rdp, bool was_alldone, } } +static void call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *head, + rcu_callback_t func, unsigned long flags, bool lazy) +{ + bool was_alldone; + + if (!rcu_nocb_try_bypass(rdp, head, &was_alldone, flags, lazy)) { + /* Not enqueued on bypass but locked, do regular enqueue */ + rcutree_enqueue(rdp, head, func); + __call_rcu_nocb_wake(rdp, was_alldone, flags); /* unlocks */ + } +} + static int nocb_gp_toggle_rdp(struct rcu_data *rdp, bool *wake_state) { @@ -1765,10 +1777,10 @@ static bool rcu_nocb_flush_bypass(struct rcu_data *rdp, struct rcu_head *rhp, return true; } -static bool rcu_nocb_try_bypass(struct rcu_data *rdp, struct rcu_head *rhp, - bool *was_alldone, unsigned long flags, bool lazy) +static void call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *head, + rcu_callback_t func, unsigned long flags, bool lazy) { - return false; + WARN_ON_ONCE(1); /* Should be dead code! */ } static void __call_rcu_nocb_wake(struct rcu_data *rdp, bool was_empty, -- 2.42.1