Multitask-Datenzugriffs-Synchronisation

Wenn von mehreren Tasks auf dieselben Daten zugegriffen wird, kann es je nach Task‑/Echtzeitkonfiguration vorkommen, dass die Tasks gleichzeitig auf dieselben Daten zugreifen. Wenn die Daten dabei von mindestens einer der Tasks geschrieben werden, können die Daten während oder nach einer Änderung einen inkonsistenten Zustand haben. Um dies zu verhindern, müssen alle konkurrierenden Zugriffe synchronisiert werden, sodass zu einem Zeitpunkt nur von höchstens einer Task auf die gemeinsam genutzten Daten zugegriffen werden kann.

Wenn also von mehreren Tasks auf dieselben Daten zugegriffen wird und bei mindestens einem dieser Zugriffe die Daten geschrieben werden, müssen alle lesenden und schreibenden Zugriffe synchronisiert werden. Dies gilt unabhängig davon, ob die Tasks auf einem oder mehreren CPU Kernen laufen.

WARNUNG

Inkonsistenzen und weitere Gefahren durch ungesicherten Datenzugriff

Werden konkurrierende Zugriffe nicht synchronisiert, so besteht die Gefahr eines inkonsistenten oder ungültigen Datensatzes. Je nachdem wie die Daten im weiteren Programmverlauf genutzt werden, kann dies ein Fehlverhalten des Programms, eine ungewünschte Achsbewegung oder auch den plötzlichen Programmstillstand zur Folge haben. Abhängig von der gesteuerten Anlage können Schäden an Anlage und Werkstücken entstehen oder Gesundheit und Leben von Personen gefährdet werden.

Allgemeine Synchronisationsmöglichkeiten zwischen den TcCOM Modulen sind bereits hier beschrieben. Hierbei wurden die folgenden Mechanismen beschrieben:

Idealerweise sollte jedoch versucht werden die Notwendigkeit einer Synchronisation zu vermeiden, ansonsten ist der einfachste Weg meistens der Austausch über das Prozessabbild, welche die Daten zwischen den Zyklen von den Ausgangs-Prozessabbildern zu den Eingangs-Prozessabbildern kopieren und dadurch für einen konsistenten Zustand sorgen.
Wenn dieses nicht ausreicht und Daten aus unterschiedlichen Kontexten zugegriffen werden müssen, kann einer der folgenden Möglichkeiten genutzt werden.

Es ist dabei wichtig die Task-Kontexte zu unterscheiden, welche die Daten zugreifen sollen. In der TwinCAT Runtime wird zwischen den Windows Kernel Mode Thread-Kontexten (kurz: Windows Kontext) sowie den TwinCAT Realtime Task-Kontexten (RT-Kontext) unterschieden. Während der Initialisierung von TwinCAT Modulen werden die Transitionen IP, PS, SP, PI im Windows Kontext ausgeführt. Die Transitionen SO und OS werden im RT-Kontext ausgeführt.

Das SDK bietet für solche Szenarien entsprechende Synchronisierungsmöglichkeiten. Trotzdem sollten die TcCOM Module in einer Weise konzipiert werden, dass sie zumindest im Windows-Kontext unabhängig voneinander sind und damit ohne Synchronisierungs-Bedarf auskommen. Die Transitionen im RT-Kontext können bei Bedarf CriticalSections nutzen.

Für die CriticalSection und Semaphoren gilt, dass im Fall einer Sperre die Task auf die Freigabe wartet, in der Zwischenzeit der Core für andere Tasks freigegeben wird. Bei CriticalSections erbt die jeweils aktive Task dabei ggf. die Priorität der wartenden Task („Priority Inheritence“).

CriticalSections

Instanzen von Critical Sections werden durch die TwinCAT Realtime angelegt. Diese Instanz kann sowohl im Windows-Kontext wie auch im RT-Kontext initialisiert werden. Genutzt werden kann die Critical Section Instanz nur im RT-Kontext.

Die TwinCAT Realtime nutzt dabei “priority inheritance” um zu verhindern, dass eine Task mit geringerer Priorität indirekt einen Task mit hoher Priorität blockiert.

CCriticalSectionInstance

Die Klasse CCriticalSectionInstance bietet die Schnittstelle an, um Critical Sections zu handhaben und besitzt den nötigen Speicher. Um eine Critical Section anzulegen benötigt die Klasse die Objekt-ID der TwinCAT Realtime Instanz, welche über OID_TCRTIME_CTRL bereitsteht, sowie eine Referenz zu dem TwinCAT Objekt-Server über einen Pointer auf ITComObjectServer.

