27
votes

In multiple ARM back-end of Linux, I'm seeing in files clkdev.h this macro definition:

#define __clk_get(clk) ({ 1; })

See for example ./arch/arm/mach-versatile/include/mach/clkdev.h

This macro is using GCC extension Statements and Declarations in Expressions

Later this macro is used in file ./drivers/clk/clkdev.c, in function clk_get_sys()

 if (cl && !__clk_get(cl->clk))
         cl = NULL;

I'm wondering why not using here a simple macro:

#define __clk_get(clk) (1)

EDIT:

I've found some other usage of this construct throughout the kernel sources using the following grep pattern:

grep -R '({[[:space:]]*[a-zA-Z0-9_()+=/!&*>., ?:-]\+[[:space:]]*;[[:space:]]*})' .

Here's some of the matches:

./kernel/trace/trace_selftest.c:# define trace_selftest_startup_dynamic_tracing(trace, tr, func) ({ 0; })
./kernel/profile.c:#define create_hash_tables()         ({ 0; })
./include/asm-generic/bug.h: * Use of ({0;}) because WARN_ON_SMP(x) may be used either as
./include/asm-generic/bug.h:# define WARN_ON_SMP(x)         ({0;})
./include/linux/key.h:#define key_get(k)            ({ NULL; })
./include/linux/key.h:#define key_get(k)            ({ NULL; })
./include/linux/audit.h:#define audit_alloc(t) ({ 0; })
./include/linux/audit.h:#define audit_bprm(p) ({ 0; })
./include/linux/audit.h:#define audit_sockaddr(len, addr) ({ 0; })
./include/linux/audit.h:#define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; })
./include/linux/audit.h:#define audit_log_start(c,g,t) ({ NULL; })
./include/linux/atalk.h:#define atalk_proc_init()   ({ 0; })
./include/linux/ftrace.h:#define register_ftrace_function(ops) ({ 0; })
./include/linux/ftrace.h:#define unregister_ftrace_function(ops) ({ 0; })
./include/linux/ftrace.h:#define ftrace_regex_open(ops, flag, inod, file) ({ -ENODEV; })
./include/linux/ftrace.h:#define ftrace_set_filter(ops, buf, len, reset) ({ -ENODEV; })
./include/linux/ftrace.h:#define ftrace_set_notrace(ops, buf, len, reset) ({ -ENODEV; })
./include/linux/cpu.h:#define unregister_hotcpu_notifier(nb)    ({ (void)(nb); })
./include/linux/proc_fs.h:#define proc_net_fops_create(net, name, mode, fops)  ({ (void)(mode), NULL; })
./arch/powerpc/include/asm/pgtable-ppc64.h:#define pgd_set(pgdp, pudp)  ({pgd_val(*(pgdp)) = (unsigned long)(pudp);})
./arch/sh/math-emu/math.c:#define WRITE(d,a)    ({if(put_user(d, (typeof (d)*)a)) return -EFAULT;})
./arch/sh/math-emu/math.c:#define READ(d,a) ({if(get_user(d, (typeof (d)*)a)) return -EFAULT;})
[...]

Note: the construct ({if(put_user(d, (typeof (d)*)a)) return -EFAULT;}) seems to be a good usage of the compound statement. But this can also be replaced by more typical do { if(put_user(d, (typeof (d)*)a)) return -EFAULT; } while(0)

One match returned by grep is interesting: in ./include/asm-generic/bug.h there's a comment of usage of ({ 0; }). This is quite the same answer of AndreyT.

Indeed, one cannot use ((void)0), since it won't be usable as a r-value. ({ 0; }) is working in each case.

So if you have a macro that can used like a function returning a value that can be used or not, the compound statement seems to be your only option.

But __clkget() is never used as anything else as a r-value

Some links

3
My guess is there used to be some meat to the macro, and at some point someone hacked it to always evaluate to 1 without removing the GCC extension paren-bracket syntax. - phonetagger
No, now I think maybe the GCC extension paren-bracket syntax may defeat a "conditional expression always true" warning? - phonetagger
@phonetagger Is that a gcc warning? But I do see a MSVC C4127 warning is possible. - Joseph Quinsey
@JosephQuinsey - I don't get such a warning myself, but a guy who works with me keeps making tweaks to code everybody else checks in because his version of GCC on his own linux box is much newer than the version everybody else uses on the server, and everybody else's normal coding practices apparently don't work so well (in terms of warnings) on whatever version he uses. I don't know what version he uses. - phonetagger
@H2CO3 I don't think anyone can compile the vanilla Linux kernel with any Microsoft products. - Alvin Wong

3 Answers

9
votes

I notice that in -Wall mode a standalone (1); expression statement generates a "statement with no effect" warning, while a standalone ({ 1; }); expression statement produces no warnings.

Maybe somewhere in the code they somehow end up with standalone __clk_get calls that ignore the result. The (1) definition would result in warning for such calls, while ({ 1; }) keeps it quiet while producing the same effect in other contexts.

8
votes

Why this macro is defined as ({ 1; })?

It all depends on the programmer's coding style. All it does is return the value 1. For example, on x86 arch in "include/asm-generic/clkdev.h", __clk_get is defined as

static inline int __clk_get(struct clk *clk) { return 1; }

Also in linux/arch/c6x/include/asm/clkdev.h

static inline int __clk_get(struct clk *clk)
{
        return 1;
}
0
votes

A possible explanation is to prevent usage in undesirable situations.
This is useful to improve code portability - if another architecture's implementation of the macro would fail, we want this one to fail too.

Example: static int x = __clk_get(clk); - there's no sense in statically initializing with the clock.
With #define __clk_get(clk) (1), it will work.
With #define __clk_get(clk) ({ 1; }), it will fail.