public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] trace_printk: replace _______STR with __UNIQUE_ID(STR)
@ 2026-04-29 16:57 Qian-Yu Lin
  2026-04-29 17:42 ` Steven Rostedt
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Qian-Yu Lin @ 2026-04-29 16:57 UTC (permalink / raw)
  To: rostedt, mhiramat
  Cc: mathieu.desnoyers, linux-kernel, linux-trace-kernel, Qian-Yu Lin

The macro trace_printk() uses a hardcoded identifier _______STR
within a statement expression, which can lead to variable name
shadowing if a caller happens to use the same name in its scope.

Following the pattern in commit 24ba53017e18 ("rcu: Replace ________p1
and _________p1 with __UNIQUE_ID(rcu)") and commit 589a9785ee3a
 ("min/max: remove sparse warnings when they're nested"), replace the
 hardcoded identifier with __UNIQUE_ID(STR).

Since __UNIQUE_ID() must be expanded once to remain consistent across
declaration and sizeof() within the statement expression, introduce a
nested helper macro ___trace_printk.

Signed-off-by: Qian-Yu Lin <tiffany019230@gmail.com>
---
 include/linux/trace_printk.h | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/linux/trace_printk.h b/include/linux/trace_printk.h
index 2670ec7f4262..060eccb40838 100644
--- a/include/linux/trace_printk.h
+++ b/include/linux/trace_printk.h
@@ -2,6 +2,7 @@
 #ifndef _LINUX_TRACE_PRINTK_H
 #define _LINUX_TRACE_PRINTK_H
 
+#include <linux/compiler.h>
 #include <linux/compiler_attributes.h>
 #include <linux/instruction_pointer.h>
 #include <linux/stddef.h>
@@ -84,15 +85,18 @@ do {									\
  * let gcc optimize the rest.
  */
 
-#define trace_printk(fmt, ...)				\
+#define ___trace_printk(fmt, str, ...)				\
 do {							\
-	char _______STR[] = __stringify((__VA_ARGS__));	\
-	if (sizeof(_______STR) > 3)			\
+	char str[] = __stringify((__VA_ARGS__));	\
+	if (sizeof(str) > 3)			\
 		do_trace_printk(fmt, ##__VA_ARGS__);	\
 	else						\
 		trace_puts(fmt);			\
 } while (0)
 
+#define trace_printk(fmt, ...) \
+	___trace_printk(fmt, __UNIQUE_ID(str), ##__VA_ARGS__)
+
 #define do_trace_printk(fmt, args...)					\
 do {									\
 	static const char *trace_printk_fmt __used			\
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH] trace_printk: replace _______STR with __UNIQUE_ID(STR)
  2026-04-29 16:57 [PATCH] trace_printk: replace _______STR with __UNIQUE_ID(STR) Qian-Yu Lin
@ 2026-04-29 17:42 ` Steven Rostedt
  2026-04-29 21:47   ` David Laight
  2026-05-01 14:40   ` Qian-Yu Lin
  2026-05-01 16:28 ` [PATCH v2] trace_printk: replace ___STR with compound literal Qian-Yu Lin
  2026-05-02  7:55 ` [PATCH v3] trace_printk: remove local variable for argument detection Qian-Yu Lin
  2 siblings, 2 replies; 12+ messages in thread
From: Steven Rostedt @ 2026-04-29 17:42 UTC (permalink / raw)
  To: Qian-Yu Lin; +Cc: mhiramat, mathieu.desnoyers, linux-kernel, linux-trace-kernel

On Thu, 30 Apr 2026 00:57:07 +0800
Qian-Yu Lin <tiffany019230@gmail.com> wrote:

> The macro trace_printk() uses a hardcoded identifier _______STR
> within a statement expression, which can lead to variable name
> shadowing if a caller happens to use the same name in its scope.

Has this ever been a problem?

