Forum: Mikrocontroller und Digitale Elektronik C-Frage: Was ist volatile?


von Tom (Gast)


Lesenswert?

kann mir vielleicht hier jemand kurz und prägnant, am besten an einem 
kleinen beispiel, erklären, was volatile vor variablen bedeutet? besten 
dank!

von gast (Gast)


Lesenswert?

volatile .. flüchtig

naja.. eine als volatile deklarierte variable muss vom kompiler vor 
jeder verwendung aus dem sram geladen werden, kann nicht in registern 
gehalten werden und wird nur verwendet für variablen die in einer isr 
den wert verändern können oder um davor zu schützen, dass der kompiler 
optimiert:

int bla, rum;
volatile int schnaps;
for( bla = 0; bla < 255; bla++ ); // wird vom kompiler wegoptimiert!

for( bla = 0; bla < 255; bla++ )
  rum = schnaps;

-> wird nicht wegoptimiert. also 255 mal durchlaufen und nicht nur 1x

von Uhu U. (uhu)


Lesenswert?

for( bla = 0; bla < 255; bla++ )
  rum = schnaps;

Das mit der Optimierung ist aber nur ein Nebeneffekt und keineswegs der 
Sinn von volatile-Variablen!

Deren Sinn ist, sicherzustellen, daß eine Variable, deren Wert sich 
asynchron ändern kann (durch eine ISR oder einen anderen Thread, oder 
Prozeß), vor Gebrauch immer aus dem Speicher nachgeladen und nie als 
temporäre Kopie in einem Register gehalten wird.

von I_ H. (i_h)


Lesenswert?

Wobei man sich darauf auch nicht 100%ig verlassen kann, Operationen auf 
volatile sind auch net atomar (bei CISC häufig, bei RISC fast immer), 
sprich während der Operation kann auch mal ein Interrupt auftauchen der 
die noch verändert.
Bei RISC können schon so einfache Sachen wie "volatile int a; [...] 
a+=1;" schiefgehen (bei CISC natürlich auch), desswegen Interrupts 
vorher ausstellen.

von Simon K. (simon) Benutzerseite


Lesenswert?

I_ H. wrote:
> Wobei man sich darauf auch nicht 100%ig verlassen kann, Operationen auf
> volatile sind auch net atomar (bei CISC häufig, bei RISC fast immer),
> sprich während der Operation kann auch mal ein Interrupt auftauchen der
> die noch verändert.
> Bei RISC können schon so einfache Sachen wie "volatile int a; [...]
> a+=1;" schiefgehen (bei CISC natürlich auch), desswegen Interrupts
> vorher ausstellen.

Das hat damit auch überhaupt nichts zu tun. Für die Atomarität muss der 
Programmierer trotz volatile noch sorgen.

von I_ H. (i_h)


Lesenswert?

Schon klar, ging nur darum, dass

>Deren Sinn ist, sicherzustellen, daß eine Variable, deren Wert sich
asynchron ändern kann (durch eine ISR oder einen anderen Thread, oder
Prozeß), vor Gebrauch immer aus dem Speicher nachgeladen und nie als
temporäre Kopie in einem Register gehalten wird.<

eben nicht bedeutet, dass es ausreicht eine Variable als volatile zu 
deklarieren, damit der Code nachvollziehbares tut (bzw. den 
Programmierer nicht in den Wahnsinn treibt).

von Uhu U. (uhu)


Lesenswert?

Das hatte ich auch nicht behauptet.

von I_ H. (i_h)


Lesenswert?

Wenn immer jeder (und auch alle die den Thread lesen) genau das 
herauslesen würde, was gemeint war, gäbe es keine Missverständnisse und 
keine Kriege mehr.
Es stand nicht explizit da, desswegen hab ich es nochmal explizit 
hingeschrieben.

von PP (Gast)


Lesenswert?

Naja, ich denke man muss es im Umfeld sehen.
Wer noch nicht mal volatile kennt wird erst recht nicht wissen das er 
für den atomaren Zugriff selber sorgen muss. Von daher finde ich die 
Anmerkung dazu schon richtig aber vor allem auch sehr wichtig 
(verhindert dann auch weitere Post weil irgendwelche "zufälligen" Fehler 
im Programmablauf auftreten ;)

