utiliza una ques que programada macro investigar ejemplos cuando caracteristicas aplicaciones c linux gcc macros linux-kernel

una - ¿Por qué esta macro se define como({1;})?



que es una macro programada (3)

¿Por qué esta macro se define como ({1;})?

Todo depende del estilo de codificación del programador. Todo lo que hace es devolver el valor 1. Por ejemplo, en el arco x86 en " include/asm-generic/clkdev.h ", __clk_get se define como

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

También en linux / arch / c6x / include / asm / clkdev.h

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

En múltiples back-end ARM de Linux, estoy viendo en los archivos clkdev.h esta definición de macro:

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

Véase, por ejemplo, ./arch/arm/mach-versatile/include/mach/clkdev.h

Esta macro utiliza declaraciones de extensión GCC y declaraciones en expresiones

Más tarde, esta macro se utiliza en el archivo ./drivers/clk/clkdev.c , en la función clk_get_sys()

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

Me pregunto por qué no usar aquí una macro simple:

#define __clk_get(clk) (1)

EDITAR:

He encontrado otro uso de esta construcción en las fuentes del kernel utilizando el siguiente patrón grep:

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

Aquí están algunos de los partidos:

./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;}) [...]

Nota: la construcción ({if(put_user(d, (typeof (d)*)a)) return -EFAULT;}) parece ser un buen uso de la declaración compuesta. Pero esto también puede reemplazarse por do { if(put_user(d, (typeof (d)*)a)) return -EFAULT; } while(0) más típico do { if(put_user(d, (typeof (d)*)a)) return -EFAULT; } while(0) do { if(put_user(d, (typeof (d)*)a)) return -EFAULT; } while(0)

Una coincidencia devuelta por grep es interesante: en ./include/asm-generic/bug.h hay un comentario sobre el uso de ({ 0; }) . Esta es la misma answer de AndreyT .

De hecho, uno no puede usar ((void)0) , ya que no se podrá utilizar como valor r. ({ 0; }) está trabajando en cada caso.

Entonces, si tiene una macro que se puede usar como una función que devuelve un valor que se puede usar o no, la instrucción compuesta parece ser su única opción.

Pero __clkget() nunca se usa como otra cosa como valor r

Algunos enlaces


Me doy cuenta de que en el modo -Wall un standalone (1); La declaración de expresión genera una advertencia de "declaración sin efecto", mientras que una independiente ({ 1; }); La declaración de expresión no produce advertencias.

Quizás en algún lugar del código terminen con llamadas __clk_get independientes que ignoran el resultado. La (1) definición resultaría en una advertencia para tales llamadas, mientras que ({ 1; }) mantendrá en silencio mientras produce el mismo efecto en otros contextos.


Una posible explicación es evitar el uso en situaciones indeseables.
Esto es útil para mejorar la portabilidad del código: si la implementación de la macro de otra macro fallara, queremos que ésta también falle.

Ejemplo: static int x = __clk_get(clk); - No tiene sentido iniciar estáticamente con el reloj.
Con #define __clk_get(clk) (1) , funcionará.
Con #define __clk_get(clk) ({ 1; }) , fallará.