Multi-task data access synchronization

When the same data is accessed by multiple tasks, the tasks may access the same data simultaneously, depending on the task/real-time configuration. If the data is written by at least one of the tasks, the data may have an inconsistent state during or after a change. To prevent this, all concurrent accesses must be synchronized so that only one task at a time can access the shared data.

If the same data is accessed by several tasks and the data is written for at least one of these accesses, all read and write accesses must be synchronized. This applies irrespective of whether the tasks run on one or more CPU cores.

WARNING

Inconsistencies and other risks due to unsecured data access

If concurrent accesses are not synchronized, there is a risk of inconsistent or invalid data records. Depending on how the data is used in the further course of the program, this can result in incorrect program behavior, undesired axis movement or even sudden program standstill. Depending on the controlled system, damage to equipment and workpieces may occur, or people's health and lives may be endangered.

General synchronization options between the TcCOM modules are described here. The following mechanisms were described:

Ideally, however, you should try to avoid the need for synchronization. Otherwise, the simplest way is usually the exchange via the process image, which copies the data between the cycles from the output process images to the input process images and thus ensures a consistent state.
If this is not sufficient and data has to be accessed from different contexts, one of the following options can be used.

It is important to differentiate between the task contexts that are to access the data. In the TwinCAT Runtime, a distinction is made between the Windows kernel mode thread contexts (Windows context for short) and the TwinCAT real-time task contexts (RT context). During initialization of TwinCAT modules, the IP, PS, SP and PI transitions are executed in the Windows context. The SO and OS transitions are executed in the RT context.

The SDK offers appropriate synchronization options for such scenarios. Nevertheless, the TcCOM modules should be designed such that that they are independent of each other, at least in the Windows context, and thus do not require synchronization. The transitions in the RT context can use CriticalSections if required.

For the CriticalSection and semaphores it applies that in case of a lock the task waits for the release. In the meantime the core is released for other tasks. With CriticalSections the active task inherits the priority of the waiting task ("Priority Inheritance").

CriticalSections

Instances of CriticalSections are created through TwinCAT real-time. This instance can be initialized in the Windows context as well as in the RT context. The CriticalSection instance can only be used in the RT context.

TwinCAT real-time uses "priority inheritance" to prevent a task with lower priority from indirectly blocking a task with high priority.

CCriticalSectionInstance

The CCriticalSectionInstance class provides the interface to handle Critical Sections and has the required memory. To create a Critical Section the class requires the object ID of the TwinCAT real-time instance, which is available via OID_TCRTIME_CTRL, as well as a reference to the TwinCAT object server via a pointer to ITComObjectServer.

Methods:

ADS_E_INVALIDPARM

Invalid Critical Section Provider

ADS_E_NOINTERFACE

The object ID is set to a reference that is not a Critical Section Provider, i.e. ITcRTime is not implemented.

E_FAIL

Internal error from the Critical Section Provider.

EnterCriticalSection() and LeaveCriticalSection() must be called in the RT context, otherwise the following return value is returned:

ADS_E_INVALIDCONTEXT

Return value if Critical Section is entered outside the RT context. The Critical Section is not entered.

If these methods are used without initializing the Critical Section, S_OK is returned without further action. All other methods can be used in the RT context as well as in the Windows context.

CriticalSections allow nested calls and require an associated LeaveCriticalSection() call for each EnterCriticalSection() call. The Critical Section is released when the last LeaveCritcalSection() is called.

Sample:

The sample shows how to use a CriticalSection to prevent simultaneous access to a date via an interface method call.

Critical Section Concurrent

The CCriticalSectionInstanceConcurrent class allows concurrent access. This can be used if several tasks have read access to the data to be protected, but all other accesses must be prevented in the case of write access.

Methods:

ADS_E_INVALIDPARM

Invalid Critical Section Provider

ADS_E_NOINTERFACE

The object ID is set to a reference that is not a Critical Section Provider, i.e. ITcRTime is not implemented.

E_FAIL

Internal error from the Critical Section Provider.

EnterCriticalSection(), EnterCriticalSectionConcurrent() and LeaveCriticalSection() must be called in the RT context, otherwise the following return value is returned:

ADS_E_INVALIDCONTEXT

Return value if Critical Section is entered outside the RT context. The Critical Section is not entered.


If these methods are used without initializing the Critical Section, S_OK is returned without further action. All other methods can be used in the RT context as well as in the Windows context.

Semaphores

Semaphores are used to synchronize access to limited resources. They can also be used to implement a notification event. Semaphores are provided by the TwinCAT real-time through the CSemaphoreInstance class.

CSemaphoreInstance

The CSemaphoreInstance class provides the interface for handling semaphores. To create a semaphore, the instance requires the object ID of the TwinCAT real-time instance, which is available via OID_TCRTIME_CTRL, as well as a reference to the TwinCAT object server via a pointer to ITComObjectServer.

Methods:

MAKE_RTOS_HRESULT(51)

Semaphore overflow. For example, if the internal memory is insufficient.

RTIME_NOWAIT (-1)

Method immediately returns S_OK if the semaphore is available.
Method returns a timeout if no resource is available.

RTIME_ENDLESSWAIT (0)

Method waits indefinitely for availability of the semaphores

The method returns S_OK if the semaphore was successfully obtained; otherwise:

MAKE_RTOS_HRESULT(10)

Indicates a timeout. If nTimeout is set as RTIME_NOWAIT, this semaphore is not available.

Sample:

Sample24: Semaphores