Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

  • http://www.toofishes.net/blog/gcc-compound-statement-expressions/
  • Abstruse #define macro encountered in Linux kernel source
  • macro: does #define a(b) ({... c;}) means a(b) returns c?
  • Why do we need parentheses around block macro?
  • Are compound statements (blocks) surrounded by parens expressions in ANSI C?
like image 509
Yann Droneaud Avatar asked Dec 18 '12 17:12

Yann Droneaud


People also ask

How do you check if a macro is defined?

Inside of a C source file, you can use the #ifdef macro to check if a macro is defined.

How to define macro variable in C?

In the C Programming Language, the #define directive allows the definition of macros within your source code. These macro definitions allow constant values to be declared for use throughout your code. Macro definitions are not variables and cannot be changed by your program code like variables.

What is macro and how do you define it?

A macro is an automated input sequence that imitates keystrokes or mouse actions. A macro is typically used to replace a repetitive series of keyboard and mouse actions and used often in spreadsheets and word processing applications like MS Excel and MS Word. The file extension of a macro is commonly . MAC.

What is the data type of macro in C?

There are two kinds of macros. They differ mostly in what they look like when they are used. Object-like macros resemble data objects when used, function-like macros resemble function calls. You may define any valid identifier as a macro, even if it is a C keyword.


1 Answers

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.

like image 83
AnT Avatar answered Sep 19 '22 21:09

AnT