mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Jim Cromie <jim.cromie@gmail.com>
To: Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,  Will Deacon <will@kernel.org>,
	Boqun Feng <boqun@kernel.org>,  Waiman Long <longman@redhat.com>
Cc: linux-kernel@vger.kernel.org, Jim Cromie <jim.cromie@gmail.com>
Subject: [PATCH 5/8] lockdep: Fast-path power-of-2 tables with shift/mask indexing
Date: Wed, 26 Aug 2026 21:58:37 -0600	[thread overview]
Message-ID: <20260826-lockdep-memblock-v1-v1-5-e2db855391ec@gmail.com> (raw)
In-Reply-To: <20260826-lockdep-memblock-v1-v1-0-e2db855391ec@gmail.com>

The 2D chunked arrays (DECLARE_CHUNKED_ARRAY) use Granlund-Montgomery
reciprocal division (reciprocal_divide()) to map indices to (chunk, offset)
tuples across 64 KB slabs. This achieves >99.8% packing density for
non-power-of-2 structs (lock_classes @ 160 B and list_entries @ 48 B).

However, the ultra-hot cache-verification tables (lock_chains @ 32 B and
chain_hlocks @ 2 B) have exact power-of-2 chunk counts (2,048 and 32,768
elements per 64 KB slab).

Add a compile-time branch in DECLARE_CHUNKED_ARRAY() using __builtin_ctz():
for power-of-2 tables, GCC/Clang folds translation into single-cycle bit
shifts (idx >> SHIFT) and masks (idx & MASK), eliminating reciprocal
multiplication overhead entirely from the hot acquire validation path.

Workload Progression (hackbench -p -g 8 -l 1000, 4 vCPUs):

  Metric        Upstream (1D) Generic (P2)      Fast-Path (P3)   Delta
  ====================================================================
  Runtime             8.482 s    8.895 s (+4.8%)       8.278 s  -2.40%
  Cycles          52899510936   55428687460     52033166458     -1.64%
  Instructions    29008189069   31932214532     31698626928     +9.27%

By replacing G-M multiplication with single-cycle bit shifts on the hot
cache verification tables, cycle overhead drops by ~6.4% relative to
Patch 2, bringing total cycles to parity with or slightly faster than
upstream baseline (-1.64% cycles).

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
 kernel/locking/lockdep.c           |  2 +-
 kernel/locking/lockdep_internals.h | 15 +++++++++++++--
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 1c8db52af1ac..b2dc7619a5e3 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -3953,7 +3953,7 @@ static struct lock_chain *alloc_lock_chain(void)
 	if (unlikely(idx >= MAX_LOCKDEP_CHAINS))
 		return NULL;
 
-	chunk_idx = reciprocal_divide(idx, lock_chain_rv);
+	chunk_idx = idx / lock_chain_PER_CHUNK;
 	if (chunk_idx >= LOCKDEP_MAX_SLABS)
 		return NULL;
 
diff --git a/kernel/locking/lockdep_internals.h b/kernel/locking/lockdep_internals.h
index eaa23d9b4dd5..ccd7343af672 100644
--- a/kernel/locking/lockdep_internals.h
+++ b/kernel/locking/lockdep_internals.h
@@ -154,14 +154,25 @@ enum {
 #define DECLARE_CHUNKED_ARRAY(name, type)					\
 	enum {									\
 		name##_PER_CHUNK = (LOCKDEP_SLAB_SIZE / sizeof(type)),		\
+		name##_IS_P2     = (!(name##_PER_CHUNK & (name##_PER_CHUNK - 1))), \
+		name##_SHIFT     = (__builtin_ctz(name##_PER_CHUNK)),		\
+		name##_MASK      = (name##_PER_CHUNK - 1),			\
 	};									\
 	extern type * name##_chunks[LOCKDEP_MAX_SLABS];				\
 	extern const struct reciprocal_value name##_rv;				\
 	static __always_inline type *idx_to_##name(unsigned int idx)		\
 	{									\
-		unsigned int chunk = reciprocal_divide(idx, name##_rv);		\
-		unsigned int offset = idx - (chunk * name##_PER_CHUNK);		\
+		unsigned int chunk, offset;					\
 		type *chunk_ptr;						\
+										\
+		if (name##_IS_P2) {						\
+			chunk = idx >> name##_SHIFT;				\
+			offset = idx & name##_MASK;				\
+		} else {							\
+			chunk = reciprocal_divide(idx, name##_rv);		\
+			offset = idx - (chunk * name##_PER_CHUNK);		\
+		}								\
+										\
 		if (unlikely(chunk >= LOCKDEP_MAX_SLABS))			\
 			return NULL;						\
 		/* Pairs with smp_store_release() when new chunk slabs are published */ \

-- 
2.55.0


  parent reply	other threads:[~2026-08-27  3:58 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-27  3:58 [PATCH 0/8] lockdep: change 5 graph-db arrays to AofAs, fill from memblock pool Jim Cromie
2026-08-27  3:58 ` [PATCH 1/8] lockdep: Traverse adjacency lists directly in zap_class() Jim Cromie
2026-08-27  3:58 ` [PATCH 2/8] lockdep: Add chunked array infrastructure and embedded indices Jim Cromie
2026-08-27  3:58 ` [PATCH 3/8] lockdep: Pre-reserve early memblock slab pool for dynamic tables Jim Cromie
2026-08-27  3:58 ` [PATCH 4/8] lockdep: Convert 5 graph arrays to chunked tables backed by slab pool Jim Cromie
2026-08-27  3:58 ` Jim Cromie [this message]
2026-08-27  3:58 ` [PATCH 6/8] lockdep: Free unused reservation slabs to buddy allocator at late boot Jim Cromie
2026-08-27  3:58 ` [PATCH 7/8] lockdep: Expose slab pool telemetry in /proc/lockdep_stats and initcalls Jim Cromie
2026-08-27  3:58 ` [PATCH 8/8] lockdep: on debug_locks_off or OOM, recycle all slabs to buddy Jim Cromie
2026-08-27  6:46 ` [PATCH 0/8] lockdep: change 5 graph-db arrays to AofAs, fill from memblock pool Peter Zijlstra
2026-08-27  8:54   ` jim.cromie
2026-08-27  9:03     ` Peter Zijlstra
2026-08-27 18:40       ` jim.cromie

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260826-lockdep-memblock-v1-v1-5-e2db855391ec@gmail.com \
    --to=jim.cromie@gmail.com \
    --cc=boqun@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=longman@redhat.com \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®