Methoden:

ADS_E_INVALIDPARM

Ungültiger Critical Section Provider

ADS_E_NOINTERFACE

Die Objekt ID ist auf eine Referenz gesetzt, die kein Critical Section Provider darstellt, also ITcRTime nicht implementiert.

E_FAIL

Interner Fehler von dem Ciritical Section Provider.

EnterCriticalSection() und LeaveCriticalSection() müssen im RT-Kontext aufgerufen werden, ansonsten wird folgender Rückgabewert zurückgegeben:

ADS_E_INVALIDCONTEXT

Rückgabewert, wenn Critical Section außerhalb der RT Kontext betreten wird. Die Critical Section wird nicht betreten.

Wenn diese Methoden genutzt werden, ohne dass die Critical Section initialisiert wurde, wird S_OK zurückgegeben, ohne dass etwas gemacht wird. Alle anderen Methoden können sowohl im RT-Kontext wie auch im Windows-Kontext benutzt werden.

CriticalSections erlauben verschachtelte („nested“) Aufrufe und verlangen für jeden EnterCriticalSection()-Aufruf einen zugehörigen LeaveCriticalSection()-Aufruf. Die Freigabe der Critical Section ergibt sich dann beim Aufruf des letzten LeaveCritcalSection().

Beispiel:

Das Beispiel zeigt eine Nutzung einer CriticalSection um über einen Interface-Methodenaufruf eine gleichzeitigen Zugriff auf ein Datum zu verhindern.

Critical Section Concurrent

Die Klasse CCriticalSectionInstanceConcurrent erlaubt einen konkurrierenden Zugriff (Concurrent access). Dieser kann genutzt werden, wenn mehrere Tasks lesend auf die zu schützenden Daten zugreifen, aber bei einem schreibenden Zugriff alle anderen Zugriffe unterbunden werden müssen.

Methoden:

ADS_E_INVALIDPARM

Ungültiger Critical Section Provider

ADS_E_NOINTERFACE

Die Objekt ID ist auf eine Referenz gesetzt, die kein Critical Section Provider darstellt, also ITcRTime nicht implementiert.

E_FAIL

Interner Fehler von dem Critical Section Provider.

EnterCriticalSection(), EnterCriticalSectionConcurrent() und LeaveCriticalSection() müssen im RT-Kontext aufgerufen werden, ansonsten wird folgender Rückgabewert zurückgegeben:

ADS_E_INVALIDCONTEXT

Rückgabewert, wenn Critical Section außerhalb der RT Kontext betreten wird. Die Critical Section wird nicht betreten.


Wenn diese Methoden genutzt werden, ohne dass die Critical Section initialisiert wurde, wird S_OK zurückgegeben, ohne dass etwas gemacht wird. Alle anderen Methoden können sowohl im RT-Kontext wie auch im Windows-Kontext benutzt werden.

Semaphoren

Semaphoren werden genutzt, um den Zugriff auf limitierte Ressourcen zu synchronisieren. Sie können auch genutzt werden um eine Benachrichtigung (Notification Event) zu realisieren. Semaphoren werden durch die TwinCAT Realtime durch die Klasse CSemaphoreInstance bereitgestellt.

CSemaphoreInstance

Die Klasse CSemaphoreInstance bietet die Schnittstelle an, um Semaphoren zu handhaben. Um eine Semaphore anzulegen, benötigt die Instanz die Objekt-ID der TwinCAT Realtime Instanz, welche über OID_TCRTIME_CTRL bereitsteht, sowie eine Referenz zu dem TwinCAT Objekt-Server über einen Pointer auf ITComObjectServer.

Methoden:

MAKE_RTOS_HRESULT(51)

Semaphoren Overflow. Beispielsweise wenn der interne Speicher nicht ausreicht.

RTIME_NOWAIT (-1)

Methode liefert sofort S_OK, wenn die Semaphore verfügbar ist.
Methode liefert ein Timeout, falls keine Ressource verfügbar ist.

RTIME_ENDLESSWAIT (0)

Methode wartet unendlich lange auf die Verfügbarkeit der Semamphore

Die Methode liefert S_OK, wenn den Semaphoren erfolgreich bezogen wurde; ansonsten:

MAKE_RTOS_HRESULT(10)

Zeigt einen Timeout an. Wenn nTimeout als RTIME_NOWAIT gesetzt wurde, ist diese Semaphore nicht verfügbar.

Beispiel:

Beispiel24: Semaphoren