Operator ‘__XADD’ΒΆ

The multicore operator is an extension of the IEC 61131-3 standard.

The operator can be used for implementing an atomic counter. If an integer variable is incremented by means of ordinary addition, for example iTest := iTest + 1;, then this operation is not executed atomically. Another access to the variable could take place between reading and writing the variable.

If the counter is incremented in multiple tasks, then the counter result can be less than the number of counting cycles. So if two tasks execute the above code one time and the variable previously had the value 0, then the variable can then have the value 1. This is especially problematic if arrays are being processed in multiple tasks and a unique index is required for the array in each processing cycle.

When the __XADD operator is called, it gets a pointer to a type DINT variable as the first summand and a type DINT value as the second summand. __XADD returns the old value of the first summand and in the same step adds the second summand to the first summand.

For example, the function call can look like this: diOld := __XADD(ADR(diVar), deAdd);

Example

The following example shows a typical usage. An array should be populated from two tasks. In the process, all positions in the array should be used and no position should be overwritten.

With this function, multiple tasks can populate a Boolean array.

FUNCTION WriteToNextArrayPosition : BOOL
VAR_EXTERNAL
        g_diIndex : DINT;  // Index and array are globally defined and used by multiple tasks
        g_boolArray : ARRAY [0..1000] OF BOOL;
END_VAR
VAR_INPUT
        bToWrite : BOOL;
END_VAR
VAR
        diIndex : DWORD;
END_VAR

diIndex := __XADD(ADR(g_diIndex), 1);       // Returns a unique index
WriteToNextArrayPosition := FALSE;
IF (diIndex >= 0 AND diIndex <= 1000) THEN
        g_boolArray[diIndex] := bToWrite;         //Writes to unique index
        WriteToNextArrayPosition := TRUE;         // TRUE: Array was not full yet
END_IF

See also