PP

von _sepp_ (Gast)


Lesenswert?

Sorry, dass ich den Thread nochmals hervorhole, aber was meint man mit 
atomar, ich habe das auch mit den Erklärungen im Netz nicht verstanden.

und wieso macht macht man Variablen volatile, wenn sie sich ändern 
können.

das kann man ja mit einer normalen Variable auch, nämlich durch Pointer. 
Dann hat sich der Wert der Variable ja auch geändert. Und das könnte ich 
ja genauso in einem Interrupt machen, wenn ich es bräuchte. Wieso also 
volatile?

Ich verstehe irgendwie immer noch nicht wieso man volatile benötigt.

von Einer K. (Gast)


Lesenswert?

Wenn eine Variable von einer Funktion in Registern gehalten werden kann, 
dann kann sie auch in 2 Funktionen in Registern gehalten werden. 
Eigentlich nichts schlimmes dran, weil der Kompiler das weiß, und 
richtig abhandelt.

Aber:
Wird die Variable in einem Registersatz verändert, sieht der andere 
nichts davon.

Das tritt bei Interrupts auf.
Der Compiler kann nicht wissen, wann ein solcher eintritt.

Wenn man den Effekt unterdrücken will, macht man die Variable volatile.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

eine meinetwegen globale Variable die in einer ISR verändert wird, 
deklariert/definiert man mit volatile. Soweit klar.

Jetzt möchte man irgendwann im Code den Wert dieser Variable wissen. Nun 
muss man dafür sorge das während des Zugriffs der Wert der Variable 
nicht verändert wird. Deswegen greift man im atomaren "Schutzzustand" 
darauf zu. Das heißt nichts änderes als das die Interrupts kontrolliert 
gesperrt und danach wieder kontrolliert freigegeben werden. SREG wird 
gesichert. Bei 1Byte Variablen braucht man das nicht. Ab 2Byte Variablen 
muss man das machen. Sonst kann es sein man greift auf das erste Byte 
zu, während dessen verändert sich der Wert in der ISR und dann greift 
man auf das 2.Byte zu. Dumm nur das beide Bytes die man dann hat nichts 
mehr miteinander zu tun haben.

Dafür gibts eine Standard atomar Lib mit entsprechenden Funktionen.

von Dirk B. (dirkb2)


Lesenswert?

volatile:
Bei nicht-volatile Variablen geht der Compiler davon aus, dass er die 
Controlle darüber hat.
Er kann dann ganz anders optimieren.

atomar:
Manche Variablen bestehen aus mehr Elemente, als bei einem 
Schreibzugriff geändert werden kann. (zB 32-Bit Variablen auf einem 
8-Bit Rechner)

Zwischen diesen Schreibzugriffen kann der Prozessor aber durch einen 
Interupt unterbrochen werden. Dann stehen teilweise noch alte Daten in 
der Variable
Beispiel Variable hat 4711, neuer Wert soll 0815 sein (vier Stellen 
werden geschrieben). Mittendrin kommt ein Interrupt, dann steht da 0811.

Wenn diese Variable in der Interruptroutine wichtig ist, gibt das ein 
Problem.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

_sepp_ schrieb:
> aber was meint man mit atomar

Siehe atomar

von Theor (Gast)


Lesenswert?

Die Antworten könnte man aus meiner Sicht tatsächlich prägnanter 
formulieren.

Die Prägnanz ist hier notwendig, weil die Ursache, deren Wirkung mit 
"volatile" verhindert werden soll, die selbe sein kann, aber nicht 
prinzipiell die selbe ist wie in dem Fall, in dem man von "atomar" 
bzw. "nicht-atomar" spricht.

In Kürze:

Volatile - Dem Compiler wird mitgeteilt, dass der Wert der Variablen 
sich unabhängig von dem Programmfluss an und um eine gegebene Stelle 
herum verändern kann. Umgekehrt: Die Variable kann, obwohl das aus dem 
Programmtext so nicht hervorgeht, einen anderen Wert als erwartet 
haben.

atomar - Eine Variable ist so groß (oder im Speicher oder einem Register 
so gestaltet), dass sie nicht als ganzes mit einer Maschinenoperation 
geholt, manipuliert oder gespeichert werden kann.


