Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+11 -8
+11 -8
include/linux/cleanup.h
··· 286 286 __no_context_analysis \ 287 287 { _type t = _init; return t; } 288 288 289 - #define EXTEND_CLASS(_name, ext, _init, _init_args...) \ 290 - typedef lock_##_name##_t lock_##_name##ext##_t; \ 289 + #define EXTEND_CLASS_COND(_name, ext, _cond, _init, _init_args...) \ 290 + typedef lock_##_name##_t lock_##_name##ext##_t; \ 291 291 typedef class_##_name##_t class_##_name##ext##_t; \ 292 - static __always_inline void class_##_name##ext##_destructor(class_##_name##_t *p) \ 293 - { class_##_name##_destructor(p); } \ 292 + static __always_inline void class_##_name##ext##_destructor(class_##_name##_t *_T) \ 293 + { if (_cond) return; class_##_name##_destructor(_T); } \ 294 294 static __always_inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \ 295 295 __no_context_analysis \ 296 296 { class_##_name##_t t = _init; return t; } 297 + 298 + #define EXTEND_CLASS(_name, ext, _init, _init_args...) \ 299 + EXTEND_CLASS_COND(_name, ext, 0, _init, _init_args) 297 300 298 301 #define CLASS(_name, var) \ 299 302 class_##_name##_t var __cleanup(class_##_name##_destructor) = \ ··· 397 394 __DEFINE_GUARD_LOCK_PTR(_name, _T) 398 395 399 396 #define DEFINE_GUARD(_name, _type, _lock, _unlock) \ 400 - DEFINE_CLASS(_name, _type, if (!__GUARD_IS_ERR(_T)) { _unlock; }, ({ _lock; _T; }), _type _T); \ 397 + DEFINE_CLASS(_name, _type, if (_T) { _unlock; }, ({ _lock; _T; }), _type _T); \ 401 398 DEFINE_CLASS_IS_GUARD(_name) 402 399 403 400 #define DEFINE_GUARD_COND_4(_name, _ext, _lock, _cond) \ 404 401 __DEFINE_CLASS_IS_CONDITIONAL(_name##_ext, true); \ 405 - EXTEND_CLASS(_name, _ext, \ 402 + EXTEND_CLASS_COND(_name, _ext, __GUARD_IS_ERR(*_T), \ 406 403 ({ void *_t = _T; int _RET = (_lock); if (_T && !(_cond)) _t = ERR_PTR(_RET); _t; }), \ 407 404 class_##_name##_t _T) \ 408 405 static __always_inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t *_T) \ ··· 491 488 static __always_inline void class_##_name##_destructor(class_##_name##_t *_T) \ 492 489 __no_context_analysis \ 493 490 { \ 494 - if (!__GUARD_IS_ERR(_T->lock)) { _unlock; } \ 491 + if (_T->lock) { _unlock; } \ 495 492 } \ 496 493 \ 497 494 __DEFINE_GUARD_LOCK_PTR(_name, &_T->lock) ··· 568 565 569 566 #define DEFINE_LOCK_GUARD_1_COND_4(_name, _ext, _lock, _cond) \ 570 567 __DEFINE_CLASS_IS_CONDITIONAL(_name##_ext, true); \ 571 - EXTEND_CLASS(_name, _ext, \ 568 + EXTEND_CLASS_COND(_name, _ext, __GUARD_IS_ERR(_T->lock), \ 572 569 ({ class_##_name##_t _t = { .lock = l }, *_T = &_t;\ 573 570 int _RET = (_lock); \ 574 571 if (_T->lock && !(_cond)) _T->lock = ERR_PTR(_RET);\