From: Alessandro Carminati <[email protected]>

KUnit support is not consistently present across distributions, some
include it in their stock kernels, while others do not.
While both KUNIT and KUNIT_SUPPRESS_BACKTRACE can be considered debug
features, the fact that some distros ship with KUnit enabled means it's
important to minimize the runtime impact of this patch.

To that end, this patch uses static branching to minimize code size
and runtime overhead when no suppressions are active. In that case,
the static branch compiles to a single no-op instruction (5 bytes on
x86), avoiding any memory loads or branch prediction overhead. The
branch is automatically enabled when the first suppression starts and
disabled when the last suppression ends.

Signed-off-by: Alessandro Carminati <[email protected]>
Signed-off-by: Albert Esteve <[email protected]>
---
 lib/kunit/bug.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/lib/kunit/bug.c b/lib/kunit/bug.c
index 53c98e225a895..9c2c4ee013d92 100644
--- a/lib/kunit/bug.c
+++ b/lib/kunit/bug.c
@@ -7,17 +7,25 @@
  */
 
 #include <kunit/bug.h>
+#include <linux/atomic.h>
 #include <linux/export.h>
 #include <linux/instrumentation.h>
+#include <linux/jump_label.h>
 #include <linux/rculist.h>
 #include <linux/string.h>
 
 #ifdef CONFIG_KUNIT_SUPPRESS_BACKTRACE
 
 static LIST_HEAD(suppressed_warnings);
+static atomic_t suppressed_symbols_cnt = ATOMIC_INIT(0);
+
+DEFINE_STATIC_KEY_FALSE(kunit_suppress_warnings_key);
+EXPORT_SYMBOL_GPL(kunit_suppress_warnings_key);
 
 void __kunit_start_suppress_warning(struct __suppressed_warning *warning)
 {
+       if (atomic_inc_return(&suppressed_symbols_cnt) == 1)
+               static_branch_enable(&kunit_suppress_warnings_key);
        list_add_rcu(&warning->node, &suppressed_warnings);
 }
 EXPORT_SYMBOL_GPL(__kunit_start_suppress_warning);
@@ -26,6 +34,8 @@ void __kunit_end_suppress_warning(struct __suppressed_warning 
*warning)
 {
        list_del_rcu(&warning->node);
        synchronize_rcu(); /* Wait for readers to finish */
+       if (atomic_dec_return(&suppressed_symbols_cnt) == 0)
+               static_branch_disable(&kunit_suppress_warnings_key);
 }
 EXPORT_SYMBOL_GPL(__kunit_end_suppress_warning);
 
@@ -49,6 +59,8 @@ noinstr bool __kunit_is_suppressed_warning(const char 
*function)
 {
        bool ret;
 
+       if (!static_branch_unlikely(&kunit_suppress_warnings_key))
+               return false;
        instrumentation_begin();
        ret = __kunit_check_suppress(function);
        instrumentation_end();

-- 
2.52.0


Reply via email to