[RFC PATCH] local_lock: Add local_lock access for a CPU-local pointer

Sebastian Andrzej Siewior posted 1 patch 8 months ago
include/linux/local_lock.h          |  6 ++++++
include/linux/local_lock_internal.h | 20 ++++++++++++++++++++
2 files changed, 26 insertions(+)
[RFC PATCH] local_lock: Add local_lock access for a CPU-local pointer
Posted by Sebastian Andrzej Siewior 8 months ago
For the most part the local_lock API expects __percpu pointer to operate
on. So we have for instance
	local_lock(var.lock)

and local_lock() will invoke this_cpu_ptr(var.lock) and do the actual
locking on the resulting pointer. Good.

There is one exception to this, that is local_lock_init(), which expects
a CPU local (instead a __percpu) pointer. This is used with dynamic
per-CPU memory allocation. You wouldn't have guessed that based on
function naming but it is kind of obvious if you think about it. The two
users, that use it, pass the __percpu pointer to the locking function so
everything works as expected.

Now I got to the case where a __percpu variable is made CPU-local and
this pointer is passed to queue_work(). This is fine but the kworker
operates on a CPU-local pointer and now I need local_lock()
without the this_cpu_ptr() in it.
Adding a _local to the function name would be a bit too local. I added
_this instead but don't like it very much. Anyone with a better naming?

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 include/linux/local_lock.h          |  6 ++++++
 include/linux/local_lock_internal.h | 20 ++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/include/linux/local_lock.h b/include/linux/local_lock.h