Was nun bei den Erklärungen oft ein Problem ist, ist das viele Beispiele 
von Fällen in denen diese Gesichtspunkte wichtig sind, sich auf 
Interrupts beziehen. Dabei bekommt man leicht den Eindruck, dass 
Interrupts immer das Problem sind; und das alleinige Problem. Das ist 
aber nicht so.

Es gibt zwei Fälle, in denen sich Variableninhalte, wie oben erwähnt, 
unabhängig vom Programmfluss verändern können. Der erste sind 
tatsächlich Interrupts und zwar präzise Variablen deren Inhalt innerhalb 
der Interrupt-Service-Routine verändert werden (können). Der zweite Fall 
sind Peripherieregister die etwa über Portpins ihren Inhalt verändern, 
weil ja diese äusseren Ereignisse, die diese Veränderung bewirken nicht 
im Programmfluss beschrieben sind. Man beachte , dass in diesem 
zweiten Fall eventuelle Interrupts nicht das Problem verursachen!

In beiden Fällen, kann und muss dem Compiler mit "volatile" gesagt 
werden: "Verlass Dich nicht darauf, dass der Variableninhalt bei der 
Ausführung des Programms noch derselbe ist, wie beim letzen Mal, als 
diese Stelle im Code ausgeführt wurde. Also: Falls Du (Compiler) an 
diese Stelle kommst, lade den Variableninhalt (den Inhalt des 
Peripherieregister oder ähnliches) noch einmal in ein Register und 
verwende nicht den alten Registerinhalt."


Was nun die Atomarität betrifft, liegt hier der Fall anders, insofern 
als Interrupts in handelsüblichen Prozessoren üblicherweise die einzige 
Problemquelle sind. Allgemein gilt, dass jede Unterbrechung des 
Programmflusses, das Problem der Atomarität verursacht. Nur gibt es eben 
im Laden fast nur Prozessoren bei denen allein Interrupts den 
Programmfluss unterbrechen.
Nimmt man den Fall, das eine CPU nur Befehle zum Laden (speichern etc.) 
von 8-Bit-Werten hat und es ist nun ein 16-Bit Wert zu laden, so kann 
also ein Interrupt genau zwischen den beiden Befehlen, die jeweils einen 
Teil der 16-Bit laden auftreten. In der Zeit aber, in der der Interrupt 
verarbeitet wird, kann sich der noch nicht geladene Teil der Variablen 
ändern. Die Veränderung kann, muss aber nicht mit dem Ereignis zu tun 
haben, das den Interrupt ausgelöst hat. Der Interrupt kann 
beispielsweise ein Timer-Interrupt sein, die fragliche Variable aber ein 
Datenregister einer Kommunikationsschnittstelle.


Um zu dem Einwand mit dem Zeiger (Pointer) zu kommen:
Die Anwendung von Zeigern, verhindert das Problem nicht.
Leider ist der Einwand:

"das kann man ja mit einer normalen Variable auch, nämlich durch 
Pointer.
Dann hat sich der Wert der Variable ja auch geändert. Und das könnte ich
ja genauso in einem Interrupt machen, wenn ich es bräuchte. Wieso also
volatile?"

aus meiner Sicht nicht klar formuliert. Meine Fragen wären: "Was kann 
man mit einer normalen Variablen auch"? "Wann hat sich der Wert der 
Variablen auch geändert"? "Was kann ich ja genauso in einem Interrupt 
machen, wenn ich es brauche"? - Kurz: Falls das ein Beispiel sein 
sollte, wie man es mit Zeigern machen könnte enthält es zu wenig 
Details.

Aber wenn ich mal versuche, den Einwand zu interpretieren, dann scheint 
er auf dem Gedanken zu beruhen, dass ein Zeiger ja trotz eines evtl. 
Interrupts konstant bleibt. Daher ist scheinbar kein "volatile" 
notwendig.
Aber das ist falsch. Das Problem ist, dass sich der "Inhalt" der 
Variablen, auf den der Zeiger zeigt, verändert haben könnte. Davon aber 
geht der Compiler erstmal nicht aus, es sei denn es steht ausdrücklich 
so im Programmtext. Der Zeiger mag konstant bleiben, aber wichtig ist 
der Inhalt der variablen auf die der Zeiger zeigt. Der Compiler aber mag 
schon früher den Inhalt geladen haben und, weil er von nichts 
gegenteiligem weiss, bei der nächsten Verwendung des Inhalts den Zeiger 
garnichtmehr benutzen um den Inhalt erneut zu laden. Insofern gibt es 
zwischen Variablen und Zeigern auf diese Variablen keinen Unterschied.

