This makes it possible to use the lock guards for guards that need
extra arguments.

I've been attempting to add a guard to xe_force_wake handling, but that
required an extra argument specifying the domain. For nested spinlock
handling, it could also be beneficial to be able to do something like
this.

For example:
DEFINE_LOCK_GUARD_1_COND(spinlock_irqsave, _nested,
                         spin_lock_irqsave_nested(_T->lock, _T->flags, nest),
                         unsigned nest);

guard(spinlock_irqsave_nested, &lock, SINGLE_DEPTH_NESTING);

The first optional argument in DEFINE_LOCK_GUARD_1 is now used for the struct 
members,
the remainder goes to init_args to allow the same usage in the base case..

I'm abusing the preprocessor to add an extra meaning to the first optional
argument is done by creating a __DO_DEFINE_LOCK_GUARD_1, and passing
__VA_ARGS__ not ##__VA_ARGS__ to it to ensure _struct_members is empty
when not passed explicitly.

Cc: Ingo Molnar <mi...@kernel.org>
Cc: David Lechner <dlech...@baylibre.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Will Deacon <w...@kernel.org>
Cc: Waiman Long <long...@redhat.com>
Cc: Boqun Feng <boqun.f...@gmail.com>
---
 include/linux/cleanup.h | 30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/include/linux/cleanup.h b/include/linux/cleanup.h
index ec00e3f7af2b3..dbaf02447f206 100644
--- a/include/linux/cleanup.h
+++ b/include/linux/cleanup.h
@@ -349,19 +349,23 @@ _label:                                                   
                \
  * locks that don't have a native type (eg. RCU, preempt) or those that need a
  * 'fat' pointer (eg. spin_lock_irqsave).
  *
- * DEFINE_LOCK_GUARD_0(name, lock, unlock, ...)
- * DEFINE_LOCK_GUARD_1(name, type, lock, unlock, ...)
- * DEFINE_LOCK_GUARD_1_COND(name, ext, condlock)
+ * DEFINE_LOCK_GUARD_0(name, lock, unlock, _lock_members...)
+ * DEFINE_LOCK_GUARD_1(name, type, lock, unlock, (opt)_lock_members, 
_init_args...)
+ * DEFINE_LOCK_GUARD_1_COND(name, ext, condlock, _init_args...)
  *
  * will result in the following type:
  *
  *   typedef struct {
  *     type *lock;             // 'type := void' for the _0 variant
- *     __VA_ARGS__;
+ *     _lock_members;          // use ; as separator to add multiple members
  *   } class_##name##_t;
  *
  * As above, both _lock and _unlock are statements, except this time '_T' will
  * be a pointer to the above struct.
+ *
+ * For DEFINE_LOCK_GUARD_1 and DEFINE_LOCK_GUARD_1_COND, it adds all
+ * _init_args as local variables available to the lock statement.
+ * They need to be passed to all guard() functions as extra argument.
  */
 
 #define __DEFINE_UNLOCK_GUARD(_name, _type, _unlock, ...)              \
@@ -381,8 +385,8 @@ static inline void 
*class_##_name##_lock_ptr(class_##_name##_t *_T) \
 }
 
 
-#define __DEFINE_LOCK_GUARD_1(_name, _type, _lock)                     \
-static inline class_##_name##_t class_##_name##_constructor(_type *l)  \
+#define __DEFINE_LOCK_GUARD_1(_name, _type, _lock, ...)                        
\
+static inline class_##_name##_t class_##_name##_constructor(_type *l, 
##__VA_ARGS__)   \
 {                                                                      \
        class_##_name##_t _t = { .lock = l }, *_T = &_t;                \
        _lock;                                                          \
@@ -398,23 +402,27 @@ static inline class_##_name##_t 
class_##_name##_constructor(void) \
        return _t;                                                      \
 }
 
-#define DEFINE_LOCK_GUARD_1(_name, _type, _lock, _unlock, ...)         \
+#define __DO_DEFINE_LOCK_GUARD_1(_name, _type, _lock, _unlock, _lock_members, 
_init_args...) \
 __DEFINE_CLASS_IS_CONDITIONAL(_name, false);                           \
-__DEFINE_UNLOCK_GUARD(_name, _type, _unlock, __VA_ARGS__)              \
-__DEFINE_LOCK_GUARD_1(_name, _type, _lock)
+__DEFINE_UNLOCK_GUARD(_name, _type, _unlock, _lock_members)            \
+__DEFINE_LOCK_GUARD_1(_name, _type, _lock, ##_init_args)
+
+/* Call __DO_DEFINE_LOCK_GUARD_1 here because of the 2 optional arguments */
+#define DEFINE_LOCK_GUARD_1(_name, _type, _lock, _unlock, ...)         \
+       __DO_DEFINE_LOCK_GUARD_1(_name, _type, _lock, _unlock, __VA_ARGS__)
 
 #define DEFINE_LOCK_GUARD_0(_name, _lock, _unlock, ...)                        
\
 __DEFINE_CLASS_IS_CONDITIONAL(_name, false);                           \
 __DEFINE_UNLOCK_GUARD(_name, void, _unlock, __VA_ARGS__)               \
 __DEFINE_LOCK_GUARD_0(_name, _lock)
 
-#define DEFINE_LOCK_GUARD_1_COND(_name, _ext, _condlock)               \
+#define DEFINE_LOCK_GUARD_1_COND(_name, _ext, _condlock, ...)          \
        __DEFINE_CLASS_IS_CONDITIONAL(_name##_ext, true);               \
        EXTEND_CLASS(_name, _ext,                                       \
                     ({ class_##_name##_t _t = { .lock = l }, *_T = &_t;\
                        if (_T->lock && !(_condlock)) _T->lock = NULL;  \
                        _t; }),                                         \
-                    typeof_member(class_##_name##_t, lock) l)          \
+                    typeof_member(class_##_name##_t, lock) l, ##__VA_ARGS__)   
        \
        static inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t 
*_T) \
        { return class_##_name##_lock_ptr(_T); }
 
-- 
2.47.1

Reply via email to