merkwürdiger Aufruf vor Speicherzugriffen

Gast #3619544
Lesenswert?

Hallo,

vor einem Schreibzugriff (SRAM) auf eine Struktur wird in Atmels ASF 
(z.B. bei den FIFOs) dieser Befehl aufgerufen:
1
    // Must be the last thing to do.
2
    barrier();

Wenn man sich diesen in der compiler.h anschaut, verbirgt sich das hier 
dahinter:
1
/**
2
 * \def barrier
3
 * \brief Memory barrier
4
 */
5
#if defined(__GNUC__)
6
#  define barrier()        asm volatile("" ::: "memory")
7
#elif defined(__ICCAVR32__)
8
#  define barrier()        __asm__ __volatile__ ("")
9
#endif

Hat jemand eine Ahnung was hiermit bewirkt werden soll?
#3619649
Lesenswert?

Ich denke eher, dass es bei einer Barriere darum geht, den Compiler 
insofern einzuengen, dass er Speicherzugriffe nicht wahllos im Code 
rumschieben darf.

In
1
   i = 5;
2
   j = 8;

könnte der Compiler auch die Reihenfolge der Zuweisungen umdrehen, wenn 
ihm das besser in den Kram passt, weil er zb j (oder die Adresse von j) 
schon in einem CPU Register hatte.
1
...
2
   j = k;
3
   i = 5;
4
   j = 8;
5
...

Erwarten würde ich solche Dinge, wenn es in den STrukturen zb logische 
Querverbindungen gibt. Wenn also Werte von zb einem Gültigkeitsflag 
abhängen und es wichtig ist, dass die Wertzuweisung erfolgt, bevor das 
Flag auf gültig gesetzt wird. Dreht der Compiler aus irgendeinem Grund 
die Reihenfolge der Aktionen um, dann ergibt das einen logischen Fehler.
Gast #3619663
Lesenswert?

brechbunkt schrieb:
> Aber wenn ich diese Speicheradresse als "volatile" deklariere, sollte
> doch diese Adresse dann ebenfalls ganz sicher beschrieben sein. Oder?

Nein.

volatile garantiert dir keine Ausführungsreihenfolgen oder sonstiges 
zeitliches Verhalten.

volatile sagt nur, daß der Zugriff stattfinden muß. Wann (insbesondere 
vor welchen anderen Zugriffen), kannst du nicht damit steuern.
Gast #3619787
Lesenswert?

Der Barrier Befehl sorgt dafür, dass über diese Grenze KEINE 
Memory-Zugriffe verschoben werden. Sprich alles was vor Barrier codiert 
wurde, wird auch vorher ausgeführt, die Reihenfolge davor kann aber von 
der im Code hingeschriebenen abweichen, wenn der Compiler es für besser 
hält. Gerade, wenn er zusammenhänge nicht erkennen kann.

    value = 0815
    written = 1

kann dann zu

    written = 1
    value = 0815

werden. Der Compiler geht hier von unabhängigen Dingen aus. Was passiert 
aber bei sowas im 2. Thread:

    while ( written )
       ;
    read = value
    written = 0

Hier sind also entweder atomics oder barriers notwendig:

    value = 0815
    barrier()
    written = 1

Beim 2. Thread ist etwas ähnliches erforderlich.

Volatile sorgt lediglich dafür, dass ein Zugriff IMMER passiert. Auf 
Multiprozessorsystemen ist aber auch volatile mit Vorsicht zu genießen, 
da es sich nicht unbedingt um Cache-Kohärenz kümmern muss, es kann also 
auch ein schon veralteter Wert gelesen werden.

Dort ist z.B. ein atomic einem volatile vorzuziehen, da sich dieser auch 
um den Cache, etc. kümmert.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren