Zur Übersicht - INFO - Neueste 50 Beiträge - Neuer Beitrag - Suchen - FAQ - Zum CC1-Forum - Zum CC-Pro-Forum

Re: Wait wartet nicht Kategorie: Programmierung (von André H. - 31.05.2007 11:21)
Als Antwort auf Wait wartet nicht von Mark - 28.05.2007 14:10
Ich nutze:
C-Control II Unit, C164CI-ControllerBoard, CC2-Application-Board, CC2-StarterBoard, CC2-ReglerBoard, OSOPT V3.0, OSOPT V3.1
Hallo Mark,

Ich vermute, daÃ? Du einen Fehler in Deinem Programm hast, welcher beim
geposteten Code nicht enhalten ist.

Denn wait funktioniert eindeutig.
Sogar die beiden Threads funktionieren.
Gewöhne Dir aber bitte eine andere Klammersetzung an.
Ich wei�, da� es in C üblich ist, die geschweiften Klammern noch in der Zeile
des "einleitenden" Befehls zu setzen und gern auf richtiges Einrücken zu verzichten.
Aber spätestens, wenn man einen Fehler suchen mu�, behindert das einen sehr.
Daher rücke lieber so ein:

long timer;
int x,y;

thread regeln
{
 loop
 {
  timer=system.timer();
  y=y+1;
  wait timer+10000<=system.timer();
 }
}

thread main
{
 run regeln;
 x=x+1;
}

Bei kurzen Routinen fällt es zwar noch nicht stark auf, aber bei längeren
kann es aber sonst schnell unübersichtlich werden.

Nun aber zum wait zurück:
Prinzipiell kann man hier wait verwenden. Jedoch ist ein sleep eindeutig weniger belastend!
Ich wei� nicht, wie Du auf die Idee kommst, ein sleep würde andere Threads
in Mitleidenschaft ziehen?
Ein sleep ist eine einzge VM-Instruktion. Dazu noch ein Parameter der einmal
auf den Stack geschoben wird.
Um die Funktionsweise des sleep einmal zu erläutern:
Gelngt der Programmablauf zu einem sleep, so wird zuerst der Wert(Konstante oder
Inhalt einer Variable) auf den Stack geschoben, und dann VM_SLEEP ausgeführt.
VM_SLEEP ist zweigeteilt. Es wird daher geprüft, ob sich der Thread bereits in
einer "Sleep-Phase" befindet.

Ist das nicht der Fall, werden ein Active-Flag undzwei interne Threadvariablen mit
dem Startzeitpunkt(Timer) des Sleeps, sowie des Endzeitpunkts beschrieben.
AnschlieÃ?end wird der Threadpointer um 1 verringert, damit sich VM_SLEEP erneut durchlaufen
wird, sobald der Thread wieder "Rechenzeit" bekommt.
Jetzt wird noch die Rechenzeit abgegeben.
 
Erhält nun der Thread wieder Rechenzeit, so wird das Active-Flag des Sleeps abgefragt.
Da dieses nun auf True steht, erfolgt nun eine weitere Abfrage, die prüft, ob bereits
die Wartezeit abgelaufen ist.
Ist diese nicht abgelaufen, wird der Threadpointer wieder um eins verringert und
die Rechenzeit abgegeben.
Ist die Wartezeit abgelaufen, wird das Flag gelöscht, und der Thread wird
nach dem sleep fortgesetzt.

Im Ganzen nimmt VM_SLEEP bei jedem Durchlauf nur eine VM-Instruktion in Anspruch.

Wenn statt dem sleep nun eine Konstruktion mit wait gemacht wird,
belastet dies die CC2 mehr. Es steht dann weniger "Rechnzeit für andere Threads zur Verfügung.
Denn ein wait besteht mehr als aus einer VM_Instruktion.
Genaugenommen entspricht das etwa dieser Schleife:
loop
{
 if <Bedingung> break;
 yield;
}

Eine einfache Schleife besteht aus einer VM_Instruktion.
Dazu kommt noch das if und der Sprung und aus der Schleife: zwei Instruktionen
Und das yield mit einer Instruktion.
Die Bedingung selbst besteht natürlich auch aus einer Anzahl an Instruktionen.
Das timer+10000<=system.timer() in Deinem Fall sind 5 Instruktionen.
Somit ergibt sich bei Deinem wait eine Anzahl von 9 Instruktionen.
Von diesen 9 Instruktionen werden, solange die Bedingung nicht erfüllt ist, immer 8 durchlaufen.
Ist die Bedingung erfüllt, sind es ab Schleifenbeginn "nurnoch" 7 Instruktionen.
(Die IDE erzeugt aus wait eine kleine Schleife, da wait keine eigene VM_Instruktion ist.)

