Created
September 26, 2015 13:09
-
-
Save vik-y/d9a2693f711b585a0093 to your computer and use it in GitHub Desktop.
Producer Consumer Problem Implementation using lock and turn variables
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* pc-lock.c | |
* | |
* Created on: Sep 24, 2015 | |
* Author: Vikas Yadav (IMT2013060) | |
* Producer Consumer Problem using lock variables | |
* | |
* NOTE: | |
* | |
* This solution works most of the time properly. | |
* Even when the Consumer Process is done executing | |
* Producer keeps producing till the buffer is full. | |
* Their can be a case of deadlock. Reason explained | |
* in the report | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/types.h> | |
#include <sys/ipc.h> | |
#include <sys/shm.h> | |
#define BUFFERSIZE 1000 | |
#define PRODUCER 1 | |
#define CONSUMER 0 | |
#define true 1 | |
#define false 0 | |
#define br printf("\n") | |
#define ITEMS_TO_PRODUCE 500 //To define how many items will be produced | |
#define ITEMS_TO_CONSUME 500 // To define how many items will be consumed | |
int p = 1; | |
int c = 0; | |
void producer(int *, int *, int *); | |
void consumer(int *, int *, int *); | |
int main(int argc, char **argv) { | |
int ShmID, ShmID1, bufferId; | |
int *count, *turn, *flag; | |
int *buffer; // Will be the buffer used by producer and consumer | |
pid_t pid; | |
int status; | |
// Creating a Shared Memory Space | |
ShmID = shmget(IPC_PRIVATE, 1*sizeof(int), IPC_CREAT | 0666); | |
ShmID1 = shmget(IPC_PRIVATE, 2*sizeof(int), IPC_CREAT | 0666); // to be used as lock variable | |
bufferId = shmget(IPC_PRIVATE, BUFFERSIZE*sizeof(int), IPC_CREAT | 0666); | |
if(ShmID<0 || ShmID1<0 || bufferId<0){ | |
// Will come here if there was error in memory allocation | |
printf("Shmget error in server\n"); | |
exit(1); | |
} | |
// If program doesn't get into the if condition | |
// then the shared space is created successfully | |
// Attaching the Shared Memory Space with current process | |
count = (int *) shmat(ShmID, NULL, 0); | |
flag = (int *) shmat(ShmID1, NULL, 0); | |
buffer = (int *) shmat(bufferId, NULL, 0); | |
if(count == (int *)-1 || flag==(int *)-1 || buffer==(int *)-1){ | |
// Will come here if there was error in attaching some memory | |
printf("shmat error in server\n"); | |
} | |
// If program is here, then memory attachment successful | |
flag[PRODUCER] = false; | |
flag[CONSUMER] = false; //Initializing both processes as not willing to enter CR; | |
pid = fork(); | |
if(pid==0){ | |
producer(count, flag, buffer); | |
exit(0); // adding this condition so that the forked process exits here | |
// and doesn't go any further | |
} | |
else{ | |
pid = fork(); | |
if(pid==0){ | |
consumer(count, flag, buffer); | |
exit(0); //to terminate the fork process exactly after calling the function | |
} | |
} | |
// Waiting for both child processes to terminate | |
wait(&status); | |
wait(&status); | |
shmdt((void *) count); // detaching memory assigned to count | |
shmctl(ShmID, IPC_RMID, NULL); //removing memory assigned to count | |
shmdt((void *) flag); // detaching memory assigned to turn | |
shmdt((void*) buffer); // detaching memory assigned to buffer | |
shmctl(ShmID1, IPC_RMID, NULL); //removing memory assigned to turn | |
shmctl(bufferId, IPC_RMID, NULL); //removing memory assigned to buffer | |
} | |
void producer(int *count, int *flag, int *buffer){ | |
// Instead of an infine loop | |
// We will take a finite loop and produce | |
// finite number of | |
int i; | |
for(i=0;i<ITEMS_TO_PRODUCE;i++){// Producing 1000 items instead of running this as an infinite loop | |
int data; // data item to be added to buffer | |
data = rand()%1000; // Generating a random value | |
while(count[0] == BUFFERSIZE){ | |
// wait if buffer is full | |
// but we also have to make sure that the consumer doesnt stop | |
// thats why while we are waiting we'll give consumer a chance to consume | |
flag[CONSUMER] = true; //let consumer consume | |
} | |
flag[PRODUCER] == true; // Producer is willing to enter the CR | |
while(flag[CONSUMER]==true); // Waiting till the Consumer is in CR | |
// Critical Region Starts Here | |
*count+=1; | |
data = rand()%1000; | |
printf("Produced. No. of items in Buffer now: %d\n", *count); | |
// Critical Region Ends here | |
flag[PRODUCER] = false; //Exiting CR. Consumer can now enter CR if it wants to | |
} | |
printf("Producer Done"); br; | |
} | |
void consumer(int *count, int *flag, int *buffer){ | |
// Instead of an infine loop | |
// We will take a finite loop and consume | |
// finite number of values in buffer | |
int i; | |
for(i=0;i<ITEMS_TO_CONSUME;i++){ | |
// Consuming 500 items instead of making it an infinite loop | |
while(*count== 0){ | |
// wait till the buffer remains empty | |
// but we also have to make sure that the producer doesnt stop | |
// production | |
flag[PRODUCER]=true ; //let producer produce | |
} | |
flag[CONSUMER] = true; // Consumer Process willing to enter CR | |
while(flag[PRODUCER]); // Waiting till the producer process is in CR | |
// Critical Region Starts Here | |
*count-=1; | |
printf("Consumed. In Bufer now: %d\n", *count); | |
// Critical Region Ends here | |
flag[CONSUMER]=false; //Exiting CR | |
} | |
printf("Consumer done");br; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Producer Consumer Problem using turn variable | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/types.h> | |
#include <sys/ipc.h> | |
#include <sys/shm.h> | |
#define BUFFERSIZE 100 | |
#define PRODUCER 1 | |
#define CONSUMER 0 | |
#define ITEMS_TO_PRODUCE 500 //To define how many items will be produced | |
#define ITEMS_TO_CONSUME 500 // To define how many items will be consumed | |
int p = 1; | |
int c = 0; | |
void producer(int *, int *, int *); | |
void consumer(int *, int *, int *); | |
int main(int argc, char **argv) { | |
int ShmID, ShmID1, bufferId; | |
int *count, *turn; | |
int *buffer; // Will be the buffer used by producer and consumer | |
pid_t pid; | |
int status; | |
// Creating a Shared Memory Space | |
ShmID = shmget(IPC_PRIVATE, 1*sizeof(int), IPC_CREAT | 0666); | |
ShmID1 = shmget(IPC_PRIVATE, 1*sizeof(int), IPC_CREAT | 0666); | |
bufferId = shmget(IPC_PRIVATE, BUFFERSIZE*sizeof(int), IPC_CREAT | 0666); | |
if(ShmID<0 || ShmID1<0 || bufferId<0){ | |
// Will come here if there was error in memory allocation | |
printf("Shmget error in server\n"); | |
exit(1); | |
} | |
// If program doesn't get into the if condition | |
// then the shared space is created successfully | |
// Attaching the Shared Memory Space with current process | |
count = (int *) shmat(ShmID, NULL, 0); | |
turn = (int *) shmat(ShmID1, NULL, 0); | |
buffer = (int *) shmat(bufferId, NULL, 0); | |
if(count == (int *)-1 || turn==(int *)-1 || buffer==(int *)-1){ | |
// Will come here if there was error in attaching some memory | |
printf("shmat error in server\n"); | |
} | |
// If program is here, then memory attachment successful | |
*turn = PRODUCER; // assigning turn to producer process | |
pid = fork(); | |
if(pid==0){ | |
producer(count, turn, buffer); | |
exit(0); // adding this condition so that the forked process exits here | |
// and doesn't go any further | |
} | |
else{ | |
pid = fork(); | |
if(pid==0){ | |
consumer(count, turn, buffer); | |
exit(0); //to terminate the fork process exactly after calling the function | |
} | |
} | |
// Waiting for both child processes to terminate | |
wait(&status); | |
wait(&status); | |
shmdt((void *) count); // detaching memory assigned to count | |
shmctl(ShmID, IPC_RMID, NULL); //removing memory assigned to count | |
shmdt((void *) turn); // detaching memory assigned to turn | |
shmdt((void*) buffer); // detaching memory assigned to buffer | |
shmctl(ShmID1, IPC_RMID, NULL); //removing memory assigned to turn | |
shmctl(bufferId, IPC_RMID, NULL); //removing memory assigned to buffer | |
} | |
void producer(int *count, int *turn, int *buffer){ | |
// Instead of an infine loop | |
// We will take a finite loop and produce | |
// finite number of | |
int i; | |
for(i=0;i<ITEMS_TO_PRODUCE;i++){// Producing 1000 items instead of running this as an infinite loop | |
int data; // data item to be added to buffer | |
data = rand()%1000; // Generating a random value | |
while(count[0] == BUFFERSIZE){ | |
// wait if buffer is full | |
// but we also have to make sure that the consumer doesnt stop | |
// thats why while we are waiting we'll give consumer a chance to consume | |
*turn = CONSUMER; //let consumer consume | |
} | |
while(*turn==CONSUMER); // Waiting till the other process is in CR | |
// Critical Region Starts Here | |
*count+=1; | |
data = rand()%1000; | |
printf("Produced. No. of items in Buffer now: %d\n", *count); | |
// Critical Region Ends here | |
*turn = CONSUMER; //Exiting CR | |
} | |
*turn = c; | |
} | |
void consumer(int *count, int *turn, int *buffer){ | |
// Instead of an infine loop | |
// We will take a finite loop and consume | |
// finite number of values in buffer | |
int i; | |
for(i=0;i<ITEMS_TO_CONSUME;i++){ | |
// Consuming 500 items instead of making it an infinite loop | |
while(count[0] == 0){ | |
// wait till the buffer remains empty | |
// but we also have to make sure that the producer doesnt stop | |
// production | |
*turn = PRODUCER; //let producer produce | |
} | |
while(*turn==PRODUCER); // Waiting till the other process is in CR | |
// Critical Region Starts Here | |
*count-=1; | |
printf("Consumed. In Buffer now: %d\n", *count); | |
// Critical Region Ends here | |
*turn = PRODUCER; //Exiting CR | |
} | |
printf("Consumer done\n"); | |
*turn = p; // Consumed all items. Giving producer a turn | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment