Optimierung stört in while-Schleifen Anwendung

OP #1880820
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
Gast #1880839
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
OP #1880854
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
#1880866
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;
OP #1880899
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

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