patterncMinor
Peterson's Algorithm (Mutual Exclusion)
Viewed 0 times
exclusionalgorithmmutualpeterson
Problem
A simple algorithm that can be run by two processes to ensure mutual exclusion for one resource.Shared variables are created and initialized before either process starts. The shared variables flag[0] and flag[1] are initialized to FALSE because neither process is yet interested in the critical section. The shared variable turn is set to either 0 or 1 randomly (or it can always be set to say 0)
```
# include
# include
# include
# include
//Shared Global variables to control processes
static int *flag0;
static int *flag1;
static int *turn;
int main(int argc, char const *argv[])
{
flag0 = mmap(NULL, sizeof *flag0, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
flag1 = mmap(NULL, sizeof *flag1, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
turn = mmap(NULL, sizeof *turn, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
*flag0 = 0;
*flag1 = 0;
*turn;
// creates child process
pid_t pid = fork();
//prcess 1 (parent):
if(pid > 0){
//process ready
*flag0 = 1;
// turn selector
*turn = 1;
int counter = 0;
//while to wait for turn change
while (flag1 && turn == 1)
{
// busy wait
printf("Parent waiting: %d sec.\n", counter);
sleep(1);
counter++;
}
// critical section
printf("PARENT: critical section\n");
sleep(5);
// end of critical section
*flag0 = 0;
}
//process 2 (child):
if(pid == 0){
//process ready
*flag1 = 1;
// turn selector
*turn = 0;
//while to wait for turn change
int counter = 0;
while (flag0 == 1 && turn == 0)
{
// busy wait
printf("Child waiting: %d sec.\n", counter);
sleep(1);
counter++;
```
# include
# include
# include
# include
//Shared Global variables to control processes
static int *flag0;
static int *flag1;
static int *turn;
int main(int argc, char const *argv[])
{
flag0 = mmap(NULL, sizeof *flag0, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
flag1 = mmap(NULL, sizeof *flag1, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
turn = mmap(NULL, sizeof *turn, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
*flag0 = 0;
*flag1 = 0;
*turn;
// creates child process
pid_t pid = fork();
//prcess 1 (parent):
if(pid > 0){
//process ready
*flag0 = 1;
// turn selector
*turn = 1;
int counter = 0;
//while to wait for turn change
while (flag1 && turn == 1)
{
// busy wait
printf("Parent waiting: %d sec.\n", counter);
sleep(1);
counter++;
}
// critical section
printf("PARENT: critical section\n");
sleep(5);
// end of critical section
*flag0 = 0;
}
//process 2 (child):
if(pid == 0){
//process ready
*flag1 = 1;
// turn selector
*turn = 0;
//while to wait for turn change
int counter = 0;
while (flag0 == 1 && turn == 0)
{
// busy wait
printf("Child waiting: %d sec.\n", counter);
sleep(1);
counter++;
Solution
Cosmetic issues
This is ok but unusual, don't put a space between the
Those are only used inside
This does nothing. Remove it. Instead, add some code to check that
This isn't consistent, so the reader wonders if there is a semantic difference between the two tests. Better be explicit in both, e.g.:
Also your indentation is out of whack in the child part (and for the global statics), and you have extraneous empty lines in both parts.
The child also runs this. Not really a bug, but a bit suspicious. Move that to parent-only code.
Big issue
You have no synchronization. The reads and writes to shared memory all race. So your program might work by sheer luck, but that's not what you want in a demo for concurrent programming. Peterson's algorithm only works if the reads and writes to the flags and turn variables propagate immediately and atomically, and you have no such guarantee here. In particular, the initial writes to
You'll need to use some form of interprocess synchronization method to achieve correct concurrency control. POSIX named semaphores, or a
# include This is ok but unusual, don't put a space between the
# and include unless you have a good reason to (sometimes used to show some "indentation" with conditional includes).//Shared Global variables to control processesThose are only used inside
main, so no need to make them global. Better would be to separate the two main parts (parent vs child) in two functions, and pass the required data as arguments to those (possibly creating a nice struct to wrap the up).*turn;This does nothing. Remove it. Instead, add some code to check that
mmap didn't fail before you proceed.while (*flag1 && *turn == 1)
while (*flag0 == 1 && *turn == 0)This isn't consistent, so the reader wonders if there is a semantic difference between the two tests. Better be explicit in both, e.g.:
while (*flag1 == 1 && *turn == 1)
while (*flag0 == 1 && *turn == 0)Also your indentation is out of whack in the child part (and for the global statics), and you have extraneous empty lines in both parts.
wait(); // wait for childThe child also runs this. Not really a bug, but a bit suspicious. Move that to parent-only code.
Big issue
You have no synchronization. The reads and writes to shared memory all race. So your program might work by sheer luck, but that's not what you want in a demo for concurrent programming. Peterson's algorithm only works if the reads and writes to the flags and turn variables propagate immediately and atomically, and you have no such guarantee here. In particular, the initial writes to
turn race with each other, and all the reads of flag1 for the parent race with the writes to flag1 in the child (and vice-versa). This doesn't give you that "turn is set to either 0 or 1 randomly", it gives you undefined behavior.You'll need to use some form of interprocess synchronization method to achieve correct concurrency control. POSIX named semaphores, or a
pthread_mutex with the process-shared attribute set, could work (see the POSIX page for pthread_mutexattr_init for an example).Code Snippets
# include <foo.h>//Shared Global variables to control processeswhile (*flag1 && *turn == 1)
while (*flag0 == 1 && *turn == 0)while (*flag1 == 1 && *turn == 1)
while (*flag0 == 1 && *turn == 0)wait(); // wait for childContext
StackExchange Code Review Q#124646, answer score: 6
Revisions (0)
No revisions yet.