Ich hoffe das hilft weiter. Allerdings gibt es dieses Thema auch schon 
zu Tausenden Malen im Internet. Vielleicht suchst Du mal ein wenig.

von (prx) A. K. (prx)


Lesenswert?

Theor schrieb:
> atomar - Eine Variable ist so groß (oder im Speicher oder einem Register
> so gestaltet), dass sie nicht als ganzes mit einer Maschinenoperation
> geholt, manipuliert oder gespeichert werden kann.

Operationen sind oder sind nicht atomar, nicht Daten. Bei:
  volatile int i = 0;
  i += 1;
ist die 2. Zeile bei x86 eine atomare Operation:
  inc mem
bei ARM nicht:
  ldr r0,mem
  add r0,r0,#1
  str r0,mem

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Für PRÄGNANT war das aber eine Menge Text. Mehr als alle vorherigen 
Beiträge zusammen.

Beitrag #5238925 wurde von einem Moderator gelöscht.
von (prx) A. K. (prx)


Lesenswert?

PS: Wenn mehrere Threads ins Spiel kommen, kann das, was bisher atomar 
war, nun nicht mehr atomar sein (oben, x86).

von Daniel A. (daniel-a)


Lesenswert?

"volatile" ist ausschliesslich für Variablen da, welche sich durch etwas 
ändern können, was nichts mit dem Programm zutun hat.

von (prx) A. K. (prx)


Lesenswert?

Daniel A. schrieb:
> "volatile" ist ausschliesslich für Variablen da, welche sich durch etwas
> ändern können, was nichts mit dem Programm zutun hat.

Für Anfänger (und einige Fortgeschrittene) ist nicht offensichtlich, 
dass ein im Programm mitten drin aufgeführter Exception-Handler nichts 
mit den Programm zu tun haben soll.

von _sepp_ (Gast)


Lesenswert?

Ich verstehe es immer noch nicht.
Bei einem Byte hat es keinen Einfluss, ok.
Bei 2 Byte lade ich das erste bearbeite es und der 2. kann sich dann 
schon geändert haben. auch ok.
und was soll da volatile daran ändern, dass man auf das 2. Byte 
zugreift, während ich noch beim 1. bin??
Spielt da der Compiler Türsteher und sagt: hier kommst du ned rein oder 
was?
Sorry, aber irgendwie ist das nicht logisch..

von _sepp_ (Gast)


Lesenswert?

Theor schrieb:

> In beiden Fällen, kann und muss dem Compiler mit "volatile" gesagt
> werden: "Verlass Dich nicht darauf, dass der Variableninhalt bei der
> Ausführung des Programms noch derselbe ist, wie beim letzen Mal, als
> diese Stelle im Code ausgeführt wurde. Also: Falls Du (Compiler) an
> diese Stelle kommst, lade den Variableninhalt (den Inhalt des
> Peripherieregister oder ähnliches) noch einmal in ein Register und
> verwende nicht den alten Registerinhalt."
>



Ok, sagt mir immer noch nichts.
Ich würde eher noch den alten nehmen, denn der ist noch der richtige. 
Beim neuen nämlich wurde das 2. Byte verändert. Da bringt es mir dann 
auch herzlich wenig, wenn mir der Compiler den falschen Wert nochmals 
ins Register ladet...

Beitrag #5238975 wurde von einem Moderator gelöscht.
von HildeK (Gast)


Lesenswert?

Das sind ja auch verschiedene Dinge.
Volatile: damit sagt man dem Compiler, dass diese Variable außerhalb 
seines Sichtbereichs eine Veränderung erfahren kann.
Atomar: hier müssen Variablen, die in einem Interrupt modifiziert werden 
und im Programmablauf verwendet werden, davor geschützt werden, dass ein 
Interrupt sie verändert, während sie außerhalb gerade verarbeitet 
werden. Im Prinzip weden während der Verarbeitungszeit die Interrupts 
temporär ausgesetzt.

