Table of Contents

Mutex

Namespace
ZPlatform
Implements
FUNCTION_BLOCK Mutex IMPLEMENTS ZCore.IMutex

Mutex implements a simple locking mechanism by utlizing a test-and-set instruction combined with an external owner handle. There are two main purposes for using this object

  • Mutual exclusion to prevent race conditions when using multiple tasks by using Lock. It is required that one task of execution never enters a critical section while a concurrent task of execution is already accessing critical section, which refers to an interval of time during which a thread of execution accesses a shared resource, such as Shared-data-objects, shared-resources, shared-memory. For instance, when using a Logger in an application the methods for writing a line into a file are not thread-safe. Without locking, there could be unexpected behavior when two tasks simultaneously add a new message to the logger. This particular problem is solved by the Logging function block, which internally uses a Mutex instance by guarding every call to a logging method with a mutex lock.

    IF _mutex.Lock(THIS^)
    THEN
      _logger.Info('Text');
    _mutex.Unlock(THIS^);
    END_IF
    
  • Taking ownership of an object to execute a set of actions and block others from accessing the object. This use-case is PLC specific, because in general, PLC calls are not blocking. For example, when we move an axis from A to B, we have to start the movement in 1 PLC cycle and poll the position for each following cycle until the axis actually reached position B. In a sense, all actions that are performed in a PLC are concurrent within 1 PLC cycle. In the previous example, a Mutex instance can be used to block others from starting a movement once a movement command is already in order.

    IF _step.OnEntry()
    THEN
      // Try to get a lock to the mutex, if this fails, try again the next cycle
      IF NOT _mutex.TryLock(THIS^)
      THEN
        _step.RepeatStep();
        RETURN;
      END_IF
      _axis.MoveAbsoluteAsync(position:=100, speed:=1);
    END_IF
    
    IF _axis.Done
    THEN
      _mutex.Unlock(THIS^);
    END_IF
    

Please note, that while the first purpose of a Mutex, which utilizes the Lock method, is usually only relevant if multiple tasks are used in a PLC. However, the second purpose of a Mutex is also relevant for PLCs with only one task, because of the concurrent nature of PLCs.

Methods

IsLocked

METHOD IsLocked () : BOOL

Return if this mutex got locked by any potential owner. Use IsLockedBy for querying the state of a specific potential owner.

This method is thread-safe and therefore may be used from multiple tasks and also on different CPU-cores at once.

Returns

BOOL

IsLockedBy

METHOD IsLockedBy (
 [input] locker : ZCore.ZPointer) : BOOL

This method returns TRUE if this mutex is locked by a specific object. If the actual object is not of particular interest, the method IsLocked may be used instead.

This method is thread-safe and therefore may be used from multiple tasks and also on different CPU-cores at once.

Inputs

locker ZPointer

Returns

BOOL

Lock

METHOD Lock (
 [input] locker : ZCore.ZPointer) : BOOL

Lock the Mutex where the owner of the instance that wants to lock the Mutex is given by a number. Usually it is either an enum entry that is uniquely linked to a locker or simply a pointer to the locker by using THIS^ as parameter for the method.

This method blocks the current thread until the lock can be achieved and should be used with special care! To be specific, this method should only be used to guard calls that are finished in << 1 cycle. It is thread-safe and therefore may be used from multiple tasks and also on different CPU-cores at once.

Warning

Even though this lock is blocking the current task, the method can still return FALSE when another Task is in a breakpoint or if the mutex is locked by a different locker.

Warning

Lock utilizes FB_IecCriticalSection, which is not available on every hardware. For instance, it is not supported by the following targets

  • Devices with Windows CE before TwinCAT 3.1.4022.29
  • TwinCAT's Usermode Runtime

When using Lock in a PLC that uses more than 1 task, on a target that is not supported by FB_IecCriticalSection, this method will always return FALSE.

Inputs

locker ZPointer

Returns

BOOL

TryLock

METHOD TryLock (
 [input] locker : ZCore.ZPointer,
 [input] recursive : BOOL) : BOOL

Try to lock the Mutex where the owner of the instance that wants to lock the Mutex is given by a number. Usually it is either an enum entry that is uniquely linked to a locker or simply a pointer to the locker by using THIS^ as parameter for this method.

_mutex.TryLock(THIS^);

This method will only succeed (return TRUE), if the locker already has ownership of this Mutex (only for recursive=true) or if the Mutex is not locked by any other party at the moment (regardless of the recursive parameter)

This method is thread-safe and therefore may be used from multiple tasks and also on different CPU-cores at once.

Inputs

locker ZPointer
recursive BOOL

recursive=true doesn't care if the object is already locked by locker (method returns true in that case)

Returns

BOOL

TryLockTransfer

METHOD TryLockTransfer (
 [input] locker : ZCore.ZPointer,
 [input] recursive : BOOL,
 [input] lockerDst : ZCore.ZPointer) : BOOL

Try to lock the Mutex (same as TryLock) - if successful, the lock is directly passed to another locker. In contrast to unlocking the Mutex first from owner1 and then locking it with owner2, this method ensures that owner2 will get the lock. If locker=0 this method will fail.

The method is thread-safe and therefore may be used from multiple tasks and also on different CPU-cores at once.

Inputs

locker ZPointer
recursive BOOL

recursive=true doesn't care if the object is already locked by locker (method returns true in that case)

lockerDst ZPointer

Returns

BOOL

Unlock

METHOD Unlock (
 [input] locker : ZCore.ZPointer) : BOOL

With this method one can try to unlock the Mutex. The owner of the instance that wants to unlock the Mutex is given by a number. Usually it is either an enum entry that is uniquely linked to a locker or simply a pointer to the locker by using THIS^ as parameter for this method.

_mutex.Unlock(THIS^);

This method will succeed only (return TRUE), if the locker already has ownership of this Mutex or if the Mutex is not locked by any other party at the moment.

The method is thread-safe and therefore may be used from multiple tasks and also on different CPU-cores at once.

Note

It is save to call this method even if locker is not the owner of this Mutex at the moment. In this case, this method will simply return without changing anything for the Mutex instance.

Inputs

locker ZPointer

Returns

BOOL