Der Multicore-Operator ist eine Erweiterung der Norm IEC 61131-3.
Der Operator kann zur Realisierung einer Semaphore verwendet werden, beispielsweise um den exklusiven Zugriff auf eine Variable zu garantieren, die von verschiedenen Tasks geschrieben wird.
__COMPARE_AND_SWAP
bekommt als Eingabe einen Pointer auf eine Variable vom Datentyp __XWORD
, einen alten Wert und einen neuen Wert, beispielsweise bMutex := __COMPARE_AND_SWAP(ADR(dwSynch), dwOld, dwNew);
. Der alte und neue Wert können auch Variablen vom Datentyp __XWORD
sein. Die referenzierte __XWORD
-Variable wird mit dem alten Wert verglichen und wenn beide gleich sind, dann wird
der neue Wert geschrieben.
Das Ergebnis der Funktion ist TRUE
, wenn der neue Wert geschrieben werden konnte.
Der Datentyp __XWORD
wird vom Compiler automatisch bei 32-Bit-Systemen durch DWORD
und bei 64-Bit-Systemen durch LWORD
ersetzt.
Diese Operation verläuft atomar, sie kann also nicht von einer anderen Task unterbrochen werden, dies gilt auch auf Multicore-Plattformen.
Beispiel
Das folgende Beispiel zeigt eine typische Verwendung. Es soll ein exklusiver Zugriff
auf eine Variable vom Typ STRING
implementiert werden, die über den Pointer pstrOutput
angesprochen wird.
Der Zugriff auf einen String ist nicht atomar. Wenn mehrere Tasks gleichzeitig auf denselben String schreiben, dann kann der Inhalt inkonsistent sein.
Mit dieser Funktion ist es nun möglich in verschiedenen Tasks dieselbe STRING-Variable zu schreiben.
FUNCTION ExclusiveStringWrite : BOOL VAR_INPUT strToWrite : STRING; pstrOutput : POINTER TO STRING; END_VAR VAR_STAT dwSynch : __XWORD; END_VAR VAR bMutex: BOOL; END_VAR bMutex:= __COMPARE_AND_SWAP(ADR(dwSynch), 0, 1); (* compare with 0 and write 1 as atomic operation *) IF bMutex THEN // bMutex is TRUE if write could be done pstrOutput^ := strToWrite; // Now you can write safely on the string dwSynch := 0; // The __XWORD variable must be reset. ExclusiveStringWrite := TRUE; // Writing was successful ELSE ExclusiveStringWrite := FALSE; // Writing was not successful END_IF