@@ -125,25 +125,55 @@ static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \
125125 * trivial wrapper around DEFINE_CLASS() above specifically
126126 * for locks.
127127 *
128+ * DEFINE_GUARD_COND(name, ext, condlock)
129+ * wrapper around EXTEND_CLASS above to add conditional lock
130+ * variants to a base class, eg. mutex_trylock() or
131+ * mutex_lock_interruptible().
132+ *
128133 * guard(name):
129- * an anonymous instance of the (guard) class
134+ * an anonymous instance of the (guard) class, not recommended for
135+ * conditional locks.
130136 *
131137 * scoped_guard (name, args...) { }:
132138 * similar to CLASS(name, scope)(args), except the variable (with the
133139 * explicit name 'scope') is declard in a for-loop such that its scope is
134140 * bound to the next (compound) statement.
135141 *
142+ * for conditional locks the loop body is skipped when the lock is not
143+ * acquired.
144+ *
145+ * scoped_cond_guard (name, fail, args...) { }:
146+ * similar to scoped_guard(), except it does fail when the lock
147+ * acquire fails.
148+ *
136149 */
137150
138151#define DEFINE_GUARD (_name , _type , _lock , _unlock ) \
139- DEFINE_CLASS(_name, _type, _unlock, ({ _lock; _T; }), _type _T)
152+ DEFINE_CLASS(_name, _type, if (_T) { _unlock; }, ({ _lock; _T; }), _type _T); \
153+ static inline void * class_##_name##_lock_ptr(class_##_name##_t *_T) \
154+ { return *_T; }
155+
156+ #define DEFINE_GUARD_COND (_name , _ext , _condlock ) \
157+ EXTEND_CLASS(_name, _ext, \
158+ ({ void *_t = _T; if (_T && !(_condlock)) _t = NULL; _t; }), \
159+ class_##_name##_t _T) \
160+ static inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t *_T) \
161+ { return class_##_name##_lock_ptr(_T); }
140162
141163#define guard (_name ) \
142164 CLASS(_name, __UNIQUE_ID(guard))
143165
166+ #define __guard_ptr (_name ) class_##_name##_lock_ptr
167+
144168#define scoped_guard (_name , args ...) \
145169 for (CLASS(_name, scope)(args), \
146- *done = NULL; !done; done = (void *)1)
170+ *done = NULL; __guard_ptr(_name)(&scope) && !done; done = (void *)1)
171+
172+ #define scoped_cond_guard (_name , _fail , args ...) \
173+ for (CLASS(_name, scope)(args), \
174+ *done = NULL; !done; done = (void *)1) \
175+ if (!__guard_ptr(_name)(&scope)) _fail; \
176+ else
147177
148178/*
149179 * Additional helper macros for generating lock guards with types, either for
@@ -152,6 +182,7 @@ static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \
152182 *
153183 * DEFINE_LOCK_GUARD_0(name, lock, unlock, ...)
154184 * DEFINE_LOCK_GUARD_1(name, type, lock, unlock, ...)
185+ * DEFINE_LOCK_GUARD_1_COND(name, ext, condlock)
155186 *
156187 * will result in the following type:
157188 *
@@ -173,6 +204,11 @@ typedef struct { \
173204static inline void class_##_name##_destructor(class_##_name##_t *_T) \
174205{ \
175206 if (_T->lock) { _unlock; } \
207+ } \
208+ \
209+ static inline void *class_##_name##_lock_ptr(class_##_name##_t *_T) \
210+ { \
211+ return _T->lock; \
176212}
177213
178214
@@ -201,4 +237,14 @@ __DEFINE_LOCK_GUARD_1(_name, _type, _lock)
201237__DEFINE_UNLOCK_GUARD(_name, void, _unlock, __VA_ARGS__) \
202238__DEFINE_LOCK_GUARD_0(_name, _lock)
203239
240+ #define DEFINE_LOCK_GUARD_1_COND (_name , _ext , _condlock ) \
241+ EXTEND_CLASS(_name, _ext, \
242+ ({ class_##_name##_t _t = { .lock = l }, *_T = &_t;\
243+ if (_T->lock && !(_condlock)) _T->lock = NULL; \
244+ _t; }), \
245+ typeof_member(class_##_name##_t, lock) l) \
246+ static inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t *_T) \
247+ { return class_##_name##_lock_ptr(_T); }
248+
249+
204250#endif /* __LINUX_GUARDS_H */
0 commit comments