Forum: Mikrocontroller und Digitale Elektronik RTOS Thread-übergreifende Variablen


von Horst (Gast)


Lesenswert?

Bei der Implementierung eines kleinen Projekts mit der CMSIS RTOS 
Implementierung RTX 
(http://www.keil.com/pack/doc/CMSIS/RTOS/html/_function_overview.html) 
habe ich folgendes Problem:

Die betroffenen Threads sollen immer nur dann aktiv werden, wenn sich 
eine von einer Hand voll Variablen ändert. Dabei sind die Variablen 
sowohl von verschiedenen Threads änderbar als auch Abhängigkeiten 
anderer Threads (also wo auf Änderung dieser gewartet wird).

Um nicht zu beeinflussen, nenne ich erstmal nicht die Lösung, die ich 
aktuell nur sehe.
Meine Frage ist nun also, was für ein Design Pattern Ihr im gegebenen 
Problem verwenden würdet.

Danke!

von guest (Gast)


Lesenswert?

Mutexes

von Horst (Gast)


Lesenswert?

guest schrieb:
> Mutexes

Und wie soll das genau funktionieren? Derjenige, der den schreibt, muss 
den dann ja entsprechend releasen, wenn was neues reingeschrieben wurde. 
Aber wie soll er den wieder bekommen? Und wie soll das funktionieren, 
wenn mehrere die Variablen schreiben können?

von guest (Gast)


Lesenswert?

jeder Task, der in die Variable benutzen möchte (lesend oder schreibend) 
fordert den Mutex vom OS an.

Meistens so (pseudocode):



if(OS_MutexPend(&mutex, TIMEOUT_TIME))
{

  // Tu was mit der Variable


 OS_MutexRelease(&mutex);
}


OS_MutexPend wartet dabei so lange, bis die Mutex frei geworden oder die 
Timeoutzeit abgelaufen ist.

Bekommt der Task die Mutex nicht, dann muss er es beim nächsten 
Durchlauf noch einmal probieren.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Horst schrieb:
> Die betroffenen Threads sollen immer nur dann aktiv werden, wenn sich
> eine von einer Hand voll Variablen ändert. Dabei sind die Variablen
> sowohl von verschiedenen Threads änderbar als auch Abhängigkeiten
> anderer Threads (also wo auf Änderung dieser gewartet wird).

Um race conditions beim Ändern der Variablen zu verhindern (ein thread 
sieht die Variablen in einem noch nicht korrekt aktualisiertem Zustand), 
verwendest Du einen mutex. Um einem anderen thread die gewünschte 
Zustandsänderung anzuzeigen, nutzt Du, was immer Dir Dein OS zu 
verfügung stellt. Ein kurzer Blick auf die Doku Deines OS lässt 
vermuten, dass ein thread in der Regel in osWait() hängen sollte und 
laut Dokumentation da wieder raus kommt, wenn Du ihm ein "Signal, 
Message oder Mail" schickst.

mfg Torsten

: Bearbeitet durch User
von Guido (Gast)


Lesenswert?

Ich würde das etwa so machen.
...ist zwar Pseudocode, müsste aber je nach OS irgendwelche
Möglichkeiten geben, das so ähnlich umzusetzen.

//Thread
while(runnning)
{
  switch (WaitMultiEvent(&modifyEvent, &terminateEvent) )
  {
    case 0: //Signal, dass Variablen modifiziert wurden
      GetLock(&rwLock)
      //Variablen manipulieren
      ReleaseLock(&rwLock);
      break;

    case 1: //Thread soll beenden
      runnning = false;
      break;
  }

  if ( running == false )
  {
    //Resourcen freigeben
  }
}

von Steffen R. (steffen_rose)


Lesenswert?

Torsten R. schrieb:
> Ein kurzer Blick auf die Doku Deines OS lässt
> vermuten, dass ein thread in der Regel in osWait() hängen sollte und
> laut Dokumentation da wieder raus kommt, wenn Du ihm ein "Signal,
> Message oder Mail" schickst.

Ich persönlich scheitere hier immer daran, dass beim Keil OS die Signale 
den Threads gehören. Wenn ein Thread eine bestimmte Variable verändert, 
will ich ihm aber nicht die zusätzliche Information geben, welche 
anderen Threads daraufhin geweckt werden sollen.

Ich möchte lieber die relevanten Threads auf das Ereignis warten lassen.

Ich verstehe die Fragestellung des TO in ähnlicher Weise und verfolge 
gespannt die weitere Diskussion.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Steffen R. schrieb:
> Torsten R. schrieb:
>> Ein kurzer Blick auf die Doku Deines OS lässt
>> vermuten, dass ein thread in der Regel in osWait() hängen sollte und
>> laut Dokumentation da wieder raus kommt, wenn Du ihm ein "Signal,
>> Message oder Mail" schickst.
>
> Ich persönlich scheitere hier immer daran, dass beim Keil OS die Signale
> den Threads gehören. Wenn ein Thread eine bestimmte Variable verändert,
> will ich ihm aber nicht die zusätzliche Information geben, welche
> anderen Threads daraufhin geweckt werden sollen.
>
> Ich möchte lieber die relevanten Threads auf das Ereignis warten lassen.
>
> Ich verstehe die Fragestellung des TO in ähnlicher Weise und verfolge
> gespannt die weitere Diskussion.

Ja, posix condition variables machen in etwa genau das (sie sind dem 
erwarteten Zustand zugeordnet).

Na, dann müsste man eine Liste implementieren, in die sich die threads, 
die sich für ein Ereignis/Zustand interessieren eintragen.

von Horst (Gast)


Lesenswert?

guest schrieb:
> jeder Task, der in die Variable benutzen möchte (lesend oder
> schreibend)
> fordert den Mutex vom OS an.
>
> Meistens so (pseudocode):
>
> if(OS_MutexPend(&mutex, TIMEOUT_TIME))
> {
>
>   // Tu was mit der Variable
>
>  OS_MutexRelease(&mutex);
> }
>
> OS_MutexPend wartet dabei so lange, bis die Mutex frei geworden oder die
> Timeoutzeit abgelaufen ist.
>
> Bekommt der Task die Mutex nicht, dann muss er es beim nächsten
> Durchlauf noch einmal probieren.

Das ist mir schon klar, wozu ein Mutex da ist. Aber wie ich das 
geschickt zwischen mehreren Lesern und Schreibern verwende sehe ich noch 
nicht...

Torsten R. schrieb:
> Ein kurzer Blick auf die Doku Deines OS lässt
> vermuten, dass ein thread in der Regel in osWait() hängen sollte und
> laut Dokumentation da wieder raus kommt, wenn Du ihm ein "Signal,
> Message oder Mail" schickst.

Normal kann man, wie ich das bisher gesehen habe, in RTX immer nur auf 
eine Message warten. Also im Kernel muss ja registriert werden, dass der 
Thread auf MessageQueue X wartet und wüsste ich nicht, wie man da sagen 
kann warte auf X oder Y. (der entsprechende Aufruf lautet 
osMessageGet(MsgBox, osWaitForever);)
Wenn ich nur osWait aufrufe weiß ja niemand, dass der Thread auf 
MessageQueue Y wartet.

Guido schrieb:
> WaitMultiEvent

Siehe oben, man kann meines Wissens irgendwie nur auf ein Event warten, 
keine Veroderung.

Steffen R. schrieb:
> Ich persönlich scheitere hier immer daran, dass beim Keil OS die Signale
> den Threads gehören. Wenn ein Thread eine bestimmte Variable verändert,
> will ich ihm aber nicht die zusätzliche Information geben, welche
> anderen Threads daraufhin geweckt werden sollen.
>
> Ich möchte lieber die relevanten Threads auf das Ereignis warten lassen.
>
> Ich verstehe die Fragestellung des TO in ähnlicher Weise und verfolge
> gespannt die weitere Diskussion.

Exakt. Man müsste eben eine Verwaltung selbst machen, in der drin steht, 
welche Threads sich für Variable X interessieren. Bei dieser könnten 
sich dann Threads anmelden und sagen, sie wollen in Zukunft darüber 
benachrichtigt werden.
Die andere Möglichkeit wäre so eine Art MessageBus, wo dann jeder Thread 
selbst schauen kann, welche Nachricht er verwerten möchte. Das würde 
natürlich gewissen Overhead mitbringen und möglicherweise Probleme bei 
der Speicherverwaltung.

Torsten R. schrieb:
> Ja, posix condition variables machen in etwa genau das (sie sind dem
> erwarteten Zustand zugeordnet).
>
> Na, dann müsste man eine Liste implementieren, in die sich die threads,
> die sich für ein Ereignis/Zustand interessieren eintragen.

Danke, ersteres werde ich mir mal anschauen.

Und ja, die Liste wäre auch meine Idee gewesen, aber ich habe gehofft, 
dass es noch was einfacheres gibt.

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.