> 
> Following the pattern in commit 24ba53017e18 ("rcu: Replace ________p1
> and _________p1 with __UNIQUE_ID(rcu)") and commit 589a9785ee3a
>  ("min/max: remove sparse warnings when they're nested"), replace the
>  hardcoded identifier with __UNIQUE_ID(STR).
> 
> Since __UNIQUE_ID() must be expanded once to remain consistent across
> declaration and sizeof() within the statement expression, introduce a
> nested helper macro ___trace_printk.

Hmm, so we are replacing one name with underscores with another name
with underscores?

> 
> Signed-off-by: Qian-Yu Lin <tiffany019230@gmail.com>
> ---
>  include/linux/trace_printk.h | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/include/linux/trace_printk.h b/include/linux/trace_printk.h
> index 2670ec7f4262..060eccb40838 100644
> --- a/include/linux/trace_printk.h
> +++ b/include/linux/trace_printk.h
> @@ -2,6 +2,7 @@
>  #ifndef _LINUX_TRACE_PRINTK_H
>  #define _LINUX_TRACE_PRINTK_H
>  
> +#include <linux/compiler.h>

People are already saying that trace_printk.h slows down the compile.
Does this add any overhead to the compile?

-- Steve


>  #include <linux/compiler_attributes.h>
>  #include <linux/instruction_pointer.h>
>  #include <linux/stddef.h>
> @@ -84,15 +85,18 @@ do {									\
>   * let gcc optimize the rest.
>   */
>  
> -#define trace_printk(fmt, ...)				\
> +#define ___trace_printk(fmt, str, ...)				\
>  do {							\
> -	char _______STR[] = __stringify((__VA_ARGS__));	\
> -	if (sizeof(_______STR) > 3)			\
> +	char str[] = __stringify((__VA_ARGS__));	\
> +	if (sizeof(str) > 3)			\
>  		do_trace_printk(fmt, ##__VA_ARGS__);	\
>  	else						\
>  		trace_puts(fmt);			\
>  } while (0)
>  
> +#define trace_printk(fmt, ...) \
> +	___trace_printk(fmt, __UNIQUE_ID(str), ##__VA_ARGS__)
> +
>  #define do_trace_printk(fmt, args...)					\
>  do {									\
>  	static const char *trace_printk_fmt __used			\


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] trace_printk: replace _______STR with __UNIQUE_ID(STR)
  2026-04-29 17:42 ` Steven Rostedt
@ 2026-04-29 21:47   ` David Laight
  2026-05-01 14:51     ` Qian-Yu Lin
  2026-05-01 14:40   ` Qian-Yu Lin
  1 sibling, 1 reply; 12+ messages in thread
From: David Laight @ 2026-04-29 21:47 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Qian-Yu Lin, mhiramat, mathieu.desnoyers, linux-kernel,
	linux-trace-kernel

On Wed, 29 Apr 2026 13:42:26 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:

> On Thu, 30 Apr 2026 00:57:07 +0800
> Qian-Yu Lin <tiffany019230@gmail.com> wrote:
> 
> > The macro trace_printk() uses a hardcoded identifier _______STR
> > within a statement expression, which can lead to variable name
> > shadowing if a caller happens to use the same name in its scope.  
> 
> Has this ever been a problem?
> 
> > 
> > Following the pattern in commit 24ba53017e18 ("rcu: Replace ________p1
> > and _________p1 with __UNIQUE_ID(rcu)") and commit 589a9785ee3a
> >  ("min/max: remove sparse warnings when they're nested"), replace the
> >  hardcoded identifier with __UNIQUE_ID(STR).

min and max do get nested - so it is important that the 'local'
variables have different names - otherwise you can get invalid expansions.

No one is going to have: trace_printk(fmt1, trace_printk(ftm2, ...), ...)
it just doesn't make sense.

There is a slight problem the ____________________________STR might
be used by an entirely different #define.
Just using _trace_printk_str[] would make this pretty unlikely.
It would also have the advantage of making the .i file a bit easier
to read, all the UNIQUE names in min/max output make it really hard
to see what the output actually means.

> > 
> > Since __UNIQUE_ID() must be expanded once to remain consistent across
> > declaration and sizeof() within the statement expression, introduce a
> > nested helper macro ___trace_printk.  
> 
> Hmm, so we are replacing one name with underscores with another name
> with underscores?
> 
> > 
> > Signed-off-by: Qian-Yu Lin <tiffany019230@gmail.com>
> > ---
> >  include/linux/trace_printk.h | 10 +++++++---
> >  1 file changed, 7 insertions(+), 3 deletions(-)
> > 
> > diff --git a/include/linux/trace_printk.h b/include/linux/trace_printk.h
> > index 2670ec7f4262..060eccb40838 100644
> > --- a/include/linux/trace_printk.h
> > +++ b/include/linux/trace_printk.h
> > @@ -2,6 +2,7 @@
> >  #ifndef _LINUX_TRACE_PRINTK_H
> >  #define _LINUX_TRACE_PRINTK_H
> >  
> > +#include <linux/compiler.h>  
> 
> People are already saying that trace_printk.h slows down the compile.
> Does this add any overhead to the compile?

A little - nothing is free.

	David

> 
> -- Steve
> 
> 
> >  #include <linux/compiler_attributes.h>
> >  #include <linux/instruction_pointer.h>
> >  #include <linux/stddef.h>
> > @@ -84,15 +85,18 @@ do {									\
> >   * let gcc optimize the rest.
> >   */
> >  
> > -#define trace_printk(fmt, ...)				\
> > +#define ___trace_printk(fmt, str, ...)				\
> >  do {							\
> > -	char _______STR[] = __stringify((__VA_ARGS__));	\
> > -	if (sizeof(_______STR) > 3)			\
> > +	char str[] = __stringify((__VA_ARGS__));	\
> > +	if (sizeof(str) > 3)			\
> >  		do_trace_printk(fmt, ##__VA_ARGS__);	\
> >  	else						\
> >  		trace_puts(fmt);			\
> >  } while (0)
> >  
> > +#define trace_printk(fmt, ...) \
> > +	___trace_printk(fmt, __UNIQUE_ID(str), ##__VA_ARGS__)
> > +
> >  #define do_trace_printk(fmt, args...)					\
> >  do {									\
> >  	static const char *trace_printk_fmt __used			\  
> 
> 


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] trace_printk: replace _______STR with __UNIQUE_ID(STR)
  2026-04-29 17:42 ` Steven Rostedt
  2026-04-29 21:47   ` David Laight
@ 2026-05-01 14:40   ` Qian-Yu Lin
  2026-05-01 15:19     ` Steven Rostedt
  2026-05-01 21:13     ` David Laight
  1 sibling, 2 replies; 12+ messages in thread
From: Qian-Yu Lin @ 2026-05-01 14:40 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: mhiramat, david.laight.linux, linux-kernel, linux-trace-kernel

On Wed, Apr 29, 2026 at 01:42:26PM -0400, Steven Rostedt wrote:
> On Thu, 30 Apr 2026 00:57:07 +0800
> Qian-Yu Lin <tiffany019230@gmail.com> wrote:
> 
> > The macro trace_printk() uses a hardcoded identifier _______STR
> > within a statement expression, which can lead to variable name
> > shadowing if a caller happens to use the same name in its scope.
> 
> Has this ever been a problem?
> 

No, this has not been a practical problem. However, the long-underscore
name ___STR is an indication of a potential shadowing risk.

> > 
> > Following the pattern in commit 24ba53017e18 ("rcu: Replace ________p1
> > and _________p1 with __UNIQUE_ID(rcu)") and commit 589a9785ee3a
> >  ("min/max: remove sparse warnings when they're nested"), replace the
> >  hardcoded identifier with __UNIQUE_ID(STR).
> > 
> > Since __UNIQUE_ID() must be expanded once to remain consistent across
> > declaration and sizeof() within the statement expression, introduce a
> > nested helper macro ___trace_printk.
> 
> Hmm, so we are replacing one name with underscores with another name
> with underscores?
> 
> > 
> > Signed-off-by: Qian-Yu Lin <tiffany019230@gmail.com>
> > ---
> >  include/linux/trace_printk.h | 10 +++++++---
> >  1 file changed, 7 insertions(+), 3 deletions(-)
> > 
> > diff --git a/include/linux/trace_printk.h b/include/linux/trace_printk.h
> > index 2670ec7f4262..060eccb40838 100644
> > --- a/include/linux/trace_printk.h
> > +++ b/include/linux/trace_printk.h
> > @@ -2,6 +2,7 @@
> >  #ifndef _LINUX_TRACE_PRINTK_H
> >  #define _LINUX_TRACE_PRINTK_H
> >  
> > +#include <linux/compiler.h>
> 
> People are already saying that trace_printk.h slows down the compile.
> Does this add any overhead to the compile?
> 
> -- Steve

Yes. I measured compile time of kernel/trace/ring_buffer_benchmark.o
after make clean on an x86_64 machine running Ubuntu 24.04 LTS:

  - Original _______STR:                 49.8s
  - v1 with __UNIQUE_ID (compiler.h):    53.5s
  - compound literal (no extra include): 33.2s

I propose using a compound literal in v2, which eliminates the local
variable entirely and requires no extra include:

#define trace_printk(fmt, ...)                          \
do {                                                    \
    if (sizeof((char[])                             \
        {__stringify((__VA_ARGS__))}) > 3)      \
        do_trace_printk(fmt, ##__VA_ARGS__);    \
    else                                            \
        trace_puts(fmt);                        \
} while (0)

This fully eliminates the shadowing risk without any compile overhead.

Qian-Yu

> 
> 
> >  #include <linux/compiler_attributes.h>
> >  #include <linux/instruction_pointer.h>
> >  #include <linux/stddef.h>
> > @@ -84,15 +85,18 @@ do {									\
> >   * let gcc optimize the rest.
> >   */
> >  
> > -#define trace_printk(fmt, ...)				\
> > +#define ___trace_printk(fmt, str, ...)				\
> >  do {							\
> > -	char _______STR[] = __stringify((__VA_ARGS__));	\
> > -	if (sizeof(_______STR) > 3)			\
> > +	char str[] = __stringify((__VA_ARGS__));	\
> > +	if (sizeof(str) > 3)			\
> >  		do_trace_printk(fmt, ##__VA_ARGS__);	\
> >  	else						\
> >  		trace_puts(fmt);			\
> >  } while (0)
> >  
> > +#define trace_printk(fmt, ...) \
> > +	___trace_printk(fmt, __UNIQUE_ID(str), ##__VA_ARGS__)
> > +
> >  #define do_trace_printk(fmt, args...)					\
> >  do {									\
> >  	static const char *trace_printk_fmt __used			\
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] trace_printk: replace _______STR with __UNIQUE_ID(STR)
  2026-04-29 21:47   ` David Laight
@ 2026-05-01 14:51     ` Qian-Yu Lin
  0 siblings, 0 replies; 12+ messages in thread
From: Qian-Yu Lin @ 2026-05-01 14:51 UTC (permalink / raw)
  To: David Laight; +Cc: rostedt, mhiramat, linux-kernel, linux-trace-kernel

On Wed, Apr 29, 2026 at 10:47:28PM +0100, David Laight wrote:
> On Wed, 29 Apr 2026 13:42:26 -0400
> Steven Rostedt <rostedt@goodmis.org> wrote:
> 
> > On Thu, 30 Apr 2026 00:57:07 +0800
> > Qian-Yu Lin <tiffany019230@gmail.com> wrote:
> > 
> > > The macro trace_printk() uses a hardcoded identifier _______STR
> > > within a statement expression, which can lead to variable name
> > > shadowing if a caller happens to use the same name in its scope.  
> > 
> > Has this ever been a problem?
> > 
> > > 
> > > Following the pattern in commit 24ba53017e18 ("rcu: Replace ________p1
> > > and _________p1 with __UNIQUE_ID(rcu)") and commit 589a9785ee3a
> > >  ("min/max: remove sparse warnings when they're nested"), replace the
> > >  hardcoded identifier with __UNIQUE_ID(STR).
> 
> min and max do get nested - so it is important that the 'local'
> variables have different names - otherwise you can get invalid expansions.
> 
> No one is going to have: trace_printk(fmt1, trace_printk(ftm2, ...), ...)
> it just doesn't make sense.
> 
> There is a slight problem the ____________________________STR might
> be used by an entirely different #define.
> Just using _trace_printk_str[] would make this pretty unlikely.
> It would also have the advantage of making the .i file a bit easier
> to read, all the UNIQUE names in min/max output make it really hard
> to see what the output actually means.
> 

Thank you for the suggestion. However, _trace_printk_str still carries
a theoretical shadowing risk if a caller happens to use the same name.

> > > 
> > > Since __UNIQUE_ID() must be expanded once to remain consistent across
> > > declaration and sizeof() within the statement expression, introduce a
> > > nested helper macro ___trace_printk.  
> > 
> > Hmm, so we are replacing one name with underscores with another name
> > with underscores?
> > 
> > > 
> > > Signed-off-by: Qian-Yu Lin <tiffany019230@gmail.com>
> > > ---
> > >  include/linux/trace_printk.h | 10 +++++++---
> > >  1 file changed, 7 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/include/linux/trace_printk.h b/include/linux/trace_printk.h
> > > index 2670ec7f4262..060eccb40838 100644
> > > --- a/include/linux/trace_printk.h
> > > +++ b/include/linux/trace_printk.h
> > > @@ -2,6 +2,7 @@
> > >  #ifndef _LINUX_TRACE_PRINTK_H
> > >  #define _LINUX_TRACE_PRINTK_H
> > >  
> > > +#include <linux/compiler.h>  
> > 
> > People are already saying that trace_printk.h slows down the compile.
> > Does this add any overhead to the compile?
> 
> A little - nothing is free.
> 
> 	David
> 

Indeed. I measured compile time of kernel/trace/ring_buffer_benchmark.o
after make clean on an x86_64 machine running Ubuntu 24.04 LTS:

  - Original _______STR:                 49.8s
  - v1 with __UNIQUE_ID (compiler.h):    53.5s
  - compound literal (no extra include): 33.2s

A compound literal eliminates the local variable entirely, removing
the shadowing risk without any extra include or compile overhead:

#define trace_printk(fmt, ...)                          \
do {                                                    \
    if (sizeof((char[])                             \
        {__stringify((__VA_ARGS__))}) > 3)      \
        do_trace_printk(fmt, ##__VA_ARGS__);    \
    else                                            \
        trace_puts(fmt);                        \
} while (0)

Qian-Yu

> > 
> > -- Steve
> > 
> > 
> > >  #include <linux/compiler_attributes.h>
> > >  #include <linux/instruction_pointer.h>
> > >  #include <linux/stddef.h>
> > > @@ -84,15 +85,18 @@ do {									\
> > >   * let gcc optimize the rest.
> > >   */
> > >  
> > > -#define trace_printk(fmt, ...)				\
> > > +#define ___trace_printk(fmt, str, ...)				\
> > >  do {							\
> > > -	char _______STR[] = __stringify((__VA_ARGS__));	\
> > > -	if (sizeof(_______STR) > 3)			\
> > > +	char str[] = __stringify((__VA_ARGS__));	\
> > > +	if (sizeof(str) > 3)			\
> > >  		do_trace_printk(fmt, ##__VA_ARGS__);	\
> > >  	else						\
> > >  		trace_puts(fmt);			\
> > >  } while (0)
> > >  
> > > +#define trace_printk(fmt, ...) \
> > > +	___trace_printk(fmt, __UNIQUE_ID(str), ##__VA_ARGS__)
> > > +
> > >  #define do_trace_printk(fmt, args...)					\
> > >  do {									\
> > >  	static const char *trace_printk_fmt __used			\  
> > 
> > 
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] trace_printk: replace _______STR with __UNIQUE_ID(STR)
  2026-05-01 14:40   ` Qian-Yu Lin
@ 2026-05-01 15:19     ` Steven Rostedt
  2026-05-01 16:17       ` Qian-Yu Lin
  2026-05-01 21:13     ` David Laight
  1 sibling, 1 reply; 12+ messages in thread
From: Steven Rostedt @ 2026-05-01 15:19 UTC (permalink / raw)
  To: Qian-Yu Lin
  Cc: mhiramat, david.laight.linux, linux-kernel, linux-trace-kernel

On Fri, 1 May 2026 22:40:17 +0800
Qian-Yu Lin <tiffany019230@gmail.com> wrote:

> I propose using a compound literal in v2, which eliminates the local
> variable entirely and requires no extra include:
> 
> #define trace_printk(fmt, ...)                          \
> do {                                                    \
>     if (sizeof((char[])                             \
>         {__stringify((__VA_ARGS__))}) > 3)      \
>         do_trace_printk(fmt, ##__VA_ARGS__);    \
>     else                                            \
>         trace_puts(fmt);                        \
> } while (0)
> 
> This fully eliminates the shadowing risk without any compile overhead.

Have you tested to make sure a string with no arguments still produces the
trace_puts() and one that has arguments calls do_trace_printk()?

I'm fine with that one if it still works.

-- Steve

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] trace_printk: replace _______STR with __UNIQUE_ID(STR)
  2026-05-01 15:19     ` Steven Rostedt
@ 2026-05-01 16:17       ` Qian-Yu Lin
  2026-05-01 16:21         ` Steven Rostedt
  0 siblings, 1 reply; 12+ messages in thread
From: Qian-Yu Lin @ 2026-05-01 16:17 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: mhiramat, david.laight.linux, linux-kernel, linux-trace-kernel

On Fri, May 01, 2026 at 11:19:39AM -0400, Steven Rostedt wrote:
> On Fri, 1 May 2026 22:40:17 +0800
> Qian-Yu Lin <tiffany019230@gmail.com> wrote:
> 
> > I propose using a compound literal in v2, which eliminates the local
> > variable entirely and requires no extra include:
> > 
> > #define trace_printk(fmt, ...)                          \
> > do {                                                    \
> >     if (sizeof((char[])                             \
> >         {__stringify((__VA_ARGS__))}) > 3)      \
> >         do_trace_printk(fmt, ##__VA_ARGS__);    \
> >     else                                            \
> >         trace_puts(fmt);                        \
> > } while (0)
> > 
> > This fully eliminates the shadowing risk without any compile overhead.
> 
> Have you tested to make sure a string with no arguments still produces the
> trace_puts() and one that has arguments calls do_trace_printk()?
> 
> I'm fine with that one if it still works.
> 
> -- Steve

Yes, I verified it with the preprocessor output. I created a minimal
test file:

// kernel/trace/test_trace_printk.c
#include <linux/trace_printk.h>

void test(void) {
    trace_printk("no args\n");
    trace_printk("with arg %d\n", 42);
}

Then ran make kernel/trace/test_trace_printk.i.

The no-args case has sizeof((char[]){"()"}) which is 3, so 3 > 3 is
false and it falls through to trace_bputs/trace_puts.

The args case has sizeof((char[]){"(42)"}) which is 5, so 5 > 3 is
true and it goes to trace_bprintk/trace_printk with the argument
42 correctly passed through.

Qian-Yu

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] trace_printk: replace _______STR with __UNIQUE_ID(STR)
  2026-05-01 16:17       ` Qian-Yu Lin
@ 2026-05-01 16:21         ` Steven Rostedt
  0 siblings, 0 replies; 12+ messages in thread
From: Steven Rostedt @ 2026-05-01 16:21 UTC (permalink / raw)
  To: Qian-Yu Lin
  Cc: mhiramat, david.laight.linux, linux-kernel, linux-trace-kernel

On Sat, 2 May 2026 00:17:50 +0800
Qian-Yu Lin <tiffany019230@gmail.com> wrote:

> Yes, I verified it with the preprocessor output. I created a minimal
> test file:
> 
> // kernel/trace/test_trace_printk.c
> #include <linux/trace_printk.h>
> 
> void test(void) {
>     trace_printk("no args\n");
>     trace_printk("with arg %d\n", 42);
> }
> 
> Then ran make kernel/trace/test_trace_printk.i.
> 
> The no-args case has sizeof((char[]){"()"}) which is 3, so 3 > 3 is
> false and it falls through to trace_bputs/trace_puts.
> 
> The args case has sizeof((char[]){"(42)"}) which is 5, so 5 > 3 is
> true and it goes to trace_bprintk/trace_printk with the argument
> 42 correctly passed through.

Thanks. When I test, I do the same but just compile down to an object file
and run objdump and look at which functions were called.

-- Steve

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v2] trace_printk: replace ___STR with compound literal
  2026-04-29 16:57 [PATCH] trace_printk: replace _______STR with __UNIQUE_ID(STR) Qian-Yu Lin
  2026-04-29 17:42 ` Steven Rostedt
@ 2026-05-01 16:28 ` Qian-Yu Lin
  2026-05-02  7:55 ` [PATCH v3] trace_printk: remove local variable for argument detection Qian-Yu Lin
  2 siblings, 0 replies; 12+ messages in thread
From: Qian-Yu Lin @ 2026-05-01 16:28 UTC (permalink / raw)
  To: rostedt, mhiramat
  Cc: mathieu.desnoyers, david.laight.linux, linux-kernel,
	linux-trace-kernel, Qian-Yu Lin

The macro trace_printk() uses a hardcoded identifier ___STR
within a statement expression, which can lead to variable name
shadowing if a caller happens to use the same name in its scope.

Replace the hardcoded identifier with a compound literal, which
eliminates the local variable entirely and removes any shadowing
risk without requiring an extra include or helper macro.

Since trace_printk() is never nested, __UNIQUE_ID() provides no
practical benefit here. The compound literal approach is simpler
and has no compile time overhead, unlike the v1 approach which
added #include <linux/compiler.h>.

Signed-off-by: Qian-Yu Lin <tiffany019230@gmail.com>
---
 include/linux/trace_printk.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/include/linux/trace_printk.h b/include/linux/trace_printk.h
index 2670ec7f4262..7a4f6711834f 100644
--- a/include/linux/trace_printk.h
+++ b/include/linux/trace_printk.h
@@ -86,8 +86,7 @@ do {									\
 
 #define trace_printk(fmt, ...)				\
 do {							\
-	char _______STR[] = __stringify((__VA_ARGS__));	\
-	if (sizeof(_______STR) > 3)			\
+	if (sizeof((char[]){__stringify((__VA_ARGS__))}) > 3)			\
 		do_trace_printk(fmt, ##__VA_ARGS__);	\
 	else						\
 		trace_puts(fmt);			\
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH] trace_printk: replace _______STR with __UNIQUE_ID(STR)
  2026-05-01 14:40   ` Qian-Yu Lin
  2026-05-01 15:19     ` Steven Rostedt
@ 2026-05-01 21:13     ` David Laight
  2026-05-02  7:37       ` Qian-Yu Lin
  1 sibling, 1 reply; 12+ messages in thread
From: David Laight @ 2026-05-01 21:13 UTC (permalink / raw)
  To: Qian-Yu Lin; +Cc: Steven Rostedt, mhiramat, linux-kernel, linux-trace-kernel

On Fri, 1 May 2026 22:40:17 +0800
Qian-Yu Lin <tiffany019230@gmail.com> wrote:

...
> Yes. I measured compile time of kernel/trace/ring_buffer_benchmark.o
> after make clean on an x86_64 machine running Ubuntu 24.04 LTS:
> 
>   - Original _______STR:                 49.8s
>   - v1 with __UNIQUE_ID (compiler.h):    53.5s
>   - compound literal (no extra include): 33.2s

That difference looks far to big to me.
And the times are far too large to be measuring the actual compile time.

> 
> I propose using a compound literal in v2, which eliminates the local
> variable entirely and requires no extra include:
> 
> #define trace_printk(fmt, ...)                          \
> do {                                                    \
>     if (sizeof((char[])                             \
>         {__stringify((__VA_ARGS__))}) > 3)      \
>         do_trace_printk(fmt, ##__VA_ARGS__);    \

There has to be a better way to align that code.
Although you should be able to use:
	if (sizeof __stringify((__VA_ARGS__)) > 3)
(I've omitted one set of parenthesis for clarity)

You could change __stringify() to work with __VA_ARGS__ the you don't need
the extra (); this works fine:
#define _x(...) #__VA_ARGS__
#define x(...) _x(__VA_ARGS__)
#define z abcd
int a = sizeof x(z, v); /* 8 */
See: https://godbolt.org/z/zo4h4nr9b

-- David

>     else                                            \
>         trace_puts(fmt);                        \
> } while (0)
> 
> This fully eliminates the shadowing risk without any compile overhead.
> 
> Qian-Yu
> 
> > 
> >   
> > >  #include <linux/compiler_attributes.h>
> > >  #include <linux/instruction_pointer.h>
> > >  #include <linux/stddef.h>
> > > @@ -84,15 +85,18 @@ do {									\
> > >   * let gcc optimize the rest.
> > >   */
> > >  
> > > -#define trace_printk(fmt, ...)				\
> > > +#define ___trace_printk(fmt, str, ...)				\
> > >  do {							\
> > > -	char _______STR[] = __stringify((__VA_ARGS__));	\
> > > -	if (sizeof(_______STR) > 3)			\
> > > +	char str[] = __stringify((__VA_ARGS__));	\
> > > +	if (sizeof(str) > 3)			\
> > >  		do_trace_printk(fmt, ##__VA_ARGS__);	\
> > >  	else						\
> > >  		trace_puts(fmt);			\
> > >  } while (0)
> > >  
> > > +#define trace_printk(fmt, ...) \
> > > +	___trace_printk(fmt, __UNIQUE_ID(str), ##__VA_ARGS__)
> > > +
> > >  #define do_trace_printk(fmt, args...)					\
> > >  do {									\
> > >  	static const char *trace_printk_fmt __used			\  
> >   


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] trace_printk: replace _______STR with __UNIQUE_ID(STR)
  2026-05-01 21:13     ` David Laight
@ 2026-05-02  7:37       ` Qian-Yu Lin
  0 siblings, 0 replies; 12+ messages in thread
From: Qian-Yu Lin @ 2026-05-02  7:37 UTC (permalink / raw)
  To: David Laight; +Cc: rostedt, mhiramat, linux-kernel, linux-trace-kernel

On Fri, May 01, 2026 at 10:13:15PM +0100, David Laight wrote:
> On Fri, 1 May 2026 22:40:17 +0800
> Qian-Yu Lin <tiffany019230@gmail.com> wrote:
> 
> ...
> > Yes. I measured compile time of kernel/trace/ring_buffer_benchmark.o
> > after make clean on an x86_64 machine running Ubuntu 24.04 LTS:
> > 
> >   - Original _______STR:                 49.8s
> >   - v1 with __UNIQUE_ID (compiler.h):    53.5s
> >   - compound literal (no extra include): 33.2s
> 
> That difference looks far to big to me.
> And the times are far too large to be measuring the actual compile time.
> 

You're right, my earlier measurements included dependency rebuilds
after make clean. I re-measured using touch to isolate the actual
compile time of ring_buffer_benchmark.o on x86_64:

  - Original ___STR:                        1.757s
  - v1 with __UNIQUE_ID (compiler.h):       1.836s
  - sizeof __stringify (your suggestion):   1.781s

> > 
> > I propose using a compound literal in v2, which eliminates the local
> > variable entirely and requires no extra include:
> > 
> > #define trace_printk(fmt, ...)                          \
> > do {                                                    \
> >     if (sizeof((char[])                             \
> >         {__stringify((__VA_ARGS__))}) > 3)      \
> >         do_trace_printk(fmt, ##__VA_ARGS__);    \
> 
> There has to be a better way to align that code.
> Although you should be able to use:
> 	if (sizeof __stringify((__VA_ARGS__)) > 3)
> (I've omitted one set of parenthesis for clarity)
> 
> You could change __stringify() to work with __VA_ARGS__ the you don't need
> the extra (); this works fine:
> #define _x(...) #__VA_ARGS__
> #define x(...) _x(__VA_ARGS__)
> #define z abcd
> int a = sizeof x(z, v); /* 8 */
> See: https://godbolt.org/z/zo4h4nr9b
> 
> -- David
> 

Yes, this works. I verified with objdump on the
samples/trace_printk module that all four cases branch correctly:
__trace_bputs, __trace_puts, __trace_bprintk, and __trace_printk.

I'll use this form in v3 since it's simpler than the compound literal.

> >     else                                            \
> >         trace_puts(fmt);                        \
> > } while (0)
> > 
> > This fully eliminates the shadowing risk without any compile overhead.
> > 
> > Qian-Yu
> > 
> > > 
> > >   
> > > >  #include <linux/compiler_attributes.h>
> > > >  #include <linux/instruction_pointer.h>
> > > >  #include <linux/stddef.h>
> > > > @@ -84,15 +85,18 @@ do {									\
> > > >   * let gcc optimize the rest.
> > > >   */
> > > >  
> > > > -#define trace_printk(fmt, ...)				\
> > > > +#define ___trace_printk(fmt, str, ...)				\
> > > >  do {							\
> > > > -	char _______STR[] = __stringify((__VA_ARGS__));	\
> > > > -	if (sizeof(_______STR) > 3)			\
> > > > +	char str[] = __stringify((__VA_ARGS__));	\
> > > > +	if (sizeof(str) > 3)			\
> > > >  		do_trace_printk(fmt, ##__VA_ARGS__);	\
> > > >  	else						\
> > > >  		trace_puts(fmt);			\
> > > >  } while (0)
> > > >  
> > > > +#define trace_printk(fmt, ...) \
> > > > +	___trace_printk(fmt, __UNIQUE_ID(str), ##__VA_ARGS__)
> > > > +
> > > >  #define do_trace_printk(fmt, args...)					\
> > > >  do {									\
> > > >  	static const char *trace_printk_fmt __used			\  
> > >   
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v3] trace_printk: remove local variable for argument detection
  2026-04-29 16:57 [PATCH] trace_printk: replace _______STR with __UNIQUE_ID(STR) Qian-Yu Lin
  2026-04-29 17:42 ` Steven Rostedt
  2026-05-01 16:28 ` [PATCH v2] trace_printk: replace ___STR with compound literal Qian-Yu Lin
@ 2026-05-02  7:55 ` Qian-Yu Lin
  2 siblings, 0 replies; 12+ messages in thread
From: Qian-Yu Lin @ 2026-05-02  7:55 UTC (permalink / raw)
  To: rostedt
  Cc: mhiramat, david.laight.linux, linux-kernel, linux-trace-kernel,
	Qian-Yu Lin

The trace_printk() macro uses a local variable _______STR to detect
whether variadic arguments are present. This name can shadow outer
variables.

Replace the local variable with sizeof applied directly to the
stringified arguments:

  if (sizeof __stringify((__VA_ARGS__)) > 3)

This eliminates the shadowing risk entirely without introducing
any additional includes or local variables.

Verified with objdump on samples/trace_printk that all four cases
branch correctly: __trace_bputs, __trace_puts, __trace_bprintk,
and __trace_printk.

Suggested-by: David Laight <david.laight.linux@gmail.com>
Signed-off-by: Qian-Yu Lin <tiffany019230@gmail.com>
---
 include/linux/trace_printk.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/include/linux/trace_printk.h b/include/linux/trace_printk.h
index 2670ec7f4262..3d54f440dccf 100644
--- a/include/linux/trace_printk.h
+++ b/include/linux/trace_printk.h
@@ -86,8 +86,7 @@ do {									\
 
 #define trace_printk(fmt, ...)				\
 do {							\
-	char _______STR[] = __stringify((__VA_ARGS__));	\
-	if (sizeof(_______STR) > 3)			\
+	if (sizeof __stringify((__VA_ARGS__)) > 3)		\
 		do_trace_printk(fmt, ##__VA_ARGS__);	\
 	else						\
 		trace_puts(fmt);			\
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-05-02  7:56 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-29 16:57 [PATCH] trace_printk: replace _______STR with __UNIQUE_ID(STR) Qian-Yu Lin
2026-04-29 17:42 ` Steven Rostedt
2026-04-29 21:47   ` David Laight
2026-05-01 14:51     ` Qian-Yu Lin
2026-05-01 14:40   ` Qian-Yu Lin
2026-05-01 15:19     ` Steven Rostedt
2026-05-01 16:17       ` Qian-Yu Lin
2026-05-01 16:21         ` Steven Rostedt
2026-05-01 21:13     ` David Laight
2026-05-02  7:37       ` Qian-Yu Lin
2026-05-01 16:28 ` [PATCH v2] trace_printk: replace ___STR with compound literal Qian-Yu Lin
2026-05-02  7:55 ` [PATCH v3] trace_printk: remove local variable for argument detection Qian-Yu Lin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox