How can context switch affect the modification of a variable? - multithreading

float myTotalAmount=0;
void update(float amt){
myTotalAmount+= amt;
}
task A call update(10);
task B call update(5);
How can race condition affect the result of myTotalAmount ?
Task B is able to call update method because context switch happened due to some reason before Task A finished ?
Over all i am trying to understand race condition.

int myTotalAmount = 0
Task A
Updata(10);
Task B
Updata(5)
myTotalAmount+= amt; is not an atomic operation. In the sense that this line will be translated to multiple machine commands.
That being said, Task A will save the value of myTotalAmount in a register, that value will be 0. If a context switch happends now and Task B starts running, it will modify myTotalAmount to be 5. Now the OS decides to run Task A again.
Even though the value of myTotalAmount is now 5, we've already extracted the value and saved it in a register and it was 0. The execution of will continue from that point where myTotalAmount was 0. Now myTotalAmount will get assigned 0+10 and it will be 10 instead of 15.
To fix this, you can deploy some synchronization to prevent race condition. You can use lock.

Related

Handling Multiple wait operation before entering into critical section in operating system?

I am stuck while solving a counting semaphore problem in Operating system subject.
S is a semaphore initialized to 5.
count = 0 (shared variable)
Assume that the increment operation in line #7 is not atomic.
Now,
1. int counter = 0;
2. Semaphore S = init(5);
3. void parop(void)
4. {
5. wait(S);
6. wait(S);
7. counter++;
8. signal(S);
9. signal(S);
10. }
If five threads execute the function parop concurrently, which of the following program behavior(s) is/are possible?
A. The value of counter is 5 after all the threads successfully complete the execution of parop
B. The value of counter is 1 after all the threads successfully complete the execution of parop
C. The value of counter is 0 after all the threads successfully complete the execution of parop
D. There is a deadlock involving all the threads
what i have understand till now is answer is A and D,because what if all process are executed one by one say(T1->T2->T3->T4->T5) and final value saved will be 5(so A is one of correct options)
Now, why D,because what if all process execute line 5 before 6 and will get blocked.
Now, please can any one help me to understand why B is another correct answer. ?
Thanks in advance,
Hope to here from you soon
Any help will be highly appreciated.
Imagine thread 1 gets to line 7 before any other thread, and line 7 is implemented as three instructions:
7_1: load counter, %r0
7_2: add $1, %r0
7_3: store %r0, counter
For some reason (eg. interrupt, preempted), thread 1 stops at instruction 7_2; so it has loaded the value 0 into register %r0.
Next, thread's 2..5 all run through this sequence, leaving counter at say 4.
Thread 1 is rescheduled, increments %r0 to the value 1 and stores it into counter.

Atomic instructions in semaphores

I am confused what it means for semaphores to be atomic. The definition of wait and signal is below.
wait(S){
while ( S<= 0)
; // Busy wait
S--;
}
signal(S) {
S++;
}
The book says
all modifications to the integer value of the sophomore in the wait()
and signal() operations must be executed atomically. That is, when one
process modifies the semaphore value, no other process can
simultaneously modify the same semaphore value
Does this mean that no other instructions can execute in-between while(S<=0) and S--? and at what point is the process done modifying the semaphore value? is this when it finally decrements S--?
Does this mean that no other instructions can execute in-between while(S<=0) and S--?
No. It means all modifications (such as S--) must be done atomically, that is, no other process can simultaneously attempt to modify S, for example, by executing the S++ in signal.
At what point is the process done modifying the semaphore value? is this when it finally decrements S--?
Each modification must be atomic, as the explanation says. So it's done modifying the value at the end of each modification. It may modify it again, but that would be a distinct modification that must also be atomic.
You can think of an "atomic modification" as one that does not overlap any other atomic access or modification. Were S++ and S-- not atomic, an operation could get lost if, for example, two processes execute S++ and their operations overlap. They could both read S, both increment S, then both write S, resulting in S only getting incremented once.
What it means for any operation to be atomic is: Either it happens or it doesn't. If some thread A performs an atomic operation on some collection of data or on some object, and thread B examines the object/data, then thread B must either see the object/data as it was before the operation started or, as it was after the operation finished. "Atomic" means that it's impossible for thread B to see the object/data in a half-way done state.
We can provide atomicity by using synchronized blocks or ReentrantLock objects when accessing data, but if somebody tells you that some object is atomic, then what they are saying is, all of the operations that you can perform on it* are automatically guaranteed to be atomic, without you having to explicitly lock anything.
* Except maybe for special cases, called out in the object's documentation.

How does thread context-switching work with global variable?

