Open In App

N process Peterson algorithm

Last Updated : 22 Nov, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

In any operating system, it is important to control how different processes run at the same time. When multiple processes are working, we have to control which process can change important information such as the variables in a program at that moment. This makes it possible to get errors or unexpected results in case it has not been done.

Such interference can be prevented by certain techniques, and one of the techniques is Peterson’s Algorithm. Another very familiar example of the critical section problem is the Producer-Consumer problem. If the processes do not properly synchronize, then it may result in something undesirable like a wrong count of items in the buffer. It prevents these problems by Peterson’s algorithm by controlling the access of various critical sections to different processes.

Description

Peterson’s solution is a software-based solution to race conditions or critical-section problems. It is usually not implemented in modern computers, but this solution provides a basic algorithmic way to solve the critical section problem. We will mainly consider the Producer-Consumer problem throughout this article. At first, this algorithm was presented easily where there was an aim to establish synchronization between only 2 processes. So it can be further expanded to consider synchronization among N processes by making a small change to it.

Peterson’s Solution to 2 Processes

Let’s consider 2 processes working parallel in an operating system. These processes modify the same variables, hence they both have a risk of entering a race condition. We consider that each process has a remainder section where they are not modifying such variables which can lead to race conditions and another section named a critical section where the processes may have a chance to enter the race condition. So a basic Peterson Algorithm for such cases is given below.

Step-1: Let’s consider the two processes being named P0 and P1. So we can switch between these two processes using a simple formula i.e. 1-<base of process>. To change the pointer to P0 from P1, it should be changed by the formula as idx = 1-1 (base of P1) = 0. Hence, in this way at any time idx will be either pointing to P1 or P0

Step-2: This algorithm requires two data items to be shared between processes.

int turn;

This variable indicates whose turn is it to execute the critical section part of its program. If turn == 1, then it’s the turn for P1 to enter the critical section area.

boolean flag[2];

This array indicates that if a process is ready to enter its critical section or not. flag[0]==true means P0 is ready to execute its critical section part of the program.

Step-3: The main part of this algorithm is given below. The process if want to enter the critical section part of the program then they have to perform two things as follows.

  1.  Set the flag[idx] = true. If P1 want to enter than it should set flag[1]=true.
  2. Set turn = 1-idx,i.e. if P1 wants to enter then it should set turn in terms of another process since it implies that if another process wishes to enter the critical section part can do so after P1 has executed its part.

Step-4 :  The algorithm is presented as follows. Any process is inhibited to enter the critical section of the program till both of the following things happens.

1) if flag[1-idx]==true
2) if turn == 1-idx.

Now till both the above conditions are true the process waits in a while loop doing nothing and if any of the condition becomes non-true process enter the critical section and the next process (i.e. 1-idx) is waiting in the loop to execute the critical section part if wanted. This also guarantees that no two processes are executing the critical section part at the same time.

Pseudo-Code:

Hence, the Pseudo-Code of the algorithm can be given as follows.

idx=0;

do{

// preparing to enter the critical section part
flag[idx] = TRUE;
turn = 1-idx;

while(flag[1-idx]==TRUE and turn == 1-idx)
// checking the two variables continuously. This is a waste of time.
;
// continues in the loop till chance cames

/*
Critical section part
*/

flag[idx] = FALSE;

/*
Remainder section part
*/
}

Hence, in this way, there exists synchronization between two processes. The above algorithm guarantees that there always exists mutual exclusion and synchronization between the two processes.

Peterson’s algorithm for N-Process

This algorithm assumes the same data structure as discussed above. The only modification it has is that it is using an N size array and variable turn can have values from 0 to N-1. There is also a very large change in this algorithm since in the above algorithm in the while condition we are continuously referring to the turn variable to contain the complementary process’s number. But in this algorithm, it is not the case because there are more than 2 Processes.

Implementation

The idea to implement the above algorithm is given below.

Step-1 : Let’s consider a queue of size N for N processes to be placed in it. Now suppose we write an algorithm as Each process pushes itself in the queue to come at the end of the queue at some time, and then they will be allowed to execute their critical section and leave the queue. In this way, we can guarantee that each process is allowed to execute their critical section once they enter the queue and reaches to its end (front). Till the process reaches the front it should have to wait since there can be two conditions happening at that moment.

  • Either some processes might be at the next index in the queue and are waiting for someone else.
  • Or if any back process (which enters the queue late) doesn’t move to the current process’s location. (This means that the back process checks that the front is emptied and wants to push the queue forwards.)

The first case is straight clear, but there is a trick (or we can say an idea) inside the second one. You will get it clear after reading 2nd point.

Step-2 :  The data structure for the algorithm is the same as for 2 processes one, but now the Turn becomes an array of size N, and also the Flag is the array of size N.

Flag[PID] 
// has size N and PID always ranges from 0---N-1 since there are N processes.

To indicate the position at which the PIDth process is in the queue.

Turn[i] = PID // has size N
  • To mark that till now no process says that it is at position i (since if any process says like that then it means that there is a back push from later processes and hence the current process should change its position).
  • Back-Push happens since some process which enters late in the queue should be given place to enter and so there exists a push for rest process to the front of the queue. Back-push arises since the system works in a multiprocessor environment, concurrently executing processes.
  • Also, slowly the size of the queue may decrease since some processes after executing their critical section may be terminated or leave the queue or enter another one for another critical section.

Hence, the pseudo-code for N process Peterson’s algorithm is explained below.

  • We will make two functions named lock() and unlock(). In the lock() function the process waits till it reaches the end of the queue and in unlock() function it marks the exit from the queue.
  • The execution of the critical section takes place when the process is at the end of the queue i.e. between the lock and unlock methods.
  • The two methods are described below as follows.
LOCK( Process PID){
for( int i = 0;i<N;++i){
//Looping through position from 0 to end (N) of queue.

Turn[i]=PID;
// Tells that PID process is at ith position.

Flag[PID]=i;
// Tells that till now there is no back push

while((for all k != PID, Flag[k]<i) or (Turn[i] != PID))
;
//Wait till either there is no process
//at the top of queue or there is a back push.
}
}
UNLOCK(Process PID) {
if (/* condition where process exits or terminates */) {
Flag[PID] = -1; // Process exists or terminates, or moves to another queue
}
else {
Flag[PID] = 0; // Process enters the first position in the queue
}
}

Hence, the Pseudo-Code for the above algorithm is given below.

LOCK( Process PID){
for( int i = 0;i<N;++i){
Turn[i]=PID;
Flag[PID]=i;
while((for all k != PID, Flag[k]<i) or (Turn[i] != PID))
;
}
}
/* Critical Section */
UNLOCK(Process PID) {
if (/* condition where process exits or terminates */) {
Flag[PID] = -1;
// Process exists or terminates, or moves to another queue
}
else {
Flag[PID] = 0;
// Process enters the first position in the queue
}
}

Conclusion

It can be clearly seen that the above algorithm obeys all the rules to be satisfied for synchronized and concurrent processes in any multi-Processor environment. Hence, we are able to get knowledge about how Peterson’s algorithm works for N-Processes.



Next Article
Article Tags :

Similar Reads