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