von Einer K. (Gast)


Lesenswert?

Du sprichst von Atomic!
Atomare Zugriffe sorgen dafür, dass dir da kein Interrupt zwischen 
dengelt, und dir die Daten unter dem Arsch weg ändert, ohne das du oder 
der Kompiler es merkt.

von (prx) A. K. (prx)


Lesenswert?

_sepp_ schrieb:
> Ich verstehe es immer noch nicht.

Und ich verstehe diesen deinen Text leider nicht.

Die Anzahl Bytes einer Variablen hat nichts mit "volatile" zu tun.

Sie kann jedoch Einfluss darauf haben, ob eine Operation "atomar" ist. 
Was wiederum nichts mit "volatile" zu tun hat.

Du hast 
https://www.mikrocontroller.net/articles/Interrupt#Interruptfeste_Programmierung 
und 
https://www.mikrocontroller.net/articles/FAQ#Was_hat_es_mit_volatile_auf_sich 
gelesen?

von _sepp_ (Gast)


Lesenswert?

Das scheint auch so ein Vortragsspezialist zu sein, aber ich habe mir da 
trotzdem mal angeschaut.

Aber warum seine Leds einmal blinken (ohne Optimierung).
Und einmal mit der Optimierung dann auf einmal nicht mehr, blicke ich 
nicht..

https://www.youtube.com/watch?v=ImHW6I0BoEs

von HildeK (Gast)


Lesenswert?

_sepp_ schrieb:
> Aber warum seine Leds einmal blinken (ohne Optimierung).
> Und einmal mit der Optimierung dann auf einmal nicht mehr, blicke ich
> nicht..

Er hat es doch schön erklärt: der Compiler will bei der Optimierung das 
Programm verkleiner und stell bei seinen Untersuchungen fest, dass in 
'main' ja gar niemand da ist, der VAR verändert. Also: weg damit! Und 
schon geht es nicht mehr.
Mit Volatile sagt man ihm, dass außerhalb seines begrenzten Horizonts 
mit VAR doch was passiert und er sie gefälligst nicht wegoptimieren 
soll. Und schon geht's wieder.

von _sepp_ (Gast)


Lesenswert?

HildeK schrieb:
> sepp schrieb:
>> Aber warum seine Leds einmal blinken (ohne Optimierung).
>> Und einmal mit der Optimierung dann auf einmal nicht mehr, blicke ich
>> nicht..
>
> Er hat es doch schön erklärt: der Compiler will bei der Optimierung das
> Programm verkleiner und stell bei seinen Untersuchungen fest, dass in
> 'main' ja gar niemand da ist, der VAR verändert. Also: weg damit! Und
> schon geht es nicht mehr.
> Mit Volatile sagt man ihm, dass außerhalb seines begrenzten Horizonts
> mit VAR doch was passiert und er sie gefälligst nicht wegoptimieren
> soll. Und schon geht's wieder.

Was heisst wegoptimieren?
Ich definiere int a = 5;
Dann kommt der Compiler und macht mir die Variable a= 5 weg, weil sonst 
niemand sonst darauf zugreift und er glaubt, dass nur er Herr über die 
Variable ist.

a ist ja hier auch nicht volatile. Also optimiert er es weg, obwohl ich 
später in irgend einer Funktion vllt. mal a= a+5; rechne.
Damit er mir meine Variable nicht wegoptimiert, muss ich ja alle meine 
Variablen volatile definieren.
Das ist doch Blödsinn.

von (prx) A. K. (prx)


Lesenswert?

_sepp_ schrieb:
> Das ist doch Blödsinn.

Hast du die Tipps und Links gelesen? Im FAQ Artikel steht es in epischer 
Breite beschrieben.

von Einer K. (Gast)


Lesenswert?

_sepp_ schrieb:
> Das ist doch Blödsinn.

Vielleicht!

Aber reproduzierbar ist es, oder zweifelst du das auch an?