Dagegen stehen die bei sleep anfänglich zwei Instruktionen, und während
des "Wartens" eine Instruktion.
Somit ist ein sleep immer ressourcenschonender als ein vergleichbares Konstrukt mir wait.

Ã?brigens sollte man, um mit dem Timer eine Wartezeit zu berechnen, auf dieses Konstrukt verzichten:
timer+10000<=system.timer()
Es hat den Nachteil, daÃ? bei einem Ã?berlauf der Vergleich durch die negativen Werte
eine Zeit lang ein gegenteiliges Ergebnis liefert. (Hier: gut 10s lang)
Besser ist es, dies so zu berechnen:
system.timer()-timer<=10000
Hier wird die Differenz gebildet. Zu beachten ist aber, da� immer vom "höheren" Wert
der "kleinere" abgezogen wird.(Oder anders ausgedrückt: Vom aktuelleren (Timer-)Wert mu�
immer der alte Wert abgezogen werden.)
Nur so ist die Differenz immer positiv.
Au�er natürlich, wenn über dreieinhalb Wochen vergehen. Denn solange dauert es,
bis der Timer seine über 2,1Mrd. erreicht, wo er schlie�lich überläuft.
Aber Zeitdifferenzen von mehreren Wochen erfasst man sicher nicht mit dem ms-Timer. ;-)
Probleme mit einer falschen Berechnung treten daher erst nach ca. 3,5 Wochen auf,
und wiederholen sich dann etwa alle 7 Wochen. (solange dauert es, bis der Timer einmal rum ist.)

Daher nochmal zur Wiederholung:
Man rechnet immer "Zeit_neu Minus Zeit_alt = Differenz".

Aber um nochmal zu Deinem direkten Problem zu kommen:
Ich vermute, daÃ? in Deinem restlichen Programm irgendwo Fehler sind.
In diesem Fall würde ich sagen, da� Du irgendwo au�erhalb definierter
Arraygrenzen auf Variablen zugreifst, und somit auch Deine timer-Variable erwischt.
Nimm einmal Deine Schleife, wie sie ist, ersetze das wait dennoch durch ein sleep,
und überwache aus einem anderen Thread die timer-Variable.
Wenn diese sich öfters als alle etwa 10sek. (sleep 10000;) ändert,
dann ist mein Verdacht bestätigt. Dann hei�t es das Programm nach solchen
Ã?berschreitungen zu durchsuchen.
Das naheliegenste sind Variabeln, die unmitelbar vor long timer; definiert sind.
Führe daher bitte mal alle globalen Variablen des Moduls in der korrekten Reihenfolge auf.
Wenn in diesem Modul keine weiteren globalen Variablen definiert sind,
dann die des vorherigen Moduls.

MfG André H.


> Hallo!
> Ich verzweifle grade an simpelsten Abläufen! Folgenden Code habe ich:
>
> long timer;
>
> thread regeln
> {
> loop{
> timer=system.timer();
> do something....;
>
> wait timer+10000<=system.timer();
> }
> }
>
> main {
> run regeln;
> do something else...;
> }
>

> Aus dem Main-Thread soll also einfach nur der Thread "Regeln" aufgerufen werden, in dem
>  dann eine Schleife abläuft und alle 10 Sekunden etwas tun soll. Das Problem dabei ist, dass sie
> nicht 10 Sekunden wartet, sondern direkt weiter macht. Ich habe auch schon ausprobiert, das Ganze
> ohne die Schleife zu machen, aber auch das funktionierte nicht. Wenn ich allerdings ein einfaches sleep
> 1000 reinsetze, pausiert er, zieht aber die anderen Threads leistungstechnisch nach unten.
> Hat jemand eine Idee, woran es liegen könnte oder wie ich das Problem elegant umgehen könnte?
> Viele Grü�e,
> Mark
>
>


Antworten bitte nur ins Forum!
Fragen per EMail auf Forum-Postings werden nicht beantwortet!

Das macht meine Heizung gerade


    Antwort schreiben


Antworten:

Re: Wait wartet nicht (von JackFrost - 5.12.2007 22:04)
    Re: Wait wartet nicht (von JackFRost - 5.12.2007 22:05)