Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | /* SPDX-License-Identifier: GPL-2.0 */ #ifndef __LINUX_GUARDS_H #define __LINUX_GUARDS_H #include <linux/compiler.h> /* * DEFINE_FREE(name, type, free): * simple helper macro that defines the required wrapper for a __free() * based cleanup function. @free is an expression using '_T' to access * the variable. * * __free(name): * variable attribute to add a scoped based cleanup to the variable. * * no_free_ptr(var): * like a non-atomic xchg(var, NULL), such that the cleanup function will * be inhibited -- provided it sanely deals with a NULL value. * * return_ptr(p): * returns p while inhibiting the __free(). * * Ex. * * DEFINE_FREE(kfree, void *, if (_T) kfree(_T)) * * struct obj *p __free(kfree) = kmalloc(...); * if (!p) * return NULL; * * if (!init_obj(p)) * return NULL; * * return_ptr(p); */ #define DEFINE_FREE(_name, _type, _free) \ static inline void __free_##_name(void *p) { _type _T = *(_type *)p; _free; } #define __free(_name) __cleanup(__free_##_name) #define no_free_ptr(p) \ ({ __auto_type __ptr = (p); (p) = NULL; __ptr; }) #define return_ptr(p) return no_free_ptr(p) /* * DEFINE_CLASS(name, type, exit, init, init_args...): * helper to define the destructor and constructor for a type. * @exit is an expression using '_T' -- similar to FREE above. * @init is an expression in @init_args resulting in @type * * EXTEND_CLASS(name, ext, init, init_args...): * extends class @name to @name@ext with the new constructor * * CLASS(name, var)(args...): * declare the variable @var as an instance of the named class * * Ex. * * DEFINE_CLASS(fdget, struct fd, fdput(_T), fdget(fd), int fd) * * CLASS(fdget, f)(fd); * if (!f.file) * return -EBADF; * * // use 'f' without concern */ #define DEFINE_CLASS(_name, _type, _exit, _init, _init_args...) \ typedef _type class_##_name##_t; \ static inline void class_##_name##_destructor(_type *p) \ { _type _T = *p; _exit; } \ static inline _type class_##_name##_constructor(_init_args) \ { _type t = _init; return t; } #define EXTEND_CLASS(_name, ext, _init, _init_args...) \ typedef class_##_name##_t class_##_name##ext##_t; \ static inline void class_##_name##ext##_destructor(class_##_name##_t *p)\ { class_##_name##_destructor(p); } \ static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \ { class_##_name##_t t = _init; return t; } #define CLASS(_name, var) \ class_##_name##_t var __cleanup(class_##_name##_destructor) = \ class_##_name##_constructor /* * DEFINE_GUARD(name, type, lock, unlock): * trivial wrapper around DEFINE_CLASS() above specifically * for locks. * * guard(name): * an anonymous instance of the (guard) class * * 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. * */ #define DEFINE_GUARD(_name, _type, _lock, _unlock) \ DEFINE_CLASS(_name, _type, _unlock, ({ _lock; _T; }), _type _T) #define guard(_name) \ CLASS(_name, __UNIQUE_ID(guard)) #define scoped_guard(_name, args...) \ for (CLASS(_name, scope)(args), \ *done = NULL; !done; done = (void *)1) /* * Additional helper macros for generating lock guards with types, either for * 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, ...) * * will result in the following type: * * typedef struct { * type *lock; // 'type := void' for the _0 variant * __VA_ARGS__; * } class_##name##_t; * * As above, both _lock and _unlock are statements, except this time '_T' will * be a pointer to the above struct. */ #define __DEFINE_UNLOCK_GUARD(_name, _type, _unlock, ...) \ typedef struct { \ _type *lock; \ __VA_ARGS__; \ } class_##_name##_t; \ \ static inline void class_##_name##_destructor(class_##_name##_t *_T) \ { \ if (_T->lock) { _unlock; } \ } #define __DEFINE_LOCK_GUARD_1(_name, _type, _lock) \ static inline class_##_name##_t class_##_name##_constructor(_type *l) \ { \ class_##_name##_t _t = { .lock = l }, *_T = &_t; \ _lock; \ return _t; \ } #define __DEFINE_LOCK_GUARD_0(_name, _lock) \ static inline class_##_name##_t class_##_name##_constructor(void) \ { \ class_##_name##_t _t = { .lock = (void*)1 }, \ *_T __maybe_unused = &_t; \ _lock; \ return _t; \ } #define DEFINE_LOCK_GUARD_1(_name, _type, _lock, _unlock, ...) \ __DEFINE_UNLOCK_GUARD(_name, _type, _unlock, __VA_ARGS__) \ __DEFINE_LOCK_GUARD_1(_name, _type, _lock) #define DEFINE_LOCK_GUARD_0(_name, _lock, _unlock, ...) \ __DEFINE_UNLOCK_GUARD(_name, void, _unlock, __VA_ARGS__) \ __DEFINE_LOCK_GUARD_0(_name, _lock) #endif /* __LINUX_GUARDS_H */ |