index 1a0bc35839e36..5bce77200248b 100644
--- a/include/linux/local_lock.h
+++ b/include/linux/local_lock.h
@@ -138,6 +138,12 @@ DEFINE_LOCK_GUARD_1(local_lock_irqsave, local_lock_t __percpu,
 #define local_unlock_nested_bh(_lock)				\
 	__local_unlock_nested_bh(_lock)
 
+#define local_lock_nested_bh_this(_lock)			\
+	__local_lock_nested_bh_this(_lock)
+
+#define local_unlock_nested_bh_this(_lock)			\
+	__local_unlock_nested_bh_this(_lock)
+
 DEFINE_GUARD(local_lock_nested_bh, local_lock_t __percpu*,
 	     local_lock_nested_bh(_T),
 	     local_unlock_nested_bh(_T))
diff --git a/include/linux/local_lock_internal.h b/include/linux/local_lock_internal.h
index 67bd13d142fac..84556b7d298f9 100644
--- a/include/linux/local_lock_internal.h
+++ b/include/linux/local_lock_internal.h
@@ -129,9 +129,18 @@ do {								\
 		local_lock_acquire(this_cpu_ptr(lock));	\
 	} while (0)
 
+#define __local_lock_nested_bh_this(lock)			\
+	do {							\
+		lockdep_assert_in_softirq();			\
+		local_lock_acquire(lock);	\
+	} while (0)
+
 #define __local_unlock_nested_bh(lock)				\
 	local_lock_release(this_cpu_ptr(lock))
 
+#define __local_unlock_nested_bh_this(lock)			\
+	local_lock_release(lock)
+
 /* localtry_lock_t variants */
 
 #define __localtry_lock_init(lock)				\
@@ -278,11 +287,22 @@ do {								\
 	spin_lock(this_cpu_ptr(lock));				\
 } while (0)
 
+#define __local_lock_nested_bh_this(lock)			\
+do {								\
+	lockdep_assert_in_softirq_func();			\
+	spin_lock(lock);					\
+} while (0)
+
 #define __local_unlock_nested_bh(lock)				\
 do {								\
 	spin_unlock(this_cpu_ptr((lock)));			\
 } while (0)
 
+#define __local_unlock_nested_bh_this(lock)			\
+do {								\
+	spin_unlock(lock);					\
+} while (0)
+
 /* localtry_lock_t variants */
 
 #define __localtry_lock_init(lock)			__local_lock_init(lock)
-- 
2.49.0
Re: [RFC PATCH] local_lock: Add local_lock access for a CPU-local pointer
Posted by Waiman Long 7 months, 4 weeks ago
On 4/17/25 12:00 PM, Sebastian Andrzej Siewior wrote:
> For the most part the local_lock API expects __percpu pointer to operate
> on. So we have for instance
> 	local_lock(var.lock)
>
> and local_lock() will invoke this_cpu_ptr(var.lock) and do the actual
> locking on the resulting pointer. Good.
>
> There is one exception to this, that is local_lock_init(), which expects
> a CPU local (instead a __percpu) pointer. This is used with dynamic
> per-CPU memory allocation. You wouldn't have guessed that based on
> function naming but it is kind of obvious if you think about it. The two
> users, that use it, pass the __percpu pointer to the locking function so
> everything works as expected.
>
> Now I got to the case where a __percpu variable is made CPU-local and
> this pointer is passed to queue_work(). This is fine but the kworker
> operates on a CPU-local pointer and now I need local_lock()
> without the this_cpu_ptr() in it.
> Adding a _local to the function name would be a bit too local. I added
> _this instead but don't like it very much. Anyone with a better naming?

The "this" suffix looks a bit weird. Since you had introduced 
localtry_lock before, maybe you can follow a similar scheme like 
localcpu_lock.

My 2 cents.

Cheers,
Longman
Re: [RFC PATCH] local_lock: Add local_lock access for a CPU-local pointer
Posted by Sebastian Andrzej Siewior 7 months, 3 weeks ago
On 2025-04-18 22:52:29 [-0400], Waiman Long wrote:
> > Adding a _local to the function name would be a bit too local. I added
> > _this instead but don't like it very much. Anyone with a better naming?
> 
> The "this" suffix looks a bit weird. Since you had introduced localtry_lock
> before, maybe you can follow a similar scheme like localcpu_lock.
> 
> My 2 cents.

Okay. Better.
We usually have function() and __function() which is the internal
implementation with some changes/ presets. Now if we apply this here
and shift the this_cpu_ptr() from __ to main one, like:

diff --git a/include/linux/local_lock.h b/include/linux/local_lock.h
index 1a0bc35839e36..d5e8c7a298055 100644
--- a/include/linux/local_lock.h
+++ b/include/linux/local_lock.h
@@ -133,10 +133,10 @@ DEFINE_LOCK_GUARD_1(local_lock_irqsave, local_lock_t __percpu,
 		    unsigned long flags)
 
 #define local_lock_nested_bh(_lock)				\
-	__local_lock_nested_bh(_lock)
+	__local_lock_nested_bh(this_cpu_ptr(_lock))
 
 #define local_unlock_nested_bh(_lock)				\
-	__local_unlock_nested_bh(_lock)
+	__local_unlock_nested_bh(this_cpu_ptr(_lock))
 
 DEFINE_GUARD(local_lock_nested_bh, local_lock_t __percpu*,
 	     local_lock_nested_bh(_T),
diff --git a/include/linux/local_lock_internal.h b/include/linux/local_lock_internal.h
index 67bd13d142fac..bc6e6cc5dca99 100644
--- a/include/linux/local_lock_internal.h
+++ b/include/linux/local_lock_internal.h
@@ -126,11 +126,11 @@ do {								\
 #define __local_lock_nested_bh(lock)				\
 	do {							\
 		lockdep_assert_in_softirq();			\
-		local_lock_acquire(this_cpu_ptr(lock));	\
+		local_lock_acquire(lock);	\
 	} while (0)
 
 #define __local_unlock_nested_bh(lock)				\
-	local_lock_release(this_cpu_ptr(lock))
+	local_lock_release(lock)
 
 /* localtry_lock_t variants */
 
@@ -275,12 +275,12 @@ typedef spinlock_t localtry_lock_t;
 #define __local_lock_nested_bh(lock)				\
 do {								\
 	lockdep_assert_in_softirq_func();			\
-	spin_lock(this_cpu_ptr(lock));				\
+	spin_lock(lock);				\
 } while (0)
 
 #define __local_unlock_nested_bh(lock)				\
 do {								\
-	spin_unlock(this_cpu_ptr((lock)));			\
+	spin_unlock((lock));			\
 } while (0)
 
 /* localtry_lock_t variants */


Then I could use __local_lock_nested_bh(lock) where "lock" is already
the actual lock pointer.

> Cheers,
> Longman

Sebastian