Data Coherency

From MotoHawk
Jump to navigationJump to search

Data Coherency Considerations

The coherency of the data used by a model must be considered when it is executing in multi-threaded environment. MotoHawk utilizes a a multi-threaded execution environment, which is discussed in more detail [ControlCoreTasking.html here]. Proper management of coherent data transfer is essential to ensure data remains consistent (or unchanged) within the context of the thread that is executing. Three examples of different "types" of data coherency will illustrate what can occur.

  • HighWriteLowRead High Priority Task Write - Low Priority Task Read
  • LowWriteHighRead Low Priority Task Write - High Priority Task Read
  • DataCorruption Data Inconsistency / Data Corruption

Data Coherency Examples

High Priority Task Write - Low Priority Task Read

A high priority task write - low priority task read type of data coherency occurs when a higher priority task (say FGND Time Task) updates a shared variable that is used in calculations implemented in a lower priority task (say BGND Time Task). Consider the following example that illustrates what can happen without coherent data transfer of the shared variable in the lower priority task's calculation:

Center

Let say we have a vector of 10 elements for which we are filling in with the result of a calculation implemented in the BGND task that uses the shared variable A that gets updated by the higher priority FGND task. At the start of the BGND task we begin calculating the vector elements in the lower priority task, in which A = x1. We get half way through the vector calculations and the FGND task interrupts the process and updates shared variable A = x2, then gives the CPU back to the BGND task to resume execution. What has changed? The calculation that uses the shared variable is now using the updated value which is different from the original value used to calculate the first 5 elements. This is an example of incoherent data. Since we did not take care of ensuring the calculation was done atomically or simply taking a "snapshot" (copy) of A before starting the vector calculations, we have half the vector calculated using an old value and the other half calculated using a more up-to-date value. Issues associated with a lack of data coherency will appear to manifest randomly in the application since for the most part the data will remain coherent. The issue only presents when the update occurs at the wrong time. Taking copies overcomes the issue, but at the cost of higher execution and memory resource consumption. Thus the need for data coherency should be evaluated and the necessary steps taken to handle it only when coherency is required.

Low Priority Task Write - High Priority Task Read

A low priority task write - high priority task read type of data coherency occurs when a lower priority task (say BGND Time Task) updates a shared variable that is used in calculations implemented in a higher priority task (say FGND Time Task). Consider the following example that illustrates what can happen without coherent data transfer of the shared variable in the higher priority task's calculation:

Center

As opposed to the previous example, data coherency issues arise under this condition if multiple variables are used in a higher priority task calculation, but are updated in the lower task priority calculation. Consider a simple calculation implemented in the FGND task such as C = B + A, where A and B both are updated in the BGND task. As shown in the illustration above, A obtains a new value, then the FGND task interrupts the BGND task before it can update variable B.� The end result is that the calculation of C was from a more up-to-date value of A and an older value of B (i.e. C = x2 + y1 instead of C = x2 + y2).

This "type" of data coherency may or may not be an issue depending on the application, but is important to understand what can happen if your calculation shares data across task boundaries.

Data Inconsistency / Data Corruption

The third type of data coherency involves datatypes whose bit-widths are larger than the processor's register size. Consider 32-bit integers or floating point types that are implemented on a processor with 16-bit registers or 64-bit datatypes on a processor with 32-bit registers. It is possible to have data that is only partially updated if a higher priority task interrupts a lower priority task in the middle of a non-protected update or copy of the value (i.e. one half of the value's bits are old, the other half are new) because the value is not atomic on the system. In situations like these it is critical that these values are copied atomically (non-interrupted) when crossing task boundaries.

Achieving Coherent Data Transfer

Atomic copy operations of shared variables must occur when crossing task boundaries in order to avoid data coherency issues. MotoHawk provides the [../MotoHawk_lib_Blocks/CriticalBuffer.html Critical Buffer] block to allow non-interruptable copy to occur.

Center

Use of the buffer ensures safe data transfer, but it is important to consider how the data is used in a calculation because performing this action multiple times has an adverse effect on efficiency and performance. It is also important to minimize the time spent during any critical code section, as interrupts will be ignored and remain in a pending state until the critical section of code completes. Also, note that if multiple events occur for the same interrupt during a critical section of code, the interrupt will only be serviced once at the end of the critical code section since the processor only knows an interrupt has occurred, not how many times it has occurred.

Consider the example of performing logic in a lower priority task that sets a fault condition using multiple shared variables that are calculated in a higher priority task. In this case, depending on the application, it may be more desirable to have the fault condition determined based on any or all most up-to-date values, in which case the requirement for coherent data transfer may not be necessary.

Coherent Data Transfer Strategy

A common strategy for implementing coherent data transfer is to first consider task priorities and where the shared variable is being produced and consumed. If a high priority task trigger is the producer and the low priority task trigger is the consumer, the atomic copy operation should occur at the start of the low priority task trigger. On the other hand, if a lower priority task trigger is the producer the the higher priority task trigger is the consumer, then the atomic copy operation should occur at the end of the low priority task trigger.

Center

Data Coherency Example

Consider the following model template illustrating proper data transfer management for the following three triggers, listed from highest to lowest priority, which are executing in different tasks and sharing data:

  • Foreground TDC - Executes in FGND Angle Task
  • Foreground 5 ms - Executes in FGND Time Task
  • Background 50 ms - Executes in BGND Task

DataCoherency Example1.PNG

Priority numbers of 0, 1, and 2 were assigned to each triggered subsystem to further illustrate each trigger's relative priority, where lowest number = highest priority.

Now let's peek into each triggered subsystem to show the internal layout.

  • Foreground TDC Subsystem

Center

Since the Foreground TDC trigger executes in the highest priority task in our example and shares information with the lower priority Foreground 5ms trigger, there is no need to perform coherent data transfer in or out. Recall from above that coherent data transfer occurs within the lower priority task triggers.

  • Foreground 5ms Subsystem

Center

Since the Foreground 5ms trigger shares data with the Foreground TDC trigger, we must perform proper data transfer management. For shared variables produced in the Foreground TDC trigger and consumed in the Foreground 5ms trigger, we need to perform an atomic transfer High Priority Task Write - Low Priority Task Read. This is done with a MotoHawk Critical Buffer for shared variables that require coherent transfer within the Data Transfer Management In subsystem. For shared variables produced in the Foreground 5ms trigger and consumed in the Foreground TDC trigger, we again need to perform an atomic transfer Low Priority Task Write - High Priority Task Read. This is done with a MotoHawk Critical Buffer for shared variables that require coherent transfer within the Data Transfer Management Out subsystem. Note that the data from the Background 50ms trigger is simply passed in since the data transfer from lower priority Background 50ms trigger to higher priority Foreground 5ms trigger is managed within the Background 50ms subsystem. Also note that not all data on the bus may require coherent transfer, so only perform the atomic transfer of data that must be coherent.

  • Background 50ms Subsystem

Center

Note that the Background 50ms subsystem is similar to the Foreground 5ms subsystem in layout since it also shares information with higher priority Foreground 5ms subsystem. The flow of information between these two triggers is the same as above and again note that any information that should be coherent should be copied atomically and any information that does not require atomic transfer should simply be passed through and not copied.