diff options
Diffstat (limited to 'include/linux/cleanup.h')
| -rw-r--r-- | include/linux/cleanup.h | 52 | 
1 files changed, 49 insertions, 3 deletions
diff --git a/include/linux/cleanup.h b/include/linux/cleanup.h index 9f1a9c455b68..c2d09bc4f976 100644 --- a/include/linux/cleanup.h +++ b/include/linux/cleanup.h @@ -125,25 +125,55 @@ static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \   *	trivial wrapper around DEFINE_CLASS() above specifically   *	for locks.   * + * DEFINE_GUARD_COND(name, ext, condlock) + *	wrapper around EXTEND_CLASS above to add conditional lock + *	variants to a base class, eg. mutex_trylock() or + *	mutex_lock_interruptible(). + *   * guard(name): - *	an anonymous instance of the (guard) class + *	an anonymous instance of the (guard) class, not recommended for + *	conditional locks.   *   * scoped_guard (name, args...) { }:   *	similar to CLASS(name, scope)(args), except the variable (with the   *	explicit name 'scope') is declard in a for-loop such that its scope is   *	bound to the next (compound) statement.   * + *	for conditional locks the loop body is skipped when the lock is not + *	acquired. + * + * scoped_cond_guard (name, fail, args...) { }: + *      similar to scoped_guard(), except it does fail when the lock + *      acquire fails. + *   */  #define DEFINE_GUARD(_name, _type, _lock, _unlock) \ -	DEFINE_CLASS(_name, _type, _unlock, ({ _lock; _T; }), _type _T) +	DEFINE_CLASS(_name, _type, if (_T) { _unlock; }, ({ _lock; _T; }), _type _T); \ +	static inline void * class_##_name##_lock_ptr(class_##_name##_t *_T) \ +	{ return *_T; } + +#define DEFINE_GUARD_COND(_name, _ext, _condlock) \ +	EXTEND_CLASS(_name, _ext, \ +		     ({ void *_t = _T; if (_T && !(_condlock)) _t = NULL; _t; }), \ +		     class_##_name##_t _T) \ +	static inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t *_T) \ +	{ return class_##_name##_lock_ptr(_T); }  #define guard(_name) \  	CLASS(_name, __UNIQUE_ID(guard)) +#define __guard_ptr(_name) class_##_name##_lock_ptr +  #define scoped_guard(_name, args...)					\  	for (CLASS(_name, scope)(args),					\ -	     *done = NULL; !done; done = (void *)1) +	     *done = NULL; __guard_ptr(_name)(&scope) && !done; done = (void *)1) + +#define scoped_cond_guard(_name, _fail, args...) \ +	for (CLASS(_name, scope)(args), \ +	     *done = NULL; !done; done = (void *)1) \ +		if (!__guard_ptr(_name)(&scope)) _fail; \ +		else  /*   * 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) \   *   * DEFINE_LOCK_GUARD_0(name, lock, unlock, ...)   * DEFINE_LOCK_GUARD_1(name, type, lock, unlock, ...) + * DEFINE_LOCK_GUARD_1_COND(name, ext, condlock)   *   * will result in the following type:   * @@ -173,6 +204,11 @@ typedef struct {							\  static inline void class_##_name##_destructor(class_##_name##_t *_T)	\  {									\  	if (_T->lock) { _unlock; }					\ +}									\ +									\ +static inline void *class_##_name##_lock_ptr(class_##_name##_t *_T)	\ +{									\ +	return _T->lock;						\  } @@ -201,4 +237,14 @@ __DEFINE_LOCK_GUARD_1(_name, _type, _lock)  __DEFINE_UNLOCK_GUARD(_name, void, _unlock, __VA_ARGS__)		\  __DEFINE_LOCK_GUARD_0(_name, _lock) +#define DEFINE_LOCK_GUARD_1_COND(_name, _ext, _condlock)		\ +	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)		\ +	static inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t *_T) \ +	{ return class_##_name##_lock_ptr(_T); } + +  #endif /* __LINUX_GUARDS_H */  |