Skip to main content

Operator: __COMPARE_AND_SWAP

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.

Tipp

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 155. 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