I have been confused at this question:
I have C++ function:
void withdraw(int x) {
balance = balance - x;
}
balance is a global integer variable, which equals to 100 at the start.
We run the above function with two different thread: thread A and thread B. Thread A run withdraw(50) and thread B run withdraw(30).
Assuming we don't protect balance, what is the final result of balance after running those threads in following sequences?
A1->A2->A3->B1->B2->B3
B1->B2->B3->A1->A2->A3
A1->A2->B1->B2->B3->A3
B1->B2->A1->A2->A3->B3
Explanation:
A1 means OS execute the first line of function withdraw in thread A, A2 means OS execute the second line of function withdraw in thread A, B3 means OS execute the third line of function withdraw in thread B, and so on.
The sequence is how OS schedule thread A & B presumably.
My answer is
20
20
50 (Before context switch, OS saves balance. After context switch, OS restore balance to 50)
70 (Similar to above)
But my friend disagrees, he said that balance was a global variable. Thus it is not saved in stack, so it does not affected by context switching. He claimed that all 4 sequences result in 20.
So who is right? I can't find fault in his logic.
(We assume we have one processor that can only execute one thread at a time)
Consider this line:
balance = balance - x;
Thread A reads balance. It is 100. Now, thread A subtracts 50 and ... oops
Thread B reads balance. It is 100. Now, thread B subtracts 30 and updates the variable, which is now 70.
...thread A continues now updates the variable, which is now 50. You've just lost the work that Thread B.
Threads don't execute "lines of code" -- they execute machine instructions. It does not matter if a global variable is affected by context switching. What matters is when the variable is read, and when it is written, by each thread, because the value is "taken off the shelf" and modified, then "put back". Once the first thread has read the global variable and is working with the value "somewhere in space", the second thread must not read the global variable until the first thread has written the updated value.
Unless the threading standard you are using specifies, then there's no way to know. Most typical threading standards don't, so typically there's no way to know.
Your answer sounds like nonsense though. The OS has no idea what balance is nor any way to do anything to it around a context switch. Also, threads can run at the same time without context switches.
Your friend's answer also sounds like nonsense. How does he know that it won't be cached in a register by the compiler and thus some of the modifications will stomp on previous ones?
But the point is, both of you are just guessing about what might happen to happen. If you want to answer this usefully, you have to talk about what is guaranteed to happen.
Clearly homework, but saved by doing actual work before asking.
First, forget about context switching. Context switching is totally irrelevant to the problem. Assume that you have multiple processors, each executing one thread, and each progressing at an unknown speed, stopping and starting at unpredictable times. Even better, assume that this stopping and storing is controlled by an enemy, who will try to break your program.
And because context switching is irrelevant, the OS will not save or restore anything. It won't touch the variable balance. Only your two threads will.
Your friend is absolutely, totally wrong. It's quite the opposite. Since balance is a global variable, both threads can read and write it. But you don't only have the problem that they might read and write it in unknown order, as you examined, it is worse. They could access it at the same time, and if one thread modifies data while another reads it, you have a race condition and anything at all could happen. Not only could you get any result, your program could also crash.
If balance was a local variable saved on the stack, then both threads would have each its own variable, and nothing bad would happen.
Consider this line:
balance = balance - x;
Thread A reads balance. It is 100. Now, thread A subtracts 50 and ... oops
Thread B reads balance. It is 100. Now, thread B subtracts 30 and updates the variable, which is now 70.
...thread A continues and updates the variable, which is now 50. You've just completely lost the work of Thread B.
Threads don't execute "lines of code" -- they execute machine instructions. It does not matter if a global variable is affected by context switching. What matters is when the variable is read, and when it is written, by each thread, because the value is "taken off the shelf" and modified, then "put back". Once the first thread has read the global variable and is working with the value "somewhere in space", the second thread cannot read the global variable until the first thread has written the updated value.
Simple and short answer for c++: Unsynchronized access to a shared variable is undefined behavior, so anything can happen. The value can e.g. be 100,70,50,20,42 or -458995. The program could crash or not. And in theory its even allowed to order pizza.
The actual machine code that is executed is usually far away from what your program looks like and in the case of undefined behavior, you are no longer guaranteed, that the actual behavior has anything to do with the c++ code you have written.

Semaphore value greater than initialized value

I am working on semaphores in Linux. I would like to know if the semaphore value can ever be incremented beyond the initialized value? If so, when can that happen?
For example, semaphore value is initialized to 1.
If I increment twice continuously using up(sem), will the value of semaphore increment beyond 1.
x(void){
sema_init(sem1, 1);
down(sem1);
{
.
. // some code implementation
.
}
up(sem1); // i understand this increment the value back to 1.
up(sem1);
/* what exactly does this statement do to the semaphore?
Will it increment the value to 2? If so what is the meaning of this statement? */
}
Yes it will increment it to 2. The effect is that the next two semaphore down calls will run without blocking. The general use case of semaphores is to protect a pool of resources. If there is 1 resource then the max expected value of the semaphore will be 1. If there are 2 resources then max expected value is 2 and so on. So whether incrementing the semaphore to 2 is correct or not depends upon the context. If only 1 process should get past the semaphore at any given time then incrementing to 2 is a bug in the code. If 2 or more processes are allowed then incrementing to 2 is allowable.
This is a simplified explanation. For more details look up "counting semaphores". The other type of semaphore which you may be thinking of is "binary semaphores" which are either 0 or 1.

changing control variable in Case statement in VHDL

case task is
when 1 => task <= 2;
when 2 => task <= 3;
when other =>...
end case
I try to change the switch variable inside the case but it does not effect the value after case clause is passed. What is the proper way to do it?
Since you use a signal assignment <= I assume that task is a signal, not a variable. The new value of task will be available in the next simulation cycle (delta cycle). This usually means that the new value will be visible when the process is executed again, or after a "wait" statement (but you probably don't want wait statements if you are going to synthesize the code).
As an alternative, you can use a variable for task, and use the variable assignment operator: task := 2;
Use a variable, not a signal - this will update the way you expect.
Signals are useful for communication between multiple processes, as their updates are well-controlled. Ordinary variables are not and are therefore limited to process-scope, so can't be inadvertently used for inter-process communication which would then be error-prone.

Resources