mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 04:21:09 -04:00
cleanup: Optimize guards
Andrew reported that a guard() conversion of zone_lock increased the code size unnecessarily. It turns out the unconditional __GUARD_IS_ERR() is to blame. As explored earlier [1], __GUARD_IS_ERR(), similar to IS_ERR_OR_NULL(), generates somewhat sub-optimal code. However, looking at things again, it is possible to avoid doing the __GUARD_IS_ERR() unconditionally. Revert the normal destructors to a simple NULL test and only add the IS_ERR bit to COND guards. This cures the reported overhead; as compiled by GCC-16: page_alloc.o: pre: Total: Before=45299, After=45371, chg +0.16% post: Total: Before=45299, After=45026, chg -0.60% [1] https://lkml.kernel.org/r/20250513085001.GC25891@noisy.programming.kicks-ass.net Reported-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Tested-by: Dan Williams <dan.j.williams@intel.com> Link: https://patch.msgid.link/20260309164516.GE606826@noisy.programming.kicks-ass.net
This commit is contained in:
@@ -286,15 +286,18 @@ static __always_inline _type class_##_name##_constructor(_init_args) \
|
||||
__no_context_analysis \
|
||||
{ _type t = _init; return t; }
|
||||
|
||||
#define EXTEND_CLASS(_name, ext, _init, _init_args...) \
|
||||
typedef lock_##_name##_t lock_##_name##ext##_t; \
|
||||
#define EXTEND_CLASS_COND(_name, ext, _cond, _init, _init_args...) \
|
||||
typedef lock_##_name##_t lock_##_name##ext##_t; \
|
||||
typedef class_##_name##_t class_##_name##ext##_t; \
|
||||
static __always_inline void class_##_name##ext##_destructor(class_##_name##_t *p) \
|
||||
{ class_##_name##_destructor(p); } \
|
||||
static __always_inline void class_##_name##ext##_destructor(class_##_name##_t *_T) \
|
||||
{ if (_cond) return; class_##_name##_destructor(_T); } \
|
||||
static __always_inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \
|
||||
__no_context_analysis \
|
||||
{ class_##_name##_t t = _init; return t; }
|
||||
|
||||
#define EXTEND_CLASS(_name, ext, _init, _init_args...) \
|
||||
EXTEND_CLASS_COND(_name, ext, 0, _init, _init_args)
|
||||
|
||||
#define CLASS(_name, var) \
|
||||
class_##_name##_t var __cleanup(class_##_name##_destructor) = \
|
||||
class_##_name##_constructor
|
||||
@@ -394,12 +397,12 @@ static __maybe_unused const bool class_##_name##_is_conditional = _is_cond
|
||||
__DEFINE_GUARD_LOCK_PTR(_name, _T)
|
||||
|
||||
#define DEFINE_GUARD(_name, _type, _lock, _unlock) \
|
||||
DEFINE_CLASS(_name, _type, if (!__GUARD_IS_ERR(_T)) { _unlock; }, ({ _lock; _T; }), _type _T); \
|
||||
DEFINE_CLASS(_name, _type, if (_T) { _unlock; }, ({ _lock; _T; }), _type _T); \
|
||||
DEFINE_CLASS_IS_GUARD(_name)
|
||||
|
||||
#define DEFINE_GUARD_COND_4(_name, _ext, _lock, _cond) \
|
||||
__DEFINE_CLASS_IS_CONDITIONAL(_name##_ext, true); \
|
||||
EXTEND_CLASS(_name, _ext, \
|
||||
EXTEND_CLASS_COND(_name, _ext, __GUARD_IS_ERR(*_T), \
|
||||
({ void *_t = _T; int _RET = (_lock); if (_T && !(_cond)) _t = ERR_PTR(_RET); _t; }), \
|
||||
class_##_name##_t _T) \
|
||||
static __always_inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t *_T) \
|
||||
@@ -488,7 +491,7 @@ typedef struct { \
|
||||
static __always_inline void class_##_name##_destructor(class_##_name##_t *_T) \
|
||||
__no_context_analysis \
|
||||
{ \
|
||||
if (!__GUARD_IS_ERR(_T->lock)) { _unlock; } \
|
||||
if (_T->lock) { _unlock; } \
|
||||
} \
|
||||
\
|
||||
__DEFINE_GUARD_LOCK_PTR(_name, &_T->lock)
|
||||
@@ -565,7 +568,7 @@ __DEFINE_LOCK_GUARD_0(_name, _lock)
|
||||
|
||||
#define DEFINE_LOCK_GUARD_1_COND_4(_name, _ext, _lock, _cond) \
|
||||
__DEFINE_CLASS_IS_CONDITIONAL(_name##_ext, true); \
|
||||
EXTEND_CLASS(_name, _ext, \
|
||||
EXTEND_CLASS_COND(_name, _ext, __GUARD_IS_ERR(_T->lock), \
|
||||
({ class_##_name##_t _t = { .lock = l }, *_T = &_t;\
|
||||
int _RET = (_lock); \
|
||||
if (_T->lock && !(_cond)) _T->lock = ERR_PTR(_RET);\
|
||||
|
||||
Reference in New Issue
Block a user