[PATCH 23/28] rcuscale: Add hazptr scale type

From: Kunwu Chan

Date: Wed Nov 04 2026 - 12:11:51 EST


Add a hazptr scale type for per-writer hazptr_synchronize()
cost and per-reader hazptr_acquire()/hazptr_release() overhead.

Signed-off-by: Kunwu Chan <kunwu.chan@xxxxxxxxx>
---
kernel/rcu/rcuscale.c | 67 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)

diff --git a/kernel/rcu/rcuscale.c b/kernel/rcu/rcuscale.c
index 5659eaebc5c0..6e3e3f296f85 100644
--- a/kernel/rcu/rcuscale.c
+++ b/kernel/rcu/rcuscale.c
@@ -40,6 +40,7 @@
#include <linux/vmalloc.h>
#include <linux/rcupdate_trace.h>
#include <linux/sched/debug.h>
+#include <linux/hazptr.h>

#include "rcu.h"

@@ -460,6 +461,71 @@ static struct rcu_scale_ops tasks_tracing_ops = {

#endif // #else // #ifdef CONFIG_TASKS_TRACE_RCU

+#if IS_ENABLED(CONFIG_HAZPTR_TORTURE_TEST)
+
+#define HAZPTR_SCALE_NR_OBJS 8
+static int hazptr_scale_obj[HAZPTR_SCALE_NR_OBJS];
+static atomic_t hazptr_scale_sync_idx = ATOMIC_INIT(0);
+
+struct hazptr_scale_state {
+ struct hazptr_ctx ctx;
+ void *addr;
+};
+static DEFINE_PER_CPU(struct hazptr_scale_state, hazptr_scale_state);
+
+static int hazptr_scale_read_lock(void)
+{
+ struct hazptr_scale_state *state = this_cpu_ptr(&hazptr_scale_state);
+ int idx = smp_processor_id() % HAZPTR_SCALE_NR_OBJS;
+ void *ptr = &hazptr_scale_obj[idx];
+
+ state->addr = hazptr_acquire(&state->ctx, &ptr);
+ return 0;
+}
+
+static void hazptr_scale_read_unlock(int idx)
+{
+ struct hazptr_scale_state *state = this_cpu_ptr(&hazptr_scale_state);
+
+ hazptr_release(&state->ctx, state->addr);
+}
+
+static unsigned long hazptr_scale_completed(void)
+{
+ return 0;
+}
+
+static void hazptr_scale_sync(void)
+{
+ int idx = atomic_fetch_inc(&hazptr_scale_sync_idx) % HAZPTR_SCALE_NR_OBJS;
+
+ hazptr_synchronize(&hazptr_scale_obj[idx]);
+}
+
+static void hazptr_scale_sync_exp(void)
+{
+ int idx = atomic_fetch_inc(&hazptr_scale_sync_idx) % HAZPTR_SCALE_NR_OBJS;
+
+ hazptr_synchronize(&hazptr_scale_obj[idx]);
+}
+
+static struct rcu_scale_ops hazptr_scale_ops = {
+ .ptype = 0,
+ .readlock = hazptr_scale_read_lock,
+ .readunlock = hazptr_scale_read_unlock,
+ .get_gp_seq = hazptr_scale_completed,
+ .gp_diff = NULL,
+ .exp_completed = hazptr_scale_completed,
+ .sync = hazptr_scale_sync,
+ .exp_sync = hazptr_scale_sync_exp,
+ .name = "hazptr",
+};
+
+#define HAZPTR_SCALE_OPS &hazptr_scale_ops,
+#else
+#define HAZPTR_SCALE_OPS
+#endif
+
static unsigned long rcuscale_seq_diff(unsigned long new, unsigned long old)
{
if (!cur_ops->gp_diff)
@@ -1140,6 +1206,7 @@ rcu_scale_init(void)
static struct rcu_scale_ops *scale_ops[] = {
&rcu_ops, &srcu_ops, &srcua_ops, &srcud_ops,
TASKS_OPS TASKS_RUDE_OPS TASKS_TRACING_OPS
+ HAZPTR_SCALE_OPS
};

if (!torture_init_begin(scale_type, verbose))
--
2.43.0