2012-02-29 10 views
20

Considérese el siguiente fragmento de código:¿Cómo evitar que g ++ optimice un ciclo controlado por una variable que puede ser modificada por un IRQ?

unsigned global; 
while(global); 

global se modifica en una función que se invoca por un IRQ. Sin embargo, g ++ elimina la prueba "is-not-zero" y traduce el ciclo while en un ciclo sin fin.

La desactivación de la optimización del compilador resuelve el problema, pero ¿ofrece C++ una construcción de lenguaje para ello?

+0

@ Styne666: el título es la pregunta – Necrolis

+0

Véase también http://stackoverflow.com/q/7083482/594137 –

+0

@ Styne666 - no es una buena práctica escribir código que necesita una configuración específica del compilador para funcionar. Por lo tanto, deshabilitar la optimización no es una opción para el código de producción. – 0xbadf00d

Respuesta

17

declarar la variable como volatile:

volatile unsigned global; 

Ésta es la palabra clave que le dice al compilador que global pueden ser modificados en diferentes hilos y todas las optimizaciones debe ser apagado por ello.

+1

Tal vez cange "todas las optimizaciones" para "ciertas optimizaciones", ya que todavía hay muchas optimizaciones que se pueden aplicar. Por ejemplo, en 'global = 5 + 6;', su afirmación puede implicar que '5 + 6' no se reducen. –

+2

Agregar el calificador volátil no cambia el código de operación creado. Todavía se traduce en un ciclo sin fin ... – 0xbadf00d

+0

@SaschaHoll sí lo hace. Puede establecer 'global' en' 0' en un hilo diferente, y el ciclo finalizará. –

0

Se podría utilizar los atributos del CCG en la declaración de la función para desactivar la optimización en función de cada función:

void myfunc() __attribute__((optimize(0))); 

Véase la página GCC Function Attributes para más información.

+0

Si la variable tiene que estar en una sección específica de la memoria, use 'section '[Variable Attribute] (http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html) para colocarla correctamente. También puede necesitar marcarlo como 'volátil '. –

7

Dado que está utilizando GCC y que decir que lo que la variable volatile no funciona, puede engañar al optimizador en el pensamiento de que el bucle cambia la variable por mentir al compilador:

while(global) 
    asm volatile("" : "+g"(global)); 

Este es una instrucción de ensamblaje en línea que dice que modifica la variable (se pasa como un operando de entrada y salida). Pero está vacío, así que obviamente no hace nada en tiempo de ejecución. Aún así, el optimizador piensa que modifica la variable - los programadores lo dicen, y el compilador, salvo la sustitución de operando (lo que significa simplemente reemplazar un texto por otro), realmente no se preocupa por el cuerpo del ensamblaje en línea y no hará ningún cosas divertidas para eso.

Y como el cuerpo está vacío y la restricción lo usa como el más genérico disponible, debería funcionar de manera confiable en todas las plataformas donde GCC admite el ensamblaje en línea.

+0

¡Puedo confirmar que este truco realmente funciona! Gracias. –

Cuestiones relacionadas