I have two TASK A and B, where Task A is High priorty and B low priorty. condition and mem are 2 global variable (shared) let's assume that Task B is running and doing some memory operation.
***Task B (Low priority) ***
if (condition) {
.....
for (i = 0; i< 10; i++){
// example we are at i=4
mem[i] = mem[i] +1;
}
.....
}
now while Task B is running (for example we are at index i = 4. ) Task A becomes ready, a context switch will occur. memory will be overwritten and the condition of execution for Task B will be set to false.
*** TASK A (High priority)
......
enter_critical();
condition = false;
mem[i] = 0;
exit_critical();
......
now Task A is finshed and yields resources for Task B to run.
Question :
1- Will the memory operation still take place, eventhough the condition is set to false? (will the condition be checked before reentering Task B)
2- If the memory operation still happens, at which index will it restart( index i= 4 or i=5)?
3- what will mem contains after Task B has finished executing. (i excepct 0 0 0 0 1 1 1 1 1 1)
Yes. The check against
condition
in taskB
has already been carried out long time ago. Furthermorecondition
in itself is probably not thread safe/atomic.It will pick up where it left, which could be in the middle of a C language expression evaluation. It doesn't orderly finish a lap in the C language loop before the context switch.
Some non-deterministic, likely corrupted gibberish with no guarantee of the value at location
mem[i]
. Whateveri
means... because it is not protected either.You have to understand that context switches are very low level. The interrupted task gets to finish whatever assembler instruction it was previously executing. Then the program counter and task
B
stack + condition code variables etc are stored, so that taskB
may resume at the very same assembler instruction it was supposed to execute before the interruption.This is why you have to use synchronizing means like semaphores or critical sections in both processes. All variables that are shared and modified by at least one process are subject to race condition bugs.
Smart programmers will minimize the amount of code placed inside such synchronizing "locks", since it may stall or disrupt other processes.
For example you could do this: