I was studying binary semaphores when the following question turned up:
Suppose there are 3 concurrent processes and 3 binary semaphores... The semaphores are intitialised as S0=1, S1=0, S2=0. The processes have the following code:
Process P0: Process P1: Process P2:
while (true){ wait(S1); wait(S2);
wait (S0); release (S0); release(S0);
print '0';
release (S1);
release (S2);
}
Now the question is how many times the process will print 0 ?
Let me explain How i was solving it.. suppose the first three statements of the three processes be executed concurrently! i.e, the while statement of process p0, wait(S1) of process p1 and wait(S2) of process P2.. Now, the wait(S1) and wait(S2) will both make the semaphore values -1 and the processes P1 and P2 will be blocked.. Then wait(S0) of Process P0 will be executed. When this happens S0's value becomes 0 and the process P0 moves into blocked state, as a result all the processes will be blocked and in a deadlock state!! But unfortunately thats not the answer. . Please tell me where I am wrong and how the solution proceeds ? :|
EDIT:
I was wrong in my approach to binary semaphores.. they can take only 0 and 1!
Ok .. so here i am answering my own question :P ..
The solution proceeds as below:
Only process P0 can execute first. That's because semaphore used by process P0 i.e S0 has an initial value of 1. Now when P0 calls wait on S0 the value of S0 becomes 0, implying that S0 has been taken by P0. As far as Process P1 and P2 are concerned, when they call wait on S1 and S2 respectively, they can't proceed because the semaphores are already initialized as taken i.e 0, so they have to wait until S1 and S2 are released!
P0 proceeds first and prints 0. Now the next statements release S1 and S2! When S1 is released the wait of process P1 is over as the value of S1 goes up by 1 and is flagged not taken. P1 takes S1 and makes S1 as taken. The same goes with Process P2.
Now, only one of P1 or P2 can execute, because either of them can be in the critical section at a given time.. Suppose P2 executes. It releases S0 and terminates.
Let P1 execute next.. P1 starts Releases S0 and terminates.
Now only P0 can execute because its in a while loop whose condition is set to true, which makes it to run always. P0 executes prints 0 second time and releases S1 and S2. But P1 and P2 have already been terminated so P0 waits forever for the release of S0.
Here's a second solution which prints 0 three times:
P0 starts, prints 0 adn releases S1 and S2.
Let P2 execute. P2 starts, releases S0 and terminates. After this only P0 or P1 can execute.
Let P0 execute. Prints 0 for second time and releases S1 and S2. At this point only P1 can execute.
P1 starts, releases S0, P1 terminates. At this point only P0 can execute because its in a while loop whose condition is set to true!
P0 starts, prints 0 for the 3rd time and releases S1 and S2. It then waits for someone to release S0 which never happens.
So the answer becomes exactly twice or exactly thrice, which can also be said "atleast twice"!
Please tell me if i am wrong anywhere!!
Related
I am trying to solve the philosopher problem by limitating the number of the philosophers who are eating at 4. And in the main function, I code like this to create the threads.
for (i = 0; i < N; i++) {
pthread_create(&tidp[i], NULL, creatPhilosopher, (void *)&i);
}
but here are the output
philosopher 0 is thinking...
philosopher 0 is thinking...
philosopher 0 is thinking...
philosopher 0 is thinking...
philosopher 0 is thinking...
philosopher 0 is eating...
philosopher 0 is eating...
philosopher 0 is eating...
philosopher 0 is eating...
philosopher 0 is eating...
while, I tried another way like this
for (i = 0; i < N; i++) {
int* temp = (int*)malloc(sizeof(int));
*temp = i;
pthread_create(&tidp[i], NULL, creatPhilosopher, (void *)temp);
}
and the output is correct.
philosopher 4 is thinking...
philosopher 3 is thinking...
philosopher 2 is thinking...
philosopher 1 is thinking...
philosopher 0 is thinking...
philosopher 4 is eating...
philosopher 3 is eating...
philosopher 2 is eating...
philosopher 1 is eating...
philosopher 0 is eating...
philosopher 4 is thinking...
philosopher 3 is thinking...
philosopher 2 is thinking...
philosopher 1 is thinking...
So, what's the difference between the two ways?
In the first case you have only one single memory location that is passed to all the different threads: the address of variable i. So all threads will read their number from the same place. What they read from there depends on when they read that value. It seems a bit odd that all read 0, but in any case, this is not what you want.
In the second case you give each thread a different memory location. So each thread reads from a different location and thus a different number.
In the first example, you pass a pointer/reference/handle to the same variable, for every thread. One variable holds one value. You're also not synchronising accesses to that variable (not to mention it could be destroyed before every thread is done trying to read from it), so really all bets are off.
In the second example, each thread gets a copy of i with the correct value, and since the variables are independent objects you also have thread-safety.
You should always be thinking about object lifetime, ownership and access patterns.
The difference is undefined behavior.
for (i = 0; i < N; i++) {
pthread_create(&tidp[i], NULL, creatPhilosopher, (void *)&i);
}
Neither the C++ standard, nor POSIX, whose thread API you are using, gives you any guarantee, whatsoever, that createPhilosopher will start executing and read the value of the pointer that gets passed to it before the for loop's iteration finishes, so that the new thread reads the current value of i. There is no guarantee that createPhilosopher actually starts executing before pthread_create returns in the main execution thread. It may, or may not. It depends on the phase the moon, and the tides.
And by the time the execution threads start executing, it's likely that the entire for loop has finished, and is just a distant memory. It called pthread_create some number of times (but they execution threads have not yet started executing), and, in fact, the i variable is now been destroyed and no longer exists (wherever it was declared), and its memory is now occupied by some other randomly-chosen value, or it's garbage, so by the time the new execution threads read the pointer that they receive as a parameter, it is pointing to garbage.
In the other case you're allocating a single int value in dynamic scope that still exists when the execution threads actually start executing, so they read the value. Nothing frees them, so the pointer are still value. And you leaked memory, but that's another story.
I am busy with pointers at the moment and specifically pointers pointing to different elements in an array when I increment.
When I incremented using ++ everything is fine, but when I incremented using +2 things turned out differently to what I expected.
Let me explain.
In the first instance I set p2 = p1++;. The result I got there was what I expected, ie. p2 gives the value 2 and p1 gives the value 3. This is obviously since the initial value of p1 is assigned to p2 and afterwards p1 is incremented by 1, giving a new value for p1. No problem with that.
However; in the second instance I setp2 = p1+2. The result I got was not what I expected. The result was p1 gives value of 2 and p2 gives value of 4. How can this be? Shouldn't, like in the first instance, the initial value of p1 have been assigned to p2 , and then afterwards p1 incremented by 2 and given a new value of 4?
Then I got thinking a bit. Maybe +2 and ++ have different characteristics. What I mean with this is that when using ++, in this case, the code is saying (in layman's terms): "Make p2 point to the same address as p1 did at the start, and then let p1 point to the address of the next element". But when using +2 the code is saying: "Go to the element two "blocks" down from p1 and let p2 point to the address of that specific element; BUT DON'T CHANGE THE ADDRESS p1 IS POINTING TO WHILE DOING SO!". And this is what I mean with "they show different characteristics". They don't act in the same manner.
Is my assumption correct?
Also, how do you increment by two(or three or four, etc.) in this instance whilst maintaining the same characteristics as the ++ operator?
Here are some links to sites I researched which dealt with increments. But none of them really address my problem properly. Nor do any other sites. Also, most of them suggest using something like a +=2 to increment by two, which is fine, but that also does not tackle my specific problem.
Link1
Link2 SO
Could you please explain in the simplest terms possible since I am still new to C++.
Instance One
#include <iostream>
int main()
{
int a[5] = {1,2,3,4,5};
int *p1, *p2;
p1 = &a[1];
p2 = p1++;
std::cout << "Value1: " << *p1 << "\n" << "Value2: " << *p2;
return 0;
}
Output result of instance one (What I expected)
Value1: 3
Value2: 2
Instance Two
#include <iostream>
int main()
{
int a[5] = {1,2,3,4,5};
int *p1, *p2;
p1 = &a[1];
p2 = p1+2;
std::cout << "Value1: " << *p1 << "\n" << "Value2: " << *p2;
return 0;
}
Output result of instance two (NOT what I expected)
Value1: 2
Value2: 4
p2 = p1+2; does not modify the value of p1. It just assigns the result of p1+2 to p2.
p2 = p1++; does modify the value of p1. It first assigns p1 to p2, then increments p1 by one.
The output is exactly what is expected. When you perform this assignment:
p2 = p1 + 2;
You just ask to assign the value p1 + 2 to p2, that's it. There is no reason for p1 being updated. You seem to confuse the + operator with the post-increment/pre-increment ++ operator.
A little reminder might help.
I have been asked to describe what these lines of code are doing for a college assignment
int main() {
int t1[] = {0,0,1,1,1}, t2[] = {0,0,1,1,1};
int *p1 = t1, *p2 = t2;
while (!*p1++ || !*p2++);
cout << (p1-t1) << endl;
cout << (p2-t2) << endl;
}
My take on it is, 2 arrays of type int are created and filled with values, 2 pointers are created and pointed at each array, then I start to have trouble.
while (!*p1++ || !*p2++);
To me this is saying while 0 move the position of *p1one place or while 0 move the position of *p2 one place, I'm really not confident in that assumption?
cout << (p1-t1) << endl;
So then we move onto the cout, now my take on this is, I'm subtracting the position of p1 from the position of t1, where p1 was positioned by the while and t1 points to the first position in the array.
again I could be completely wrong I'm only learning about pointers so please bear this in mind if I'm wrong in my assumptions.
The while loop is actually quite horrid. I've never seen code like this in real life, and would declare any programmer doing it in real life as mad. We need to go through this step by step:
while (condition);
We have here a while statement with an empty statement (the ";" alone is an empty statement). The condition is evaluated, and if it is true, then the statement is executed (which does nothing because it is an empty statement) and we start all over again. In other words, the condition is evaluated repeatedly until it is false.
condition1 || condition2
This is an "or" statement. The first condition is evaluated. If it is true, then the second condition is not evaluated and the result is "true". If it is false, then the second condition is evaluated, and the result is "true" or "false" accordingly.
while (condition1 || condition2);
This evaluates the first condition. If it's true we start all over. If it is false, we evaluate the second condition. If that is true, we start all over. If both are false, we exit the loop. Note that the second condition is only evaluated if the first one is false. Now we look at the conditions:
!*p1++
!*p2++
This is the same as *(p1++) == 0 and *(p2++) == 0. Each condition increases p1 or p2 after it has been evaluated, no matter what the outcome. Each condition is true if *p1 or *p2 was zero and false otherwise. Now we check what happens at each iteration:
p1 = &t1 [0], p2 = &t2 [0]
*p1++ == 0 is true, *p2++ == 0 is never evaluated, p1 = &t1 [1], p2 = &t2 [0].
*p1++ == 0 is true, *p2++ == 0 is never evaluated, p1 = &t1 [2], p2 = &t2 [0].
*p1++ == 0 is false, *p2++ == 0 is true, p1 = &t1 [3], p2 = &t2 [1].
*p1++ == 0 is false, *p2++ == 0 is true, p1 = &t1 [4], p2 = &t2 [2].
*p1++ == 0 is false, *p2++ == 0 is false, p1 = &t1 [5], p2 = &t2 [3].
t1 is the same as &t1 [0]. p1 - t1 == &t1 [5] - &t1 [0] == 5.
t2 is the same as &t2 [0]. p2 - t2 == &t2 [3] - &t2 [0] == 3.
You are correct in you assessment of t1, t2, p1, and p2.
while (!*p1++ || !*p2++);
I don't like this coding style, as it is easy to assume the programmer placed the semi-colon there by mistake. To indicate that an empty body is truly intended, the empty body should be distinguished in some way (like with a comment, placed on a separate line, or use curly braces instead).
The while enters the body so long as the condition is true. Since this is a logical-or expression, both !*p1++ and !*p2++ must be false before the while loop terminates. This happens when both *p1++ and *p2++ become non-zero. Because logical-or short circuits (the second expression is not evaluated if the first one is true), the progression of the p1 and p2 take on the following at the start of each iteration:
iter p1 *p1 p2 *p2 condition
---- -- --- -- --- ---------
0 &t1[0] 0 &t2[0] 0 !*p1++ is true, !*p2++ not evaluated
1 &t1[1] 0 &t2[0] 0 !*p1++ is true, !*p2++ not evaluated
2 &t1[2] 1 &t2[0] 0 !*p1++ is false, !*p2++ is true
3 &t1[3] 1 &t2[1] 0 !*p1++ is false, !*p2++ is true
4 &t1[4] 1 &t2[2] 1 !*p1++ is false, !*p2++ is false
Since each iteration uses post-increment, p1 ends with the value &t1[5], and p2 ends with the value &t2[3].
Pointer subtraction within the same array measures the distance between the two pointers in terms of number of array elements. An array name used in most expressions will decay to the value equal to the pointer to its first element. So t1 decays to &t1[0], and t2 decays to &t2[0].
Thus:
p1 - t1 => 5
p2 - t2 => 3
The key thing to note here is how the expression (a || b) is evaluated. First, the expression a is evaluated. If a returns true, b is not evaluated since OR of anything with True is True. This is called short-circuiting.
It helps to augment the code in the following manner -
int main(void){
int t1[] = {0,0,1,1,1}, t2[] = {0,0,1,1,1};
int *p1 = t1, *p2 = t2;
cout << *p1 << " " << *p2 << endl;
cout << p1 << " " << p2 << endl;
while (!*p1++ || !*p2++) {
cout << *p1 << " " << *p2 << endl;
cout << p1 << " " << p2 << endl;
}
cout << (p1-t1) << endl;
cout << (p2-t2) << endl;
return 0;
}
Output:
0 0
0x7fff550709d0 0x7fff550709f0
0 0
0x7fff550709d4 0x7fff550709f0
1 0
0x7fff550709d8 0x7fff550709f0
1 0
0x7fff550709dc 0x7fff550709f4
1 1
0x7fff550709e0 0x7fff550709f8
5 // Final p1 - t1
3 // Final p2 - t2
!*p1++ is equivalent to (!(*(p1++)). This is the post-increment operator. It increments the pointer but returns the old value (before the increment).
The expression in the loop is evaluated 5 times.
In the first iteration, p1 is incremented. Since the current value of *p1 (before incrementing) is 0, a ! of 0 returns 1. Due to short-circuiting, the rest of the expression is not evaluated. Thus only p1 gets incremented.
Same thing happens in the next loop.
Now, we have p1 = t1 + 2 indices, and p2 = t2.
In the third iteration, current value of *p1 is no longer 0. Thus both p1 and p2 are incremented.
Same thing happens in the fourth iteration.
Note that in the first four iterations, either p1 or p2 points to a 0 - so the not of either the left side or the right side is True and hence the while loop continues.
In the fifth iteration, both p1 and p2 are incremented, but since neither points to a 0 value, the loop exits.
Thus p1 is incremented 5 times, and p2 is incremented 3 times.
Summarizing - p1 - t1 will contain 1 + the number of 0s appearing continuously in the beginning of t1 and t2 (2 + 2 + 1). p2 - t2 will evaluate to 1 + number of 0s appearing continuously in the beginning of t2 (2 + 1).
First:
while (!*p1++ || !*p2++);
That means while the contents of p1 is 0 keep looping adding 1 to p1 each time until it becomes non-zero. Thereafter while the contents of p2 is 0 keep looping adding 1 to both p1 and p2 each time. If at any time the content of p1 become 0 again the logic repeats (I know this is confusing).
Basically in a while(first || second) style test the second part is only tested if the first part fails. And the pointer gets incremented regardless if the test passes or fails.
Your assumption about (p1-t1) is correct. That calculation gives you the number of integers between t1 and p1 (because they are int pointers). Because t1 is the beginning of the array the calculation actually gives you the index (offset) into the array that p1 is pointing at.
NOTE #1: If p1 and t1 were char pointers then subtracting them would give you the number of characters between them. If they were float pointers then subtracting them would give you the number of floats etc... Pointer arithmetic adds and subtracts in units of the data type they are pointing to.
NOTE #2: Strictly speaking t1 is an array type. It collapses to a pointer when you use it in a pointer context. For example in pointer arithmetic or when you assign it to a pointer variable. If that confuses you, don't worry, mostly it just works as a pointer because the compiler makes the conversion automatically whenever it is implied by the context.
As far as question is what would this print on console , answer is 0 0 before you removes ; at the end of while loop.
What's the significance of this loop?
First you are using OR that means if either value pointed to by p1 or p2 is 0 block would be executed. So, till p1 points to 3rd element (p1-t1) will give you number of elements crossed in t1 while (p2-t2) will be 0 as (p1-t1) will return true so second condition will not be checked. When p1 points to 1 then it will start incrementing p2 till it points to 3rd element of t2 and there's the end.
This is all this assignment has for you I believe.
This relation can help you better understand the conditions within the while loop:
arr[ i ] == * ( arr + i )
When doing pointer subtraction (if pointers are of the same type), the result is the distance (in array elements) between the two elements.
Assume that p1 and p2 are both pointers of type T*. Then, the value computed is:
( p2 - p1 ) == ( addr( p2 ) - addr( p1 ) ) / sizeof( T )
Consider following example:
-Thread 1-
y.store (20, memory_order_relaxed);
x.store (10, memory_order_release);
-Thread 2-
if (x.load(memory_order_acquire) == 10) {
assert (y.load(memory_order_relaxed) == 20)
y.store (10, memory_order_release)
}
-Thread 3-
if (y.load(memory_order_acquire) == 10)
assert (x.load(memory_order_relaxed) == 10)
In this example second assert will fire(am i correct?). is it because there is no store to x in thread 2 before y.store (10, memory_order_release)?
(in cppreference.com they say this sentence about release: "A store operation with this memory order performs the release operation: prior writes to other memory locations become visible to the threads that do a consume or an acquire on the same location.")
Can i change the order of store to y in thread2 from release to sec/cst to solve the problem?
Your example isn't complete because you haven't specified initial values for x & y. But let's assume that the thread that starts all threads has initialized both to 0.
Then if thread 2 does a store to y, it must have read from thread 1's store to x and synchronized with it. If thread 3's load from y reads thread 2's store to y, it must synchronize also. Therefore, the store to x in thread 1 must happen before the load in thread 3 and it must happen after the initialization store to x. Thus thread 3's x.load must get the value of 10. Happens before in the absence of consume is transitive.
I suggest using CDSChecker on these examples to see what values are possible.
The following program consists of 3 concurrent processes and 3 binary semaphores The
semaphore, are initialized as S0=1 S1=0 S2=0
Process P0:
while(1)
{
wait (S0);
print '0';
release (S1);
release (S2);
}
Process P1:
wait(S1);
release (S0);
Process P2:
wait(S2);
release (S0);
How many times will process PO print '0"??
(A) At least twice (b) Exactly tWlce (c) Exactly thrice (d) Exactly once
in this I have a confusion that Process P1 and P2 as will execute once or they will continue after executing once as they are not having while loop like process P0, if they will execute once only then According to me the answer should be (b), and if they will execute again then the answer will be (A)
please help thanks in advance
Initially P0 will execute because only S0=1. It will print single 0.
Now when S1 and S2 are releases by P0 then any one of them can be executed.
Let us suppose P1 executes and releases S0(Now value of S0 is 1).
Now there are two possibilities either P0 or P2 can execute.
Let us take P2 executes and releases S0, so at the end P0 execute and print 0 (means two 0's)
but if P0 executes before P2 then total of 3 0's will print(one at the time of P0 and then P2 which releases S0 so P0 executes again).
So the perfect answer is at least two 0's.
The solution proceeds as below:
Only process P0 can execute first. That's because semaphore used by process P0 i.e S0 has an initial value of 1. Now when P0 calls wait on S0 the value of S0 becomes 0, implying that S0 has been taken by P0. As far as Process P1 and P2 are concerned, when they call wait on S1 and S2 respectively, they can't proceed because the semaphores are already initialized as taken i.e 0, so they have to wait until S1 and S2 are released!
P0 proceeds first and prints 0. Now the next statements release S1 and S2! When S1 is released the wait of process P1 is over as the value of S1 goes up by 1 and is flagged not taken. P1 takes S1 and makes S1 as taken. The same goes with Process P2.
Now, only one of P1 or P2 can execute, because either of them can be in the critical section at a given time.. Suppose P2 executes. It releases S0 and terminates.
Let P1 execute next.. P1 starts Releases S0 and terminates.
Now only P0 can execute because its in a while loop whose condition is set to true, which makes it to run always. P0 executes prints 0 second time and releases S1 and S2. But P1 and P2 have already been terminated so P0 waits forever for the release of S0.
Here's a second solution which prints 0 three times:
P0 starts, prints 0 adn releases S1 and S2.
Let P2 execute. P2 starts, releases S0 and terminates. After this only P0 or P1 can execute.
Let P0 execute. Prints 0 for second time and releases S1 and S2. At this point only P1 can execute.
P1 starts, releases S0, P1 terminates. At this point only P0 can execute because its in a while loop whose condition is set to true!
P0 starts, prints 0 for the 3rd time and releases S1 and S2. It then waits for someone to release S0 which never happens.
So the answer becomes exactly twice or exactly thrice, which can also be said "atleast twice"!
Please tell me if i am wrong anywhere!!
For more problems on semaphore, refer this
I'm assuming wait() decrements the semaphore and blocks if it becomes <= 0, whereas release increases the counter and wakes up the next process.
Given your code, P1 and P2 execute once (there is no loop around them). This means each of them triggers S0 once. And as P0 blocks waiting on S0 before every print, it will finally print '0' twice.
One more thing to check is the initial state of S0, because P0 will only block if S0 is 0. This is the case given your statement. Therefore, the answer is that P0 will print 0 exactly twice.
Reading the question and the code I would also say (A). I am assuming that the processes cannot be preempted before completing their task.
It says the initial state is S0=1 S1=0 S2=0, and from what we know P1 and P2 will execute exactly once.
Concurrent processes can be complex and however I try to describe the flow people will find faults with the way I think about it, that is ok, I'm here to learn too.
Now you have a few situations yielding different results depending on order of processes.
P0 -> P1 -> P0 -> P2 -> P0 = Three times
P0 -> P1 -> P2 -> P0 = Twice
P0 -> P2 -> P1 -> P0 = Twice
This gives us the answer of at least twice.
Edit:
All this is made under the assumption of wait() blocking while semaphore == 0 and that release() sets semaphore = 1 because otherwise the code would just mostly be insanity.
If the processes can be interrupted at any time, then things can get interesting.
P0 starts out running because S0=1 at start
P0 print '0';
P0 release(S1);
-- here S1 may take over or not --
P0 release(S2);
-- here S2 may take over or not --
P0 goes back to wait(S0)
-- here P0 continues or if S1 *and* S2 have not run blocks --
-- it may also be that only S1 or S2 ran and now the other will run --
Now I tried figuring out a way to visualize how things would work out, and I failed to find a way good to put it in the code block.
If both S1 and S2 runs as soon as they can, since the semaphores are binary and can be in only one of two states, P0 will only be run twice, however if scheduling is perverse enough to delay either S1 or S2 until P0 has passed wait() once more P0 will run three times.
But I think this question was not meant to have interruptable processes, it just gets messy.
P0 will execute first because only S0=1. Hence it will print 0 (for the first time). Also P0 releases S1 and S2. Since S1=1 and S2=1, therefore P1 or P2, any one of them can be executed.
Let us assume that P1 executes and releases S0 (Now value of S0 = 1). Note that P1 process is completed.
Now S0=1 and S2=1, hence either P0 can execute or P2 can execute. Let us check both the conditions:-
Let us assume that P2 executes, and releases S0 and completes its execution. Now P0 executes; S0=0 and prints 0 (i.e. second 0). And then releases S1 and S2. But note that P1 and P2 processes has already finished their execution. Again if P0 tries to execute it goes into sleep condition because S0=0. Therefore, minimum number of times '0' gets printed is 2.
Now, let us assume that P0 executes. Hence S0=0, (due to wait(S0)), and it will print 0 (second 0) and releases S1 and S2. Now only P2 can execute, because P1 has already completed its execution and P0 cannot execute because S0 = 0. Now P2 executes and releases S0 (i.e. S0=1) and finishes its execution. Now P0 starts its execution and again prints 0 (thrid 0) and releases S1 and S2 (Note that now S0=0). P1 and P2 has already completed its execution therefore again P1 takes its turn, but since S0=0, it goes into sleep condition. And the processes P1 and P2 which could wakeup P0 has already finished their execution.Therefore, maximum number of times '0' gets printed is 2.
Reference: http://www.btechonline.org/2013/01/gate-questions-os-synchronization.html
Initially only P0 can go inside the while loop as S0 = 1, S1 = 0, S2 = 0. P0 first prints '0' then, after releasing S1 and S2, either P1 or P2 will execute and release S0. So 0 is printed again.