TestAndSet

TestAndSet 1:

You can use this function to check and set a flag. There is no option to interrupt the process. This allows data accesses to be synchronized. The mode of operation of a semaphore can be achieved with TestAndSet.

If the function call is successful, the function returns TRUE and the desired data can be accessed. If the function call is unsuccessful, the function returns FALSE and the desired data cannot be accessed. In this case, an alternative treatment must be provided for.

VAR_IN_OUT

VAR_IN_OUT
    Flag : BOOL; (* Flag to check if TRUE or FALSE *)
END_VAR

Flag: Boolean flag to be checked

  • if it was FALSE, the flag was free and is set (and therefore blocked from now on), and the function returns TRUE
  • if it was TRUE, the flag was already assigned (and therefore blocked), and the function returns FALSE

Sample

VAR_GLOBAL
    bGlobalTestFlag : BOOL;
END_VAR
VAR
    nLocalBlockedCounter : DINT;
END_VAR
IF TestAndSet(GVL.bGlobalTestFlag) THEN
    (* bGlobalTestFlag was FALSE, nobody was blocking, NOW
    bGlobalTestFlag is set to TRUE and blocking others *)
    
    (* ... *)
    
    (* remove blocking by resetting the flag *) 
    GVL.bGlobalTestFlag := FALSE;
ELSE
    (* bGlobalTestFlag was TRUE, somebody is blocking *)
    nLocalBlockedCounter := nLocalBlockedCounter + 1;
    
    (* ... *)
END_IF

NEGATIVE sample

Caution is advised with a further encapsulation, e.g. in a function block, as this can destroy the desired atomic operation. Secure synchronization of data accesses can then no longer take place. In the following, a NEGATIVE sample is included that shows how the function may NOT be used. If two contexts were to request access at the same time in this implementation, both might assume that the access is allowed and simultaneous, unsecured accessing of the data would take place.

FUNCTION_BLOCK FB_MyGlobalLock
VAR_INPUT
    bLock    : BOOL; // set TRUE to lock & set FALSE to unlock
END_VAR
VAR_OUTPUT
    bLocked : BOOL;
END_VAR

IF bLock THEN
    TestAndSet(bLocked);
ELSE // unlock
    bLocked := FALSE;
END_IF
IF NOT GVL.fbGlobalLock.bLocked THEN
    GVL.fbGlobalLock(bLock := TRUE);
    
    (* ... *)
    
    GVL.fbGlobalLock(bLock := FALSE);
END_IF

 

The function block FB_IecCriticalSection offers the application of critical sections as an alternative Mutex method.

Requirements

Development environment

Target system type

PLC libraries to include (Category group)

TwinCAT v3.1.0

PC or CX (x86, x64, ARM)

Tc2_System (System)