Hallo liebe Forenbesucher :) Wie im Betreff schon erwähnt, handelt sich meine Frage über den Unterschied von Reentrant und Critical Section. Irgendwie habe ich da ein Denkfehler oder tu mir mit den Begriffen schwer. Also man spricht von Critical Section (bessert mich bitte aus wenn ich falsch liege), wenn mehrere Tasks/Threads auf eine Shared Data zugreifen wollen, vor allem dann wenn ein Task lesen und einer schreiben will. (zum Beispiel Memory welches ich durch malloc erstellt habe). Hier kann es passieren, dass Dateninkonsistenz (Data race) entsteht. Nicht-Reentrante Funktionen sind Funktionen oder librarys, welche globale oder statische Variablen besitzen (also alles was sich nicht am Stack befindet). Hier kann ebenso Dateninkonsistenz entstehen. Bei beiden Fällen muss ich diese Kritischen Sektionen durch Mutex oder Semaphoren schützen. Meine Frage ist jetzt: Betrifft der Begriff Reentrant nur Funktionen und Librarys oder kann ich zu einer Crtical Section auch sagen, dass diese Reentrant gemacht werden muss oder können nur librarys oder Funktionen reentrant sein? Also mir geht vorallem um die Begrifflichkeiten und bitte bessert mich aus falls ich oben bei den Erklärungen fehler gemacht habe. Lg Jooo
Hallo Johannes, Johannes H. schrieb: > Wie im Betreff schon erwähnt, handelt sich meine Frage über den > Unterschied von Reentrant und Critical Section. Irgendwie habe ich da > ein Denkfehler oder tu mir mit den Begriffen schwer. > > Also man spricht von Critical Section (bessert mich bitte aus wenn ich > falsch liege), wenn mehrere Tasks/Threads auf eine Shared Data zugreifen > wollen, vor allem dann wenn ein Task lesen und einer schreiben will. Ja, etwas genauer, ist eine Critical Section der Pfad im Code, in dem eine Invariante verletzt ist und so halt nicht beobachtet werden darf. > Nicht-Reentrante Funktionen sind Funktionen oder librarys, welche > globale oder statische Variablen besitzen (also alles was sich nicht am > Stack befindet). Hier kann ebenso Dateninkonsistenz entstehen. > > Bei beiden Fällen muss ich diese Kritischen Sektionen durch Mutex oder > Semaphoren schützen. Nein, eine Mutex oder eine Semaphore macht so eine durch gegenseitigen Ausschluss gesicherte Critical Section garantiert nicht reentrant. Reentrante Funktionen sind Funktionen, die Du mitten in der Ausführung unterbrechen kannst und sind dann von einem anderen Kontext aus wieder aufrufen kannst. Wenn die Funktion einen Mutex locked, dann unterbrochen wird und dann wieder aufgerufen wird, blockt sie beim zweiten Versuch, den Mutex zu locken. > Meine Frage ist jetzt: Betrifft der Begriff Reentrant nur Funktionen und > Librarys oder kann ich zu einer Crtical Section auch sagen, dass diese > Reentrant gemacht werden muss oder können nur librarys oder Funktionen > reentrant sein? Reentrant und thread safe sind unterschiedlich starke Garantien. Eine Funktion, die reentrant ist, kannst Du aus einer Interrupt service routine heraus aufrufen, eine Funktion die einem Mutex verwendet ist nicht reentrant und Du kannst sie nicht von einer ISR aus aufrufen. Eine Funktion, die reentrant ist, ist auch thread safe. Um eine Funktion, die eine critical section enthält, reentrant zu machen, musst Du entweder potentielle interrupts disablen oder aber, die Änderungen müssen atomar sein, bzw. ein entsprechendes, auf atomaren Operationen aufbauendes Protokoll implementieren (z.B. pthread_mutex_lock()). mfg Torsten
Eine Frage hätte ich noch und zwar du diesem Abschnitt: Torsten R. schrieb: > Reentrante Funktionen sind Funktionen, die Du mitten in der Ausführung > unterbrechen kannst und sind dann von einem anderen Kontext aus wieder > aufrufen kannst. Wenn die Funktion einen Mutex locked, dann unterbrochen > wird und dann wieder aufgerufen wird, blockt sie beim zweiten Versuch, > den Mutex zu locken. Wer blockt hier wem? Das habe ich nicht ganz verstanden. Uns wurde in der Schule gesagt, dass Mutexes auch bei nicht reentrant Problemen die Lösung ist. Wenn ein Task die Mutex besitzt und die die Kritische Funktion eintritt, kann kein anderer Task diese betreten, solange der eine Task diese nicht freigibt oder? Und wie mache ich es dann bei Echtzeitbetriebssytemen? Lg
Johannes H. schrieb: > Eine Frage hätte ich noch und zwar du diesem Abschnitt: > > Torsten R. schrieb: > Wer blockt hier wem? Das habe ich nicht ganz verstanden. Uns wurde in > der Schule gesagt, dass Mutexes auch bei nicht reentrant Problemen die > Lösung ist. Wenn ein Task die Mutex besitzt und die die Kritische > Funktion eintritt, kann kein anderer Task diese betreten, solange der > eine Task diese nicht freigibt oder? Die CPU sich selbst. Wenn eine Funktion z.B. einen spin lock verwendet, um eine kurze critical section zu locken, dann eine ISR ausführt und die nun wieder versucht, den spin lock zu locken, dann hängt es halt. Unterprechbar ist das dann nur noch mit einem ISR einer höheren Prio. > Und wie mache ich es dann bei Echtzeitbetriebssytemen? Kommt darauf an, was Du mit der Frage meinst ;-) Als Nutzer solltest Du ja eigentlich nicht mehr mit der HW mit ISRs kommunizieren mussen. Als Autor müsstest Du Dein OS entsprechend designen.
Torsten R. schrieb: > Die CPU sich selbst. Wenn eine Funktion z.B. einen spin lock verwendet, > um eine kurze critical section zu locken, dann eine ISR ausführt und die > nun wieder versucht, den spin lock zu locken, dann hängt es halt. > Unterprechbar ist das dann nur noch mit einem ISR einer höheren Prio. Also wenn eine ISR ausgeführt wird und diese die Mutex locken will, die Mutex aber schon durch einen Task besetzt ist dieser Task aber wiederum durch die ISR unterbrochen wurde, kann die ISR die reentrate Funktion betreten, weil sie die Mutex nicht besitzt? Hab ich das richtig verstanden? > Unterprechbar ist das dann nur noch mit einem ISR einer höheren Prio. Meinst du dass die alte ISR (welche versucht die Mutex zu locken) solange ausgeführt wird, bis eine höher priorisierte ISR die alte ISR unterbricht und ihre Arbeit erledigt? Wenn die höher priorisierte ISR fertig exekutiert hat, wird dann nicht wieder die alte ISR versuchen die besetzte Mutex zu locken? Es tut mir wirklich Leid, aber ich hänge da irgendwie am Schlauch.
Johannes H. schrieb: > Torsten R. schrieb: >> Die CPU sich selbst. Wenn eine Funktion z.B. einen spin lock verwendet, >> um eine kurze critical section zu locken, dann eine ISR ausführt und die >> nun wieder versucht, den spin lock zu locken, dann hängt es halt. >> Unterprechbar ist das dann nur noch mit einem ISR einer höheren Prio. > > Also wenn eine ISR ausgeführt wird und diese die Mutex locken will, die > Mutex aber schon durch einen Task besetzt ist dieser Task aber wiederum > durch die ISR unterbrochen wurde, kann die ISR die reentrate Funktion > betreten, weil sie die Mutex nicht besitzt? Hab ich das richtig > verstanden? > Die Mutual Exclusion zwischen Tasks/Prozessen funktioniert per Definition grundsätzlich anders als zwischen Tasks und ISRs bzw. ISRs untereinander. Die Grundregel heisst, dass ISRs im Gegensatz zu Tasks NIEMALS während der Ausführung "warten" dürfen. Ein gegenseitiger Ausschluss, in dem ISRs beteiligt sind, ist grundsätzlich "asymmetrisch." Wenn ein niedrig priorisierter ISR oder eine Task versucht, kritischen Code auszuführen, der gegen einen (höher priorisierten) ISR konkurriert, darf in dem Zeitraum der gesamte ISR gar nicht erst starten (also muss dieser ISR ausmaskiert werden). Erst wenn der "geschützte" Code fertig ist, darf der Interrupt wieder freigegeben werden. Im Gegensatz dazu arbeiten Mutexes "symmetrisch," d.h. ihre Benutzung ist nur von tasks untereinander erlaubt und (von Details wie Priority Inversion Prevention abgesehen) für alle beteiligten tasks von der Benutzungsseite her identisch. >> Unterprechbar ist das dann nur noch mit einem ISR einer höheren Prio. > > Meinst du dass die alte ISR (welche versucht die Mutex zu locken) > solange ausgeführt wird, bis eine höher priorisierte ISR die alte ISR > unterbricht und ihre Arbeit erledigt? Wenn die höher priorisierte ISR > fertig exekutiert hat, wird dann nicht wieder die alte ISR versuchen die > besetzte Mutex zu locken? > s.o. > Es tut mir wirklich Leid, aber ich hänge da irgendwie am Schlauch. Ist auch nicht ganz einfach, die Materie... ;-) P.S. In Aller Regel versucht man Szenarien, in denen Tasks und ISRs um Ressourcen konkurrieren, zu vermeiden, um den ISR Durchsatz nicht zu verringern. Z.B. ist der typische Kontrollfluss in Gerätetreibern (Rx Seite) so, dass der ISR einen Ringpuffer befüllt und einer Verarbeitungstask Signale sendet, die den Ringpuffer wegarbeitet. Viele Entwickler denken nun, dass man den Ringpuffer gegen nebenläufigen Zugriff schützen muss, also den Interrupt ausmaskieren, während ein Zeichen ausgelesen wird. Bei näherer Betrachtung ist das aber in der Regel nicht notwendig, weil (wie eine Analyse ergibt) erst ein Ring Buffer Overflow ein Problem ergibt. Solange noch Platz im Puffer ist, darf der ISR gerne die Abarbeitung unterbrechen, um weitere Zeichen in den Ringpuffer einzuarbeiten. Zuviel Syncronisation ist in der nebenläufigen Programmierung genau so schlecht wie Zu Wenig (alte Bitpulerweisheit).
:
Bearbeitet durch User
Ok verstehe, also ist die einzige Möglichkeit, bevor man die Funktion betritt, die ISR abschalten ausmaskieren und sobald man fertig ist wieder einschalten, und keine statischen oder globalen Variablen verwenden oder alles atomar ausfüren... Puhh das war ziemlich heftig :) jedenfalls vielen Dank für die Hilfe. Lg Johannes
Johannes H. schrieb: > Ok verstehe, also ist die einzige Möglichkeit, bevor man die Funktion > betritt, die ISR abschalten ausmaskieren und sobald man fertig ist > wieder einschalten, und keine statischen oder globalen Variablen > verwenden oder alles atomar ausfüren... Ja, und praktischer Weise macht man das nicht extern zur Funktion, sonder in der Funktion, den die Funktion selbst kennt Ihre Anforderung an Exklusivität besser.
Eine Funktion ist reentrant, wenn beliebig viele Instanzen davon ausgeführt werden können. Ein typisches Beispiel sind Rekursionen (die Funktion ruft sich selbst auf). Da Rekursionen nicht sonderlich effizient sind (Zeit-, Stackverbrauch), versucht der Compiler oft, sie in eine Schleife aufzudröseln.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.