Forum: Compiler & IDEs Optimierung stört in while-Schleifen Anwendung


von Ingo S. (ingo-s)


Lesenswert?

Hi,

ich habe eine WinAVR Anwendung in der serielle Eingangsdaten per ISR in 
einen Ringbuffer geschrieben werden. In der Auslesefunktion überwache 
ich, das ich den Pointer auf die Eingangsposition nicht überhole. Mit 
der -Os Optimierung wird aber leider die Übernahme der momentanen 
Eingangsposition dummerweise vom Compiler optimiert vor die 
Warteschleife gesetzt.

Codebeibspiel das nicht funktioniert:

-----
char* psaveInputpos;

  // diese Schleife soll das Überholen der Eingangsposition verhindern
  do{
    cli();
    psaveInputpos = prInputpos;
    sei();
  }while(psaveInputpos == prOutputpos);

  //hier gehts dann weiter mit dem Abholen der neuen Daten
----
im Assembler Listing kann man sehen, das die Anweisung
  psaveInputpos = prInputpos;
vor die while Schleife gesetzt wird und damit funktioniert die Abfrage 
natürlich nicht mehr.
Gelöst habe ich das Problem indem ich den Positionsvergleich in eine 
getrennte Funktion ausgelagert habe, die ich allerdings dann noch als 
noinline deklarieren musste, sonst war es das selbe in grün.

Gibt es für solche Fälle Compiler Direktiven, die die Position einer 
Anweisung gezielt für eine Funktion oder innerhalb einer Funktion 
sicherstellen?

Gruß Ingo

von (prx) A. K. (prx)


Lesenswert?

Ja, gibt es: die vom Interrupt-Handler modifizierte Variable als 
volatile deklarieren.

von Ingo S. (ingo-s)


Lesenswert?

Hi prx,

die sind natürlich volatile, selbst die Funktions interne zusätzlich als 
volatile zu definieren bringst nicht. Der Compiler setzt sie trotzdem 
vor die while Schleife :-((

Gruß Ingo

von (prx) A. K. (prx)


Lesenswert?

Vertrauen ist gut, Kontrolle ist besser. Ich sehe nirgends ein volatile.

Vorsorglicher Tipp: in
  volatile char *p;
zeigt ein non-volatile Pointer auf volatile char, in
  char *volatile p;
ist der Pointer selbst volatile.

von Oliver (Gast)


Lesenswert?

Ingo Stahl schrieb:
> Gibt es für solche Fälle Compiler Direktiven, die die Position einer
> Anweisung gezielt für eine Funktion oder innerhalb einer Funktion
> sicherstellen?

Nö. Der Compiler darf und wird die Reihenfolge der Anweisungen so 
umstellen, wie es es für sinnvoll hält. Das macht er das so, daß sich 
dabei am Ergebnis nichts ändert (wenn er keine Bug hat) .


Ingo Stahl schrieb:
> Der Compiler setzt sie trotzdem
> vor die while Schleife :-((

Bist du dir sicher? Optimierter Code ist schwer zu lesen. Die als 
Kommentar eingefügten C-Sourcecodezeilen kannst du als Anhaltspunkt 
dabei getrost vergessen.

Zeig mal ein compilierbares Codebeispiel, an dem sich das Verhalten 
reproduzieren lässt.

Oliver

von Ingo S. (ingo-s)


Lesenswert?

Hi,
@prx:
so sind sie global definiert:
volatile char* prInputpos;
volatile char* prOutputpos;

die Anweisung
psaveInputpos = prInputpos;
gibt ein natürlich ein Warning, den Cast
psaveInputpos = (char*)prInputpos;
hatte ich vergessen mit anzuführen.
Wobei ich ja auch die Variante
volatile char* psaveInputpos;
erfolglos ausprobiert hatte.

@Oliver:
ich baue morgen mal wieder die alte Variante ein und zeige das 
Codebeispiel.
Sicher bin ich mir schon, ich bin beim Debugging (Dragon) auf die 
Assembler Ansicht gegangen. Ohne Optimierung sieht man, das der Compiler 
die Anwweisung nicht verschiebt.

Gruß Ingo

von (prx) A. K. (prx)


Lesenswert?

Ingo Stahl schrieb:

> so sind sie global definiert:
> volatile char* prInputpos;
> volatile char* prOutputpos;

Na also, dachte ich mir es doch. Die Pointer sind hier eben nicht 
volatile, auch wenn's für ungeübte Augen zunächst so aussieht, und daher 
gibst du dem Compiler die ungewollte Freiheit der Optimierung.

Damit deklarierst du, dass die chars, auf die die Pointer zeigen, 
volatile sind. Nicht die Pointer. Bei deinem Vergleich geht es aber um 
die Pointer, nicht die chars. Wenn du das grade ziehst bist du nebenbei 
auch ganz ohne cast die Warnung los. Also:
  char *volatile prInputpos;
  char *volatile prOutputpos;

von Ingo S. (ingo-s)


Lesenswert?

Hi,

jetzt wollte ich es doch noch wissen und hab das Problem in einem 
Testprojekt nachvollzogen.

@prx:
Super Tipp, das wars!
Im Assembler Listing ist es einwandfrei sichtbar.
Irgentwie werde ich mit der für mich etwas kryptischen "C" Syntacs" 
trotz einiger Jahre VC++ nicht 100%tig so warm, das mir das auf Anblick 
auffällt.

@Oliver:
ich denke, das sich das Codebeispiel damit erledigt hat.

Gruß Ingo

von Oliver (Gast)


Lesenswert?

Ingo Stahl schrieb:
> @Oliver:
> ich denke, das sich das Codebeispiel damit erledigt hat.

;-)

Oliver

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Oliver schrieb:
> Ingo Stahl schrieb:
>> @Oliver:
>> ich denke, das sich das Codebeispiel damit erledigt hat.

hmmm, nicht wirklich. Zwar wird die störende Optimierung nicht mehr 
gemacht, aber es sieht stark danach aus, daß da noch ne Race-Condition 
zuschlagen kann wegen nicht-atomarem Code im Zeiger-Test.

von Oliver (Gast)


Lesenswert?

Wenn prOutputpos in der ISR nicht verändert wird (was zu vermuten ist), 
dann nicht.

Oliver

von Ingo S. (ingo-s)


Lesenswert?

Oliver schrieb:
> Wenn prOutputpos in der ISR nicht verändert wird (was zu vermuten ist),
> dann nicht.
>
> Oliver

genau, da fummelt keine ISR dran rum :-)

Gruß Ingo

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.