2

Here is the two process solution algorithm 1:

turn = 0;
i = 0, j = 1;
do
{
    while (turn != i) ; //if not i's turn , wait indefinitely 
    // critical section

    turn = j; //after i leaves critical section, lets j in

    //remainder section
} while (1); //loop again

I understand that the mutual exclusion is satisfied. Because when P0 is in critical section, P1 waits until it leaves critical section. And after P0 updates turn, P1 enters critical section. I don't understand why progress is not satisfied in this algorithm.

Progress is if there is no process in critical section waiting process should be able to enter into critical section without waiting.

P0 updates turn after leaving critical section so P1 who waits in while loop should be able to enter to critical section. Can you please tell me why there is no progress then?

Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
Figen Güngör
  • 12,169
  • 14
  • 66
  • 108

3 Answers3

3

Forward progress is defined as follows:

If no process is executing in its CS and there exist some processes that wish to enter their CS, then the selection of the process that will enter the CS next cannot be postponed indefinitely.

The code you wrote above does not satisfy this in the case the threads are not balanced, consider the following scenario:

  1. P0 has entered the critical section, finished it, and set the turn to P1.
  2. P1 enters the section, completes it, sets the turn back to P0.
  3. P1 quickly completes the remainder section, and wishes to enter the critical section again. However, P0 still holds the turn.
  4. P0 gets stalled somewhere in its remainder section indefinitely. P1 is starved.

In other words, this algorithm can't support a system where one of the processes runs much faster. It forces the critical section to be owned in equal turns by P0 -> P1 -> P0 -> P1 -> ... For forward progress we would like to allow a scenario where it's owned for example in the following manner P0 -> P1 -> P1 -> .., and continuing with P1 while P0 isn't ready for entering again. Otherwise P1 may be starved.

Petersons' algorithm fixes this by adding flags to indicate when a thread is ready to enter the critical section, on top of the turn-based fairness like you have. This guarantees that no one is stalled by the other thread inefficiency, and that no one can enter multiple times in a row unless the other permits it to.

Leeor
  • 19,260
  • 5
  • 56
  • 87
  • Do you mean P0 didn't assign turn to 1 after it leaves the critical section by that sentence "P0 still holds the turn"? Because in the code, after leaving critical section it assigns j to turn then proceeds the remainder section. Well, while P0 is in remainder section, P1 can enter into critical section because it's its turn according to turn=j assignment. – Figen Güngör Nov 02 '13 at 23:03
  • In #1, the turn is set to P1, in #2 the turn is set back to P0, and it then stays that way even though P1 completed his remainder section (faster than P0 does) and wants to enter again. In other words, the critical section can't be owned in this way: P0 -> P1 -> P1, so if P0 gets stuck in the remainder section, you'll get stuck after P0 -> P1.. – Leeor Nov 03 '13 at 07:22
  • Now, I see the light. Thanks. – Figen Güngör Nov 03 '13 at 08:55
1

You can not be sure about the order in which the code in the two processes is run. When first P1 is run and tries to enter the critical section, it is not allowed to, because it is the turn of P0. So, P1 can not enter the critical section even if there is no other process in it. Therefore progress is not fulfilled.

Sven Painer
  • 194
  • 1
  • 10
  • It would only have to wait until P0 sets the turn back to P1, and would then be free to progress inside. The requirement is only that the entry will not be postponed **indefinitely**. – Leeor Nov 02 '13 at 18:37
  • Yes, you are right. The normal definition of progress would be that no process should be starving because it will never get into the critical section and the other process will always have the possibility to get in. But in the definition in the question it was defined in another way. There it is said that when one process wants to enter the critical section and there is no process inside this critical section, it should be able to enter immediately. Progress in this definition is not fulfilled whereas progress in the other definition is fulfilled. – Sven Painer Nov 02 '13 at 20:44
  • But how do you know when P0 will need to enter critical section? Wouldn't P1 wait indefinitely in that case? – Figen Güngör Nov 03 '13 at 08:57
  • Sorry, but I do not see the point of your question. In my example P1 will wait to enter the critical section, but it is P0's turn to enter it. When P0 tries to enter the critical section it is allowed to, because it is its turn. At the end of the critical section P0 sets turn to 1 and then P1 is able to enter when it is run the next time. Of course, if P0 is never run, P1 could never enter but that should not be the case if scheduling works right. – Sven Painer Nov 03 '13 at 09:23
0

The problem here is that this totally depends on the lower level process scheduling. OS usually takes a bit to wake up a sleeping process, and this is done at a point when the process currently running on the CPU voluntarily gives up control by executing some blocking system call, or out of timer interrupt when time quanta expires. On a full SMP system this also takes some non-trivial in-kernel synchronization and signaling.

This means that process 0 can just loop leaving and entering critical section again without process 1 ever having a chance to run.

Also, I hope you are nor relying on bare integer variables for mutual exclusion. These might be cached in a register by a compiler, and if not, processor caches come into play. This is supposed to be done with special CPU instructions like test-and-set.

Nikolai Fetissov
  • 82,306
  • 11
  • 110
  • 171
  • Well, after P0 leaves critical section, it assigns turn to 1 which means it cannot skip while(turn!=i ); (while(1!=0) holds true so it waits until P1 enters and updates turn value to 0). And because it updated turn value to 1, P1 can skip while(turn!=i); (while(1!=1); condition is false) and after entering and leaving critical section, it will update turn to 0 and P0 can enter now and it goes so on. So P0 cannot loop before P1 enters and updates turn value. – Figen Güngör Nov 02 '13 at 16:42