Ich würde sagen, entweder ist es Blödsinn, oder du verstehst es nicht.
Eine dritte Möglichkeit fällt mir nicht ein.

von Tippgeber (Gast)


Lesenswert?

Arduino F. schrieb:
> Ich würde sagen, entweder ist es Blödsinn, oder du verstehst es nicht.
> Eine dritte Möglichkeit fällt mir nicht ein.

Drittens: Er ist ein Troll. Was am wahrscheinlichsten ist ...

von HildeK (Gast)


Lesenswert?

Nein, in deinem Beispiel veränderst du ja 'A'.
In seinem Beispiel steht vermitlich nur drin:
PORTB = VAR;
und das in einer Dauerschleife.
Also setzt er PORTB = 0, weil der Init-Wert von VAR ja 0 ist und macht 
weiter nichts.
Wenn du dir bei einem optimierten Compilat mal Werte im Simulator 
ausgeben lässt, kommt es bei einigen immer wieder vor, dass er diese gar 
nicht kennt - deren Verarbeitung wurde einfach anders gelöst. Das 
funktioniert einwandfrei, wenn der Compiler über alles Bescheid weiß, 
nicht aber, wenn im zwischendurch jemand anders den Wert verändert.

Primitives Beispiel:
a=3;
b=5;
c=a+b;
d=c*10;
Wenn 'c' nicht im weiteren Programmverlauf verwendet wird, taucht sie 
garantiert nirgends auf - trotz des 3. Statements.
Es wird dann
d=(a+b)*10
daraus gemacht.

von _sepp_ (Gast)


Lesenswert?

HildeK schrieb:
> Nein, in deinem Beispiel veränderst du ja 'A'.
> In seinem Beispiel steht vermitlich nur drin:
> PORTB = VAR;
> und das in einer Dauerschleife.
> Also setzt er PORTB = 0, weil der Init-Wert von VAR ja 0 ist und macht
> weiter nichts.
> Wenn du dir bei einem optimierten Compilat mal Werte im Simulator
> ausgeben lässt, kommt es bei einigen immer wieder vor, dass er diese gar
> nicht kennt - deren Verarbeitung wurde einfach anders gelöst. Das
> funktioniert einwandfrei, wenn der Compiler über alles Bescheid weiß,
> nicht aber, wenn im zwischendurch jemand anders den Wert verändert.
>


Dass VAR 0 ist, sehe ich nirgends, ist ja gar nicht initialisiert. Hat 
wohl ein garbage value.
Ich hätte jetzt eher gemeint, er optimiert es weg, weil es in der 
Schleife ist und sonst nichts mit dem Wert passiert als immer nur den 
gleichen Wert zuzuweisen, muss ja nicht 0 sein, kann ja auch 1 sein..

von batman (Gast)


Lesenswert?

_sepp_ schrieb:
> a ist ja hier auch nicht volatile. Also optimiert er es weg, obwohl ich
> später in irgend einer Funktion vllt. mal a= a+5; rechne.

Warum auch nicht. Wenn sonst nichts mit dem Wert von a passiert, wird er 
ja nicht gebraucht.

von HildeK (Gast)


Lesenswert?

_sepp_ schrieb:
> Dass VAR 0 ist, sehe ich nirgends, ist ja gar nicht initialisiert

VAR war als globale Variable definiert, die ist in C inital '0'. War 
wohl in dem Video auch so umgesetzt, denn die LEDs blieben ja aus.
Aber das ist nur ein Nebenschauplatz.

Sie hätte auch jeden andern Wert haben können. Der Compiler hat sie als 
Variable wegen 'global' gar nicht mal verschwinden lassen, sondern eben 
dem LED-PORT nur ein einziges mal den Initialwert zugewiesen - weil er 
in 'main' keine Veränderung erkennen konnte.

von _sepp_ (Gast)


Lesenswert?

HildeK schrieb:
> sepp schrieb:
>> Dass VAR 0 ist, sehe ich nirgends, ist ja gar nicht initialisiert
>
> VAR war als globale Variable definiert, die ist in C inital '0'. War
> wohl in dem Video auch so umgesetzt, denn die LEDs blieben ja aus.
> Aber das ist nur ein Nebenschauplatz.
>
> Sie hätte auch jeden andern Wert haben können. Der Compiler hat sie als
> Variable wegen 'global' gar nicht mal verschwinden lassen, sondern eben
> dem LED-PORT nur ein einziges mal den Initialwert zugewiesen - weil er
> in 'main' keine Veränderung erkennen konnte.

