Funktion von __asm__ __volatile__ (“” : : : “Speicher”)

Lesezeit: 4 Minuten

Benutzeravatar von vnr1992
vr1992

Was im Grunde __asm__ __volatile__ () tut und was ist die Bedeutung von "memory" für ARM-Architektur?

  • asm _volatile_ erklärt in (ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.4). Aber sollten das nicht zwei getrennte Fragen sein?

    – Phoeagon

    19. Februar 2013 um 5:54 Uhr

  • @phoeagon: Diese Zeile ist, so wie sie ist, eine einheitliche Operation einer Scheduling-Barriere für den Speicherzugriff des Compilers – obwohl die beiden Fragen separat relevant genug sein könnten, würde dies die gestellte Frage wahrscheinlich nicht beantworten.

    – Unixschlumpf

    19. Februar 2013 um 7:38 Uhr

auselens Benutzeravatar
auslesen

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

erstellt eine Speicherbarriere auf Compilerebene, die den Optimierer zwingt, Speicherzugriffe über die Barriere hinweg nicht neu zu ordnen.

Wenn Sie beispielsweise auf eine Adresse in einer bestimmten Reihenfolge zugreifen müssen (wahrscheinlich weil dieser Speicherbereich tatsächlich von einem anderen Gerät und nicht von einem Speicher unterstützt wird), müssen Sie dies dem Compiler mitteilen können, da er sonst möglicherweise nur Ihre Schritte optimiert für der Effizienz halber.

Angenommen, Sie müssen in diesem Szenario einen Wert in Adresse erhöhen, etwas lesen und einen anderen Wert in einer benachbarten Adresse erhöhen.

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

Das Problem ist der Compiler (gcc in diesem Fall) kann Ihren Speicherzugriff neu anordnen, um eine bessere Leistung zu erzielen, wenn Sie danach fragen (-O). Wahrscheinlich führt dies zu einer Folge von Anweisungen wie unten:

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

Obige Werte für d[0] und d[1] werden gleichzeitig geladen. Nehmen wir an, Sie möchten dies vermeiden, dann müssen Sie dem Compiler mitteilen, dass er die Speicherzugriffe nicht neu anordnen soll, und das ist zu verwenden 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;
}

So erhalten Sie Ihre Anweisungssequenz so, wie Sie sie haben möchten:

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

Es sollte beachtet werden, dass dies nur eine Speicherbarriere zur Kompilierzeit ist, um zu verhindern, dass der Compiler Speicherzugriffe neu ordnet, da es keine zusätzlichen Anweisungen auf Hardwareebene gibt, um Speicher zu leeren oder darauf zu warten, dass das Laden oder Speichern abgeschlossen ist. CPUs können Speicherzugriffe immer noch neu ordnen, wenn sie über die architektonischen Fähigkeiten verfügen und Speicheradressen eingeschaltet sind normal Typ statt strongly ordered oder device (Ref).

  • In diesem speziellen Fall kann der gleiche Effekt in Standard C erreicht werden, indem die Parameter wie folgt deklariert werden: int c(volatile int *d, volatile int *e)

    – Tor Klingeberg

    25. November 2014 um 10:26 Uhr


Diese Sequenz ist eine Scheduling-Barriere für den Speicherzugriff des Compilers, wie in dem Artikel erwähnt, auf den Udo verweist. Dies ist GCC-spezifisch – andere Compiler haben andere Möglichkeiten, sie zu beschreiben, einige davon mit expliziteren (und weniger esoterischen) Aussagen.

__asm__ ist eine gcc-Erweiterung, die es ermöglicht, Assembler-Anweisungen verschachtelt in Ihren C-Code einzugeben – hier wegen ihrer Eigenschaft verwendet, Nebeneffekte angeben zu können, die den Compiler daran hindern, bestimmte Arten von Optimierungen durchzuführen (was in diesem Fall dazu führen könnte, dass falsche Code).

__volatile__ ist erforderlich, um sicherzustellen, dass die asm Die Anweisung selbst wird nicht mit anderen flüchtigen Zugriffen umgeordnet (eine Garantie in der Sprache C).

memory ist eine Anweisung an GCC, die (sozusagen) besagt, dass die Inline-ASM-Sequenz Nebenwirkungen auf den globalen Speicher hat und daher nicht nur Auswirkungen auf lokale Variablen berücksichtigt werden müssen.

  • +1 Diese Antwort plus Du tust ist richtig. Dies ist eine Speicherbarriere für a Compiler nur. Es funktioniert nicht für SMP-Hardware.

    – ungekünstelter Lärm

    5. März 2013 um 15:52 Uhr

  • Wie entscheiden Sie also, wo Sie die asm volatile-Anweisung einfügen?

    – Soundarajan

    6. Januar 2014 um 4:56 Uhr

  • @Soundararajan: Diese Frage hat keine kurze Antwort. Ich würde empfehlen, Paul McKenneys exzellenten Artikel über die Anforderungen für die Bestellung von Speicherzugriffen zu lesen: rdrop.com/~paulmck/scalability/paper/whymb.2009.04.05a.pdf und die Linux-Kernel-Übersicht über Speicherbarrieren: git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/…

    – Unixschlumpf

    6. Januar 2014 um 15:48 Uhr

Die Bedeutung wird hier erklärt:

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

Grundsätzlich bedeutet dies, dass der Assembler-Code dort ausgeführt wird, wo Sie es erwarten. Es weist den Compiler an, die Anweisungen nicht neu anzuordnen. Das ist, was codiert wird, bevor dieses Stück Code vorher ausgeführt wird, und was danach codiert wird, wird danach ausgeführt.

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;
}

1414320cookie-checkFunktion von __asm__ __volatile__ (“” : : : “Speicher”)

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy