Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp2590693pxa; Mon, 24 Aug 2020 19:51:44 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyg5ZXFiRWyxJHOM4qz27jVRtjl5ODKXA9AAZFPEfQp8rwknh0Edbn/V5jdnmmdp20eESvR X-Received: by 2002:aa7:df15:: with SMTP id c21mr8416248edy.334.1598323904650; Mon, 24 Aug 2020 19:51:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1598323904; cv=none; d=google.com; s=arc-20160816; b=l8mBXG2kF7UuQpbUqkD67h/+KYb2b0UkoPkO+ooNPMblOBQmTZAd3vsDD3TZYcX+Tq HjNLBMYP8aou0wuIzRAkgnSH+AFEanqgSuFYQZnz0IVl4eZuuTm0K4EkIiXAMrGMRBdK mcRdF3DHLmDSPUkRTn6/D1+a76HUO8oKTvt/UIC0HCfVhqOPjFKuFmJQOBmNpx87yo5X wf2i2YG564eESU2muPTPAFUPsZxEZN85R19ZhV2cFzA+vidFntWOih66gOkz4wIQCqGx zMHUPIzW7LnPQ8Ue52jFMmIgBK40lDajzxuE6+u+Yg95Su8HAguwEP+bIJD3iKB1odSI S0fw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=GNOc7Z1ZVQv4ZS9+nEACu5nTPNDX+2CD9wuHQr/q5ns=; b=rM2fxeNX5Hfr/eDbHAJSD9YWM0RKleYVHyiMjaNL4P5j8qygN+pC58s/N6WZvNkBoB BLVY2UHwi7SDfvyfb8iqEw/UtS0iD/AoPgDdXoXyBSrTGa8jcSDO4QWqrfylteLeVgvg b8bWG00IA5sYRifXjO/nGC1qloIktkLGuaqr9w8peEnTrdC3oZbtVu+QDUHH+BH26eoC PY/aG6h7N7yty5/4UasMtGmo5a5hn5WM4wbmzHL4lFALGRMuu7Pur+GRWkPvrQHUaj/k Hb97VlzZLhCKMYFYXamXiuvJA7TSLcNqDYtZFhYkey1CLv1ob7oaS43/9CiIQuxXAxz5 8UdQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@joelfernandes.org header.s=google header.b=s7w7iOPG; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id z1si7916045edx.129.2020.08.24.19.51.21; Mon, 24 Aug 2020 19:51:44 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@joelfernandes.org header.s=google header.b=s7w7iOPG; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728396AbgHYCtG (ORCPT + 99 others); Mon, 24 Aug 2020 22:49:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36308 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728209AbgHYCsy (ORCPT ); Mon, 24 Aug 2020 22:48:54 -0400 Received: from mail-qk1-x744.google.com (mail-qk1-x744.google.com [IPv6:2607:f8b0:4864:20::744]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E4C52C061795 for ; Mon, 24 Aug 2020 19:48:53 -0700 (PDT) Received: by mail-qk1-x744.google.com with SMTP id z3so5437041qkz.7 for ; Mon, 24 Aug 2020 19:48:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=joelfernandes.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=GNOc7Z1ZVQv4ZS9+nEACu5nTPNDX+2CD9wuHQr/q5ns=; b=s7w7iOPGM3ouI/jBlVnA51DTTkbg0weRq4FqUc/HFMssVraJKBhTeO+INe6sd8K3Ux 33Ln40HR8EPkPxsXCROUCxeF3PBxIRMNPzn+wWA7AeaC2QxCqFNurc1oYeoISL2RpHg9 JgXRRhTQNbifALcHGTU4UIVSchUjBzeGPm4Dw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=GNOc7Z1ZVQv4ZS9+nEACu5nTPNDX+2CD9wuHQr/q5ns=; b=afW0ABw+/N901GoVK4VOKHGKGc62gfBz1qaUDBLrFKHp6IlgCYrgcY/qLXmxocqNe4 BAeGXuRoMuHk4iGfgKiM6CLWvnWWb2JYPT8c3cRVx9qJGkOQ6O93sZzewTcYsyGh/6in c/mrvDWbmctDMbX645E+O1QfcJR1+c5+qCSp6Sga76P9F1Afg7YbiNgmTSFobx9H6exL CxJp4ZC+O4ieXjg7zoGh6HPYtjKQ1XvdZGECoN+/IYiZIfM+/0Ag/78HYzNM4e3sawwH tKPs+8zCAjYjKuWBHQdOgjHkQwnABdxxsbUb0wi1pKCl7THJKgzRoSLVcYC0qs6Npy2o vzAA== X-Gm-Message-State: AOAM531gejitnYK4GgAhI/ii80mnI0AQLyCFy4PE4VBwLSJ+XZr6bAml e42r+KSQcx4sCwYwTSU2YmxCgNZg5A9mzA== X-Received: by 2002:a37:a882:: with SMTP id r124mr7201780qke.56.1598323732659; Mon, 24 Aug 2020 19:48:52 -0700 (PDT) Received: from joelaf.cam.corp.google.com ([2620:15c:6:12:cad3:ffff:feb3:bd59]) by smtp.gmail.com with ESMTPSA id n14sm2159188qtk.50.2020.08.24.19.48.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Aug 2020 19:48:52 -0700 (PDT) From: "Joel Fernandes (Google)" To: linux-kernel@vger.kernel.org Cc: "Joel Fernandes (Google)" , boqun.feng@gmail.com, dave@stgolabs.net, Ingo Molnar , Josh Triplett , Lai Jiangshan , Madhuparna Bhowmik , Mathieu Desnoyers , neeraj.iitr10@gmail.com, "Paul E. McKenney" , rcu@vger.kernel.org, Steven Rostedt , "Uladzislau Rezki (Sony)" , vineethrp@gmail.com Subject: [PATCH v4 -rcu 3/4] rcu/segcblist: Add counters to segcblist datastructure Date: Mon, 24 Aug 2020 22:48:41 -0400 Message-Id: <20200825024842.3408659-4-joel@joelfernandes.org> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog In-Reply-To: <20200825024842.3408659-1-joel@joelfernandes.org> References: <20200825024842.3408659-1-joel@joelfernandes.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add counting of segment lengths of segmented callback list. This will be useful for a number of things such as knowing how big the ready-to-execute segment have gotten. The immediate benefit is ability to trace how the callbacks in the segmented callback list change. Tested by profusely reading traces when segcblist counts updated. Signed-off-by: Joel Fernandes (Google) --- include/linux/rcu_segcblist.h | 2 + kernel/rcu/rcu_segcblist.c | 82 +++++++++++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/include/linux/rcu_segcblist.h b/include/linux/rcu_segcblist.h index b36afe7b22c9..d462ae5e340a 100644 --- a/include/linux/rcu_segcblist.h +++ b/include/linux/rcu_segcblist.h @@ -69,8 +69,10 @@ struct rcu_segcblist { unsigned long gp_seq[RCU_CBLIST_NSEGS]; #ifdef CONFIG_RCU_NOCB_CPU atomic_long_t len; + atomic_long_t seglen[RCU_CBLIST_NSEGS]; #else long len; + long seglen[RCU_CBLIST_NSEGS]; #endif u8 enabled; u8 offloaded; diff --git a/kernel/rcu/rcu_segcblist.c b/kernel/rcu/rcu_segcblist.c index 076337ae2e50..73a103464ea4 100644 --- a/kernel/rcu/rcu_segcblist.c +++ b/kernel/rcu/rcu_segcblist.c @@ -88,6 +88,62 @@ static void rcu_segcblist_set_len(struct rcu_segcblist *rsclp, long v) #endif } +/* Get the length of a segment of the rcu_segcblist structure. */ +static long rcu_segcblist_get_seglen(struct rcu_segcblist *rsclp, int seg) +{ +#ifdef CONFIG_RCU_NOCB_CPU + return atomic_long_read(&rsclp->seglen[seg]); +#else + return READ_ONCE(rsclp->seglen[seg]); +#endif +} + +/* Set the length of a segment of the rcu_segcblist structure. */ +static void rcu_segcblist_set_seglen(struct rcu_segcblist *rsclp, int seg, long v) +{ +#ifdef CONFIG_RCU_NOCB_CPU + atomic_long_set(&rsclp->seglen[seg], v); +#else + WRITE_ONCE(rsclp->seglen[seg], v); +#endif +} + +/* Return number of callbacks in a segment of the segmented callback list. */ +static void rcu_segcblist_add_seglen(struct rcu_segcblist *rsclp, int seg, long v) +{ +#ifdef CONFIG_RCU_NOCB_CPU + smp_mb__before_atomic(); /* Up to the caller! */ + atomic_long_add(v, &rsclp->seglen[seg]); + smp_mb__after_atomic(); /* Up to the caller! */ +#else + smp_mb(); /* Up to the caller! */ + WRITE_ONCE(rsclp->seglen[seg], rsclp->seglen[seg] + v); + smp_mb(); /* Up to the caller! */ +#endif +} + +/* Move from's segment length to to's segment. */ +static void rcu_segcblist_move_seglen(struct rcu_segcblist *rsclp, int from, int to) +{ + long len; + + if (from == to) + return; + + len = rcu_segcblist_get_seglen(rsclp, from); + if (!len) + return; + + rcu_segcblist_add_seglen(rsclp, to, len); + rcu_segcblist_set_seglen(rsclp, from, 0); +} + +/* Increment segment's length. */ +static void rcu_segcblist_inc_seglen(struct rcu_segcblist *rsclp, int seg) +{ + rcu_segcblist_add_seglen(rsclp, seg, 1); +} + /* * Increase the numeric length of an rcu_segcblist structure by the * specified amount, which can be negative. This can cause the ->len @@ -149,8 +205,10 @@ void rcu_segcblist_init(struct rcu_segcblist *rsclp) BUILD_BUG_ON(RCU_NEXT_TAIL + 1 != ARRAY_SIZE(rsclp->gp_seq)); BUILD_BUG_ON(ARRAY_SIZE(rsclp->tails) != ARRAY_SIZE(rsclp->gp_seq)); rsclp->head = NULL; - for (i = 0; i < RCU_CBLIST_NSEGS; i++) + for (i = 0; i < RCU_CBLIST_NSEGS; i++) { rsclp->tails[i] = &rsclp->head; + rcu_segcblist_set_seglen(rsclp, i, 0); + } rcu_segcblist_set_len(rsclp, 0); rsclp->enabled = 1; } @@ -245,6 +303,7 @@ void rcu_segcblist_enqueue(struct rcu_segcblist *rsclp, struct rcu_head *rhp) { rcu_segcblist_inc_len(rsclp); + rcu_segcblist_inc_seglen(rsclp, RCU_NEXT_TAIL); smp_mb(); /* Ensure counts are updated before callback is enqueued. */ rhp->next = NULL; WRITE_ONCE(*rsclp->tails[RCU_NEXT_TAIL], rhp); @@ -274,6 +333,7 @@ bool rcu_segcblist_entrain(struct rcu_segcblist *rsclp, for (i = RCU_NEXT_TAIL; i > RCU_DONE_TAIL; i--) if (rsclp->tails[i] != rsclp->tails[i - 1]) break; + rcu_segcblist_inc_seglen(rsclp, i); WRITE_ONCE(*rsclp->tails[i], rhp); for (; i <= RCU_NEXT_TAIL; i++) WRITE_ONCE(rsclp->tails[i], &rhp->next); @@ -307,6 +367,7 @@ void rcu_segcblist_extract_done_cbs(struct rcu_segcblist *rsclp, if (!rcu_segcblist_ready_cbs(rsclp)) return; /* Nothing to do. */ + rclp->len = rcu_segcblist_get_seglen(rsclp, RCU_DONE_TAIL); *rclp->tail = rsclp->head; WRITE_ONCE(rsclp->head, *rsclp->tails[RCU_DONE_TAIL]); WRITE_ONCE(*rsclp->tails[RCU_DONE_TAIL], NULL); @@ -314,6 +375,7 @@ void rcu_segcblist_extract_done_cbs(struct rcu_segcblist *rsclp, for (i = RCU_CBLIST_NSEGS - 1; i >= RCU_DONE_TAIL; i--) if (rsclp->tails[i] == rsclp->tails[RCU_DONE_TAIL]) WRITE_ONCE(rsclp->tails[i], &rsclp->head); + rcu_segcblist_set_seglen(rsclp, RCU_DONE_TAIL, 0); } /* @@ -330,11 +392,16 @@ void rcu_segcblist_extract_pend_cbs(struct rcu_segcblist *rsclp, if (!rcu_segcblist_pend_cbs(rsclp)) return; /* Nothing to do. */ + rclp->len = rcu_segcblist_get_seglen(rsclp, RCU_WAIT_TAIL) + + rcu_segcblist_get_seglen(rsclp, RCU_NEXT_READY_TAIL) + + rcu_segcblist_get_seglen(rsclp, RCU_NEXT_TAIL); *rclp->tail = *rsclp->tails[RCU_DONE_TAIL]; rclp->tail = rsclp->tails[RCU_NEXT_TAIL]; WRITE_ONCE(*rsclp->tails[RCU_DONE_TAIL], NULL); - for (i = RCU_DONE_TAIL + 1; i < RCU_CBLIST_NSEGS; i++) + for (i = RCU_DONE_TAIL + 1; i < RCU_CBLIST_NSEGS; i++) { WRITE_ONCE(rsclp->tails[i], rsclp->tails[RCU_DONE_TAIL]); + rcu_segcblist_set_seglen(rsclp, i, 0); + } } /* @@ -359,6 +426,7 @@ void rcu_segcblist_insert_done_cbs(struct rcu_segcblist *rsclp, if (!rclp->head) return; /* No callbacks to move. */ + rcu_segcblist_add_seglen(rsclp, RCU_DONE_TAIL, rclp->len); *rclp->tail = rsclp->head; WRITE_ONCE(rsclp->head, rclp->head); for (i = RCU_DONE_TAIL; i < RCU_CBLIST_NSEGS; i++) @@ -379,6 +447,8 @@ void rcu_segcblist_insert_pend_cbs(struct rcu_segcblist *rsclp, { if (!rclp->head) return; /* Nothing to do. */ + + rcu_segcblist_add_seglen(rsclp, RCU_NEXT_TAIL, rclp->len); WRITE_ONCE(*rsclp->tails[RCU_NEXT_TAIL], rclp->head); WRITE_ONCE(rsclp->tails[RCU_NEXT_TAIL], rclp->tail); } @@ -403,6 +473,7 @@ void rcu_segcblist_advance(struct rcu_segcblist *rsclp, unsigned long seq) if (ULONG_CMP_LT(seq, rsclp->gp_seq[i])) break; WRITE_ONCE(rsclp->tails[RCU_DONE_TAIL], rsclp->tails[i]); + rcu_segcblist_move_seglen(rsclp, i, RCU_DONE_TAIL); } /* If no callbacks moved, nothing more need be done. */ @@ -423,6 +494,7 @@ void rcu_segcblist_advance(struct rcu_segcblist *rsclp, unsigned long seq) if (rsclp->tails[j] == rsclp->tails[RCU_NEXT_TAIL]) break; /* No more callbacks. */ WRITE_ONCE(rsclp->tails[j], rsclp->tails[i]); + rcu_segcblist_move_seglen(rsclp, i, j); rsclp->gp_seq[j] = rsclp->gp_seq[i]; } } @@ -444,7 +516,7 @@ void rcu_segcblist_advance(struct rcu_segcblist *rsclp, unsigned long seq) */ bool rcu_segcblist_accelerate(struct rcu_segcblist *rsclp, unsigned long seq) { - int i; + int i, j; WARN_ON_ONCE(!rcu_segcblist_is_enabled(rsclp)); if (rcu_segcblist_restempty(rsclp, RCU_DONE_TAIL)) @@ -487,6 +559,10 @@ bool rcu_segcblist_accelerate(struct rcu_segcblist *rsclp, unsigned long seq) if (rcu_segcblist_restempty(rsclp, i) || ++i >= RCU_NEXT_TAIL) return false; + /* Accounting: everything below i is about to get merged into i. */ + for (j = i + 1; j <= RCU_NEXT_TAIL; j++) + rcu_segcblist_move_seglen(rsclp, j, i); + /* * Merge all later callbacks, including newly arrived callbacks, * into the segment located by the for-loop above. Assign "seq" -- 2.28.0.297.g1956fa8f8d-goog