jetzt habs ich glaub geschnallt :P

von c-hater (Gast)


Lesenswert?

A. K. schrieb:

> Operationen sind oder sind nicht atomar, nicht Daten. Bei:
>   volatile int i = 0;
>   i += 1;
> ist die 2. Zeile bei x86 eine atomare Operation:
>   inc mem

Nein, leider nicht. Es ist zwar nur eine Asm-Instruktion, aber auch 
diese eine Operation ist nicht notwendigerweise atomar. Nur bei völlig 
veralteten X86ern mit nur einem Kern und nur einer CPU ist sie 
tatsächlich atomar. Wobei ich mir nicht einmal da ganz sicher bin, es 
gibt ja schließlich auch noch DMA...

Sprich: die Faustregel "was sich mit einer Asm-Anweisung ausdrücken 
läßt, ist atomar" gilt nur für sehr simple Architekturen. Bei modernen 
leistungsfähigen µC/µP fällt man damit ziemlich sicher auf die Schnauze.

von (prx) A. K. (prx)


Lesenswert?

c-hater schrieb:
> Nein, leider nicht. Es ist zwar nur eine Asm-Instruktion, aber auch
> diese eine Operation ist nicht notwendigerweise atomar. Nur bei völlig
> veralteten X86ern mit nur einem Kern und nur einer CPU ist sie
> tatsächlich atomar.

Was ist kurz drauf auch schon erwähnte. Aber so lange wir es mit den 
hier im Forum üblichen µCs ohne Betriebsystem zu tun haben, ist das 
weniger relevant. Da geht es eigentlich immer um Interrupts auf einem 
einzelnen Prozessor.

> Wobei ich mir nicht einmal da ganz sicher bin, es
> gibt ja schließlich auch noch DMA...

Ja. Aber R-M-W Befehle auf Speicher, der im gleichen Zeitraum von DMA 
genutzt wird, sind schon etwas exotisch und ganz sicher weit jenseits 
des Horizonts des aktuellen Fragestellers. Da kannst du dann auch gleich 
mit den unterschiedlichen memory consistency models von ARM und x86 und 
damit verknüpfter Speicherbereichsverwaltung kommen und wirst damit auch 
viele erfahrenen µC-User aus der Kurve werfen.

: Bearbeitet durch User
von Mampf F. (mampf) Benutzerseite


Lesenswert?

I_ H. schrieb:
> Wobei man sich darauf auch nicht 100%ig verlassen kann, Operationen auf
> volatile sind auch net atomar

Volatilität hat doch nichts mit atomar zu tun ...

Für Atomarität gibt es mutexe.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

_sepp_ schrieb:
> Ich verstehe irgendwie immer noch nicht wieso man volatile benötigt.

Angenommen du hättest eine ISR, die ein Flag setzt und deine Main-Loop 
macht sowas wie:
1
while (!flag) {
2
  // wait
3
}

dann würde der Compiler nicht erkennen können, dass flag auch mal den 
Wert 1 annehmen kann, wenn die Variable nicht volatile ist und die 
Schleife einfach zur Endlos-Schleife optimieren.

Aber in einer ISR könnte flag auf 1 gesetzt werden.

Dann muss man flag volatile deklarieren.

von M. K. (sylaina)


Lesenswert?

Ihr solltet mal in die FAQs hier schaun, zum Thema gibts da was was sehr 
informativ ist: 
https://www.mikrocontroller.net/articles/FAQ#Was_hat_es_mit_volatile_auf_sich

Das sagt eigentlich alles.

von (prx) A. K. (prx)


Lesenswert?

Es wurde zwar schon alles verlinkt, aber noch nicht von jedem. ;-)

von Falk B. (falk)


Lesenswert?


von M. K. (sylaina)


Lesenswert?

A. K. schrieb:
> Es wurde zwar schon alles verlinkt, aber noch nicht von jedem. ;-)

Hm, stimmt. Jetzt wo du es sagst :D

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.