SA0103: Concurrent access on not atomic data

Function

Determines non-atomic variables (for example with data types STRING, WSTRING, ARRAY, STRUCT, FB instances, 64-bit data types) that are used in more than one task.

Reason

If no synchronization occurs during access, inconsistent values may be read when reading in one task and writing in another task at the same time.

Exception

This rule does not apply in the following cases:

  • If the target system has an FPU (floating point unit), the access of several tasks to LREAL variables is not determined and reported.
  • If the target system is a 64-bit processor or "TwinCAT RT (x64)" is selected as the solution platform, the rule does not apply for 64-bit data types.

Importance

Medium

SA0103: Concurrent access on not atomic data 1:

See also rule SA0006: Write access from several tasks.

Samples:

Structure ST_sample:

TYPE ST_Sample :
STRUCT
    bMember : BOOL;
    nTest   : INT;
END_STRUCT
END_TYPE

Function block FB_Sample:

FUNCTION_BLOCK FB_Sample
VAR_INPUT
    fInput  : LREAL;
END_VAR

GVL:

{attribute 'qualified_only'}
VAR_GLOBAL
    fTest   : LREAL;              // => no error SA0103: Since the target system has a FPU, SA0103 does not apply.
    nTest   : LINT;               // => error reporting depends on the solution platform:
                                     // - SA0103 error if solution platform is set to "TwinCAT RT(x86)"
                                     // - no error SA0103 if solution platform is set to "TwinCAT (x64)"
    sTest   : STRING;             // => SA0103
    wsTest  : WSTRING;            // => SA0103
    aTest   : ARRAY[0..2] OF INT; // => SA0103
    aTest2  : ARRAY[0..2] OF INT; // => SA0103
    fbTest  : FB_Sample;          // => SA0103
    stTest  : ST_Sample;          // => SA0103
END_VAR

Program MAIN1, called by task PlcTask1:

PROGRAM MAIN1
VAR
END_VAR
GVL.fTest         := 5.0;
GVL.nTest         := 123;
GVL.sTest         := 'sample text';
GVL.wsTest        := "sample text";
GVL.aTest         := GVL.aTest2;
GVL.fbTest.fInput := 3;
GVL.stTest.nTest  := GVL.stTest.nTest + 1;

Program MAIN2, called by task PlcTask2:

PROGRAM MAIN2
VAR
    fLocal  : LREAL;
    nLocal  : LINT;
    sLocal  : STRING;
    wsLocal : WSTRING;
    aLocal  : ARRAY[0..2] OF INT;
    aLocal2 : ARRAY[0..2] OF INT;
    fLocal2 : LREAL;
    nLocal2  : INT;
END_VAR
fLocal  := GVL.fTest + 1.5;
nLocal  := GVL.nTest + 10;
sLocal  := GVL.sTest;
wsLocal := GVL.wsTest;
aLocal  := GVL.aTest;
aLocal2 := GVL.aTest2;
fLocal2 := GVL.fbTest.fInput;
nLocal2 := GVL.stTest.nTest;