Hello,
I have a pretty generic question about embedded RTOS systems and data integrity.
I'm using RTX and I have several instances of structures that need to be read/written from several task.
As an example, take:
struct demo { int var_a; int var_b; int var_a_max; int var_a_min; }
If I have several global demo instances, what is the 'danger' in allowing several tasks to R/W the global instances?
I understand that the values could change mid execution but say you implemented a simple "lock and copy" procedure before each tasks loop execution.
Would mailboxes really be required in this case?
Further, what if all tasks only ever read/write one of the fields (var_a) do you even need a lock and copy or would simple copy do?
Finally, say I did want to implement a generic mailbox pattern so that any task could request a copy from a managing task and send updates to a managing task. Does any one have an example of such a pattern?
Thanks. I appreciate any discussion and opinion on this topic, I'm looking for the most efficient (time and complexity) way to proceed while still being 'safe' in my logic.
M
Tamir - can you explain how a register value might get corrupted during a context switch? Have you ever experienced this? Wouldn't this be a major concern above and beyond data integrity?
Let's say that task1 needs to increment a value of a variable and that the accesses are not atomic. Typically, it will load the value from memory first - let's assume the variable has an initial value 10. A context switch occurs after the load operation and before task1 can decrement the value, allowing task2 to increment the value to 11 without interruption. Task1, having made a copy of the variable before the context switch, decrements the value to 9 and write it to memory. Task2 will then have to deal with what might represent an undefined situation.
Tamir - in your experience do you always synchronize access to any global data in a multi task environment? Wouldn't this bloat quite quickly.
Of course not. In some cases such as when using a circular buffer (producer-consumer design pattern) no synchronization is needed. Pure read access do not require synchronization, of course.
If I'm not mistaken 32bit reads and writes are atomic on Cortex M3 devices.
Yes, but see the example above. Typically, the data addressed needs to be changed in some way which is the source of the trouble.
This is why I'm unclear as to the need to synchronize access if precaution is taken to always copy the value before using the value in each task?
This can save time by reducing overhead, but still requires the usage of synchronization primitives while making the copy to a local variable and when writing back to shared memory.