'volatile' nur für Interrupt Variablen?

#5484013
Lesenswert?

volatile weißt den Compiler an, den Zugriff auf diese Variable nicht zu 
optimieren, sondern davon auszugehen, dass zwischen zwei Zugriffen (z.B. 
in einer While-Schleife), der Wert sich geändert haben könnte, z.B. 
durch einen Interruptzugriff.
Falls die DMA-Arrays in der main-loop verwendet werden (beispielsweise) 
würde ich sie schon als volatile definieren.
#5484022
Lesenswert?

Daniel V. schrieb:
> Falls die DMA-Arrays in der main-loop verwendet werden (beispielsweise)
> würde ich sie schon als volatile definieren.

Ohne volatile könnte der Compiler denken, der DMA-RAM ist write only und 
könnte es wegoptimieren. Er wird es zwar selten tun, aber es ist 
unsauber. Korrekter Weise muß der DMA-RAM also volatile sein, wie auch 
jedes IO-Register.
#5484025
Lesenswert?

Bei Arrays, die im Programm und per DMA angesprochen werden, wird 
volatile allein nicht unbedingt ausreichen, will man Probleme vermeiden. 
Je nach Controller-Architektur kann es auch wichtig sein, das Array per 
Software so anzusprechen, dass Caches/Puffer nicht in die Quere kommen. 
Sei es, dass der gleiche Speicher mit unterschiedlichen Eigenschaften 
mehrfach im Adressraum eingeblendet ist. Sei es, dass man im Adressraum 
diesbezügliche Eigenschaften einstellen muss. Sei es, dass man spezielle 
Befehle benötigt, um Konsistenz herzustellen (memory barriers).
#5484049
Lesenswert?

Schreiboperationen dürfen genau dann als unnötig wegoptimiert werden, 
wenn der Compiler den vollständigen Überblick über alle im C-Programm 
möglichen Operationen auf diese Daten hat. Bei Daten, die 
ausschliesslich lokal in der Funktion definiert sind, ist das 
beispielsweise der Fall, es sei denn deren Adresse wird an Funktionen 
oder Pointer übergeben.

Solange man Quellfiles in traditioneller Manier einzeln übersetzt, hat 
der Compiler über den Datenbestand von puts() keinen Überblick, wird 
also nichts wegoptimieren. Wird jedoch das Programm mitsamt Library aus 
Zwischencode vollständig in einem Vorgang übersetzt, dann hat er den 
Überblick. Nur sieht er dann auch den Lesezugriff darauf, oder die 
Übergabe des Arrays als Parameter an einen Systemaufruf, und wird es 
deshalb nicht wegoptimieren.

DMA-Operationen jedoch sind für den Compiler stets unsichtbar, egal ob 
er zusammen oder getrennt übersetzt. Dementsprechend muss man das 
Programm ausrichten.
#5484135
Lesenswert?

Bernd K. schrieb:
>> Solange man Quellfiles in traditioneller Manier einzeln übersetzt, hat
>> der Compiler über den Datenbestand von puts() keinen Überblick, wird
>> also nichts wegoptimieren.
>
> Es sei denn man verwendet LTO, dann wird modulübergreifend optimiert.

Das hatte ich direkt auf diesen Satz folgend in anderen Worten bereits 
geschrieben. ;-)

A. K. schrieb:
> Wird jedoch das Programm mitsamt Library aus
> Zwischencode vollständig in einem Vorgang übersetzt,

Wobei im Fall von puts() die Library in gleicher Weise mit übersetzt 
werden muss, denn sonst ist das eine unbekannte Funktion. Ob normale LTO 
das tut?
#5484146
Lesenswert?

Daniel V. schrieb:
> volatile weißt den Compiler an, den Zugriff auf diese Variable nicht zu
> optimieren, sondern davon auszugehen, dass zwischen zwei Zugriffen (z.B.
> in einer While-Schleife), der Wert sich geändert haben könnte, z.B.
> durch einen Interruptzugriff.

Das ist falsch/unvollständig formuliert und teilweise irreführend.

Volatile weist den Compiler an daß alle Zugriffe auf die betreffende 
Variable als beobachtbarer Seiteneffekt (also als Eingabe/Ausgabe) des 
Programms zu betrachten sind.

Für beobachtbare Seiteneffekte gilt die zwingende Regel daß sie genau in 
der im Programm vorgeschriebenen Anzahl und Reihenfolge auszuführen 
sind. Dies hat zur Folge daß manche Optimierungen (nämlich nur solche 
die die Anzahl oder die Reihenfolge der Seiteneffekte ändern würden) 
nicht ausgeführt werden können.

Volatile ist also ein Sprachmittel um einen gewünschten Seiteneffekt, 
eine Interaktion mit der Außenwelt zu deklarieren. Alles was kein 
Seiteneffekt ist  unterliegt der freien Willkür des Compilers und er 
kann es nach belieben umbauen solange die Seiteneffekte gleich bleiben, 
umgangssprachlich "solange das Programm das gleiche tut".

Mit volatile wird also definiert was in diesem Zusammenhang mit "tun" 
eigentlich gemeint ist, alles was es nicht explizit tun soll muss es 
auch nicht tun.

Volatile ist das Sprachmittel mit dem deklariert wird an welchen Stellen 
die abstrakte Maschine mit der realen Maschine verbunden ist.
Gast #5484158
Lesenswert?

A. K. schrieb:
> Wichtig ist nur, dass dabei die Adresse von Daten an
> eine Funktion übergeben wird, deren Code dem Compiler unbekannt ist.

In Standard-C kann man keine Syscalls machen. Den Code dem Compiler 
unbekannt zu machen ist eine Möglichkeit; das ist aber keine zwingende 
Voraussetzung. Wenn der Code bekannt ist kann man mit entsprechender 
Konstruktion dafür sorgen dass nicht wegoptimiert wird. Bei kompletten 
Assembler-Funktionen wird sowieso nicht optimiert, selbst wenn bekannt. 
Wenn man den Syscall als Inline-Assembler umsetzt, der in einem Makro 
oder einer Inline-Funktion auftaucht, kann er ge-inlined werden 
(Effizienz) und durch Angabe entsprechender Constraints kann 
sichergestellt werden dass nicht zu viel optimiert wird.
z.B. so:
https://stackoverflow.com/a/10831844
#5484180
Lesenswert?

Jim M. schrieb:
> Äußerst unwahrscheinlich, denn dann würde auch sowas wie puts() nicht
> mehr korrekt tun.

Und genau das ist mir mal passiert. Der Compiler ist nämlich nicht dumm.
Wenn puts() das Array nacheinander an eine RAM-Stelle schreibt und der 
Compiler sieht nirgends einen Lesezugriff zwischendurch (macht ja ein 
Interrupt), dann schreibt er einfach nur das letzte Byte des Arrays da 
hinein. Diese RAM-Stelle muß also volatile sein.
#5484184
Lesenswert?

Dr. Sommer schrieb:
> In Standard-C kann man keine Syscalls machen.

Das hängt davon ab, wie ein Syscall aussieht. Grundsätzlich könnte ein 
Syscall wie eine normale C Funktion aussehen, bei der nur die Adresse 
den Unterschied ergibt. Die x86 Call Gates stellen so etwas dar, die in 
segmentiertem Code nicht von normalen Funktionen mit gleicher 
Übergabecharakteristik unterscheidbar sind.

Aber das geht allmählich ins Erbsenzählen über. Ich will damit nur 
ausdrücken, dass der Unterschied nicht so sehr im Aufrufverfahren liegt, 
sondern darin, wieviel der Compiler über das weiss, was aufgerufen wird.
Gast #5484188
Lesenswert?

A. K. schrieb:
> bei der nur die Adresse
> den Unterschied ergibt

Das Angeben fixer Adressen ist auch Nicht-Standard... :o) Aber okay, da 
hat man dann kein Problem.

A. K. schrieb:
> Ich will damit nur
> ausdrücken, dass der Unterschied nicht so sehr im Aufrufverfahren liegt,
> sondern darin, wieviel der Compiler über das weiss, was aufgerufen wird.
Wobei man entsprechendes Wissen nachreichen kann, sodass es eben auch 
dann geht, wenn der Compiler den Aufruf sieht.
#5484264
Lesenswert?

Teo D. schrieb:
> Volatile zwingt den Compiler doch nur dazu, bei JEDEM zugriff auf die
> Variable, diese aus dem Speicher zu holen und keinesfalls die Register
> für Zwischenergebnisse nutzen.

Nicht als Zwischenspeicher über den Moment hinaus. Nur betrifft das 
ausschliesslich die Sicht des Compilers. Um irgendwelche Puffer oder 
Caches des Prozessors kümmert er sich nicht. Das ist bei I/O-Registern 
kein Problem, da die von der Hardware konsistent abgesprochen werden. 
Bei von DMA genutzem RAM kann das jedoch je nach Controller Aufgabe des 
Programmierers sein. Da ist "volatile" zwar notwendig, aber 
möglicherweise nicht ausreichend.
Gast #5484273
Lesenswert?

A. K. schrieb:
> Da ist "volatile" zwar notwendig, aber
> möglicherweise nicht ausreichend.

Genau... Bei Cortex-A mit mehreren Cache-Ebenen muss man ein "Cache 
Clean" durchführen, und das kann etwas fummelig werden, denn entweder 
macht man das auf dem gesamten Cache (braucht 3 verschachtelte 
Schleifen) oder auf einem Block (einfacher, aber u.U. tatsächlich 
langsamer). Das ganze dann typischerweise noch in Assembler aufgrund der 
CP15-Spezial-Instruktionen. Wenn man das nicht macht, sieht man z.B. bei 
einem Display-Controller schön an den Artefakten welche Cache-Lines 
geleert wurden und welche RAM-Stellen noch die alten Daten haben :-)

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