Funcionamiento de __asm__ __volátil__ (“” : : : “memoria”)

5 minutos de lectura

avatar de usuario
vnr1992

que basicamente __asm__ __volatile__ () hace y cuál es el significado de "memory" para la arquitectura ARM?

  • asm _volatile_ explicado en (ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.4). Pero, ¿no deberían ser dos preguntas separadas?

    – phoeagon

    19 de febrero de 2013 a las 5:54

  • @phoeagon: esta línea, tal como está, es una operación unificada de una barrera de programación de acceso a la memoria del compilador, aunque las dos preguntas pueden ser lo suficientemente relevantes por separado, es poco probable que respondan a la pregunta formulada.

    – pitufo unix

    19 de febrero de 2013 a las 7:38

avatar de usuario
auselen

asm volatile("" ::: "memory");

crea una barrera de memoria a nivel de compilador que obliga al optimizador a no reordenar los accesos a la memoria a través de la barrera.

Por ejemplo, si necesita acceder a alguna dirección en un orden específico (probablemente porque esa área de memoria en realidad está respaldada por un dispositivo diferente en lugar de una memoria), debe poder decirle esto al compilador; de lo contrario, puede optimizar sus pasos para el bien de la eficiencia.

Suponga que en este escenario debe incrementar un valor en la dirección, leer algo e incrementar otro valor en una dirección adyacente.

int c(int *d, int *e) {
        int r;
        d[0] += 1;
        r = e[0];
        d[1] += 1;
        return r;
}

El problema es el compilador (gcc en este caso) puede reorganizar su acceso a la memoria para obtener un mejor rendimiento si lo solicita (-O). Probablemente conduce a una secuencia de instrucciones como la siguiente:

00000000 <c>:
   0:   4603        mov r3, r0
   2:   c805        ldmia   r0, {r0, r2}
   4:   3001        adds    r0, #1
   6:   3201        adds    r2, #1
   8:   6018        str r0, [r3, #0]
   a:   6808        ldr r0, [r1, #0]
   c:   605a        str r2, [r3, #4]
   e:   4770        bx  lr

Valores anteriores para d[0] y d[1] se cargan al mismo tiempo. Supongamos que esto es algo que desea evitar, entonces debe decirle al compilador que no reordene los accesos a la memoria y eso es usar asm volatile("" ::: "memory").

int c(int *d, int *e) {
        int r;
        d[0] += 1;
        r = e[0];
        asm volatile("" ::: "memory");
        d[1] += 1;
        return r;
}

Entonces obtendrá su secuencia de instrucciones como desea que sea:

00000000 <c>:
   0:   6802        ldr r2, [r0, #0]
   2:   4603        mov r3, r0
   4:   3201        adds    r2, #1
   6:   6002        str r2, [r0, #0]
   8:   6808        ldr r0, [r1, #0]
   a:   685a        ldr r2, [r3, #4]
   c:   3201        adds    r2, #1
   e:   605a        str r2, [r3, #4]
  10:   4770        bx  lr
  12:   bf00        nop

Cabe señalar que esta es solo una barrera de memoria de tiempo de compilación para evitar que el compilador reordene los accesos a la memoria, ya que no pone instrucciones adicionales de nivel de hardware para vaciar las memorias o esperar a que se complete la carga o las tiendas. Las CPU aún pueden reordenar los accesos a la memoria si tienen las capacidades arquitectónicas y las direcciones de memoria están activadas. normal escriba en lugar de strongly ordered o device (árbitro).

  • En este caso particular, se puede lograr el mismo efecto en el estándar C al declarar los parámetros de esta manera: int c(volatile int *d, volatile int *e)

    –Tor Klingberg

    25 de noviembre de 2014 a las 10:26


Esta secuencia es una barrera de programación de acceso a la memoria del compilador, como se indica en el artículo al que hace referencia Udo. Este es específico de GCC: otros compiladores tienen otras formas de describirlos, algunos de ellos con declaraciones más explícitas (y menos esotéricas).

__asm__ es una extensión de gcc que permite ingresar declaraciones en lenguaje ensamblador anidadas dentro de su código C; se usa aquí por su propiedad de poder especificar efectos secundarios que evitan que el compilador realice ciertos tipos de optimizaciones (que en este caso podrían terminar generando errores código).

__volatile__ se requiere para asegurar que el Asm La declaración en sí no se reordena con ningún otro acceso volátil (una garantía en el lenguaje C).

memory es una instrucción para GCC que (más o menos) dice que la secuencia asm en línea tiene efectos secundarios en la memoria global y, por lo tanto, no solo deben tenerse en cuenta los efectos en las variables locales.

  • +1 Esta respuesta más Tú haces es correcto. Esta es una barrera de memoria para un compilador solamente. No funcionará para hardware SMP.

    – ruido sin arte

    5 de marzo de 2013 a las 15:52

  • Entonces, ¿cómo decide dónde insertar la declaración volátil de asm?

    – Soundararajan

    6 de enero de 2014 a las 4:56

  • @Soundararajan: Esa pregunta no tiene una respuesta breve. Recomendaría leer el excelente artículo de Paul McKenney sobre los requisitos de pedido de acceso a la memoria: rdrop.com/~paulmck/scalability/paper/whymb.2009.04.05a.pdf y la descripción general del kernel de Linux sobre las barreras de memoria: git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/…

    – pitufo unix

    6 de enero de 2014 a las 15:48

El significado se explica aquí:

http://en.wikipedia.org/wiki/Memory_ordering

Básicamente implica que el código ensamblador se ejecutará donde lo esperas. Le dice al compilador que no reordene las instrucciones a su alrededor. Eso es lo que se codifica antes de que este fragmento de código se ejecute antes y lo que se codifica después se ejecutará después.

static inline unsigned long arch_local_irq_save(void)
{
    unsigned long flags;

    asm volatile(
        "   mrs %0, cpsr    @ arch_local_irq_save\n"
        "   cpsid   i"      //disabled irq
        : "=r" (flags) : : "memory", "cc");
return flags;
}

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad