1 Compile and run the programs given below as separate proce
(1) Compile and run the programs given below as separate processes.
(2) Modify the code for both producer & consumer to include the PID of the process in the output statements.
(3) Start multiple producers and multiple consumers. Do you have to make any changes to the code to run properly? Explain your answer.
(4) modify the code given below by adding a third type of process which processes the data generated by the producer, before it’s used and printed by the consumer. In this example, the “Processing process” changes the case if the item generated by the producer from upper-case to lower-case and stores it back in the buffer before the consumer can retrieve and print it.
Program #1:
#include <stdio.h>
 #include <sys/types.h>
 #include <semsphore.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/shm.h>
 #define BUFF_SIZE 20
 typedef struct {
 char buffer[BUFF_SIZE];
 int nextIn;
 int nextOut;
 } shared_data;
 shared_data *shm, *s;
 char sem_name1[] = \"mutex\";
 char sem_name2[] = \"empty_slots\";
 char sem_name3[] = \"full_slots\";
 sem_t *empty_slots;
 sem_t *full_slots;
 sem_t *mutex;
 void Put(char item)
 {
 sem_wait(empty_slots);
 sem_wait(mutex);
 s->buffer[s->nextIn] = item;
 s->nextIn = (s->nextIn + 1) % BUFF_SIZE;
 sem_post(mutex);
 printf(\"Producing %c ...\ \", item);
 sem_post(full_slots);
 }
 void Producer()
 {
 int i;
 for(i = 0; i < 10; i++)
 {
 sleep(rand()%3);
 Put((char)(\'A\'+ i % 26));
 }
 }
 void main()
 {
 //Create and initialize the semaphores
 mutex=sem_open(sem_name1, O_CREAT,0644, 1);
 full_slots=sem_open(sem_name3, O_CREAT,0644, 0);
 empty_slots=sem_open(sem_name2, O_CREAT,0644, 10);
 //Create a key for the segment
 key_t key;
 key = 1234; //NOTE: you can use ftok() function to generate the key
 //create the segment
 int shmid;
 if ((shmid = shmget(key, sizeof(shared_data), IPC_CREAT |0666)) <0)
 {
 perror(\"Shmget\");
 exit(1);
 }
 //attach to the segment
 if ((shm = (shared_data *) shmat(shmid, NULL, 0))==(shared_data *) -1)
 {
 perror(\"Shmat\");
 exit(1);
 }
 s=shm;
 s->nextIn = 0;
 Producer( );
 //detach from the segment
 shmdt((void *) shm);
Program #2:
#include <pthread.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <semaphore.h>
 #include <fcntl.h>
 #include <sys/shm.h>
 #define BUFF_SIZE 20
 char buffer[BUFF_SIZE];
 int nextIn = 0;
 int nextOut = 0;
 char sem_name1[] = \"mutex\";
 char sem_name2[] = \"empty_slots\";
 char sem_name3[] = \"full_slots\";
 sem_t *empty_slots;
 sem_t *full_slots;
 sem_t *mutex;
 typedef struct {
 char buffer[BUFF_SIZE];
 int nextIn;
 int nextOut;
 } shared_data;
 shared_data *shm, *s;
 void Get(char item)
 {
 sem_wait(full_slots);
 sem_wait(mutex);
 item = s->buffer[s->nextOut];
 s->nextOut = (s->nextOut + 1) % BUFF_SIZE;
 sem_post(mutex);
 printf(\"Consuming %c ...\ \", item);
 sem_post(empty_slots);
 }
 void Consumer()
 {
 int i;
 char item;
 for(i = 0; i < 10; i++)
 {
 sleep(rand()%9);
 Get(item);
 }
 }
 void main()
 {
 //Open exisitng semaphores
 mutex=sem_open(sem_name1, O_CREAT,0644, 1);
 full_slots=sem_open(sem_name3, O_CREAT,0644, 0);
 empty_slots=sem_open(sem_name2, O_CREAT,0644, 10);
 //Create a key for the segment
 key_t key;
 key = 1234; //NOTE: you can use ftok() function to generate the key
 //locate the segment
 int shmid;
 if ((shmid = shmget(key, sizeof(shared_data),0666)) <0)
 {
 perror(\"Shmget\");
 exit(1);
 }
 //attach to the segment
 if ((shm = (shared_data *) shmat(shmid, NULL, 0))==(shared_data *) -1)
 {
 perror(\"Shmat\");
 exit(1);
 }
 s=shm;
 s->nextOut = 0;
 Consumer();
 }
Solution
Solution:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <conio.h>
#define MAX 10
typedef struct travs {
 int id;
 int numBags;
 int arrTime;
 struct travs *next;
 } travs;
 travs *queue;
 //travs *servicing[MAX];
int produced; // The total # of produced in the queue
pthread_mutex_t queue_lock;
 //pthread_mutex_t staff_lock;
 pthread_cond_t ct, cs;
int CheckIn(){
 sleep(1);
 if(produced != 0) return 1;
 else return 0;
 }
void *producerThread(void *args){
 travs *traveler = (travs *)args;
 // Acquire the mutex
 if(queue != NULL) {
 travs *check_in = malloc(sizeof(travs));
 check_in = queue;
 while(check_in->next != NULL){
 check_in = check_in->next;
 }
 check_in->next = traveler;
 }
 else
 { queue = traveler;
}
 pthread_mutex_lock(&queue_lock);
 produced++;
 // pthread_cond_signal(&cs);
 pthread_cond_wait(&ct, &queue_lock);
 printf(\"Producer %d is now checked in at time %d.\ \", queue->id, (1+queue- >arrTime));
 queue = queue->next;
 pthread_mutex_unlock(&queue_lock);
return;
 }   
int Producer(int id, int numBags, int arrTime){
int ret;
 pthread_t ttid;
 travs *traveler = malloc(sizeof(travs));
 traveler->id = id;
 traveler->numBags = numBags;
 traveler->arrTime = arrTime;
 sleep(arrTime);
 pthread_mutex_lock(&queue_lock);
 if(queue != NULL) {
 travs *check_in = malloc(sizeof(travs));
 check_in = queue;
 while(check_in->next != NULL){
 check_in = check_in->next;
 }
 check_in->next = traveler;
 }
 else { queue = traveler; }
 pthread_mutex_unlock(&queue_lock);
 // Create a new traveler thread
 ret = pthread_create(&ttid, NULL, producerThread, (void *)traveler);
// Check if thread creation was successful
 if(ret == 0) {
 printf(\"Producer %d has entered the check-in line at time %d; s/he is at position %d and has %d bags.\ \", id, arrTime, produced, numBags);
 pthread_cond_signal(&cs);
 return 0;
 }
 else return -1;
}
 void *consumerThread(void *arg){
int i = 0; // travelers serviced
 char *name = (char *)arg;
 while(1) { // run iteratively
// If 20 producers have been served, the consumer\'s work is done.
 if(i == 20) {
 printf(\"Consumer %s\'s service has completed!\ \", name);
 pthread_exit(NULL);
 }
 // Sleep for 10s if 5 travelers have been checked in
 if (((i+1) % 5) == 0) {
 // Wake up sleeping travelers
 printf(\"Consumer %s is taking a break.\ \", name);
 sleep(2);
 printf(\"Consumer %s\'s break is over.\ \", name);
 }
if(CheckIn()) {
 pthread_mutex_lock(&queue_lock);
 int j = 1;
 pthread_cond_wait(&cs, &queue_lock);
 printf(\"Producer %d presents ticket to consumer %s.\ \", queue->id, name);
 printf(\"Consumer %s gives boarding pass to producer %d.\ \", name, queue->id);
 while(j <= queue->numBags){
 printf(\"Consumer %s checks in bag %d for producer %d; baggage tag is _X_.\ \", name, j, queue->id);
 j++;
 }
 // Signal producer being serviced that their check in is complete.
 i++;
 pthread_mutex_unlock(&queue_lock);
 produced--;
 pthread_cond_signal(&ct);
 }
 sleep(3);
 }
 }
int Consumer(char *Name) {
sleep(5);
 int ret;
 pthread_t stid;
 // Create a staff thread
ret = pthread_create(&stid, NULL, consumerThread, (void *)Name);
 // Acquire the lock
 if(ret == 0) {
 printf(\"Producer %s\'s service has begun!\ \", Name);
 return 0;
 }
 else return -1;
 }
int main() {
 int ret = 0;
 char *staff_name = malloc(sizeof(char));
 int staff_check = 0;
 int trav_check = 0;
 int id;
 int bagnum;
 int travtime;
 FILE *consumer_fp;
 FILE *producer_fp;
 queue = malloc(sizeof(travs));
 queue = NULL;
 /*while(ret < 10){
 servicing[ret] = malloc(sizeof(travs));
 servicing[ret] = NULL;
 }*/
// Initilize mutexes
 pthread_mutex_init(&queue_lock, NULL);
 //pthread_mutex_init(&staff_lock, NULL);
// Initialize condition variables
 pthread_cond_init(&ct, NULL);
 pthread_cond_init(&cs, NULL);
// Open the file so we can start reading from it
consumer_fp = fopen(\"staff.txt\", \"r\");
 producer_fp = fopen(\"travelers.txt\", \"r\");
staff_check = fscanf(consumer_fp, \"%s\", staff_name);
 trav_check = fscanf(producer_fp, \"%d %d %d\", &id, &bagnum, &travtime);
 while(1){   
K:
 while(staff_check == 1) {
 Consumer(staff_name);
 staff_check = fscanf(consumer_fp, \"%s\", staff_name);
 goto L;
 }
 L:
 while(trav_check == 3) {
 Producer(id, bagnum, travtime);
 trav_check = fscanf(producer_fp, \"%d %d %d\", &id, &bagnum, &travtime);
 goto K;
 }
pthread_exit(NULL);
 }
}






