The bounded-buffer solution in the below code uses a last-in-first-out strategy (LIFO). Change the code to implement a FIFO (First-in-First-out) strategy. You may use the (in,out) pointer method (using semaphores to test if the queue is full or empty should alleviate the problem of only using up N-1 locations) or implement a FIFO queue. Use the correct counting semaphore implementation. C code below ******************************************************************************************************************************* #include #include #include #include #define SIZE 5 #define NUMB_THREADS 6 #define PRODUCER_LOOPS 2 typedef int buffer_t; buffer_t buffer[SIZE]; int buffer_index; pthread_mutex_t buffer_mutex; /* initially buffer will be empty. full_sem will be initialized to buffer SIZE, which means SIZE number of producer threads can write to it. And empty_sem will be initialized to 0, so no consumer can read from buffer until a producer thread posts to empty_sem */ sem_t full_sem; /* when 0, buffer is full */ sem_t empty_sem; /* when 0, buffer is empty. Kind of like an index for the buffer */ void insertbuffer(buffer_t value) { if (buffer_index < SIZE) { buffer[buffer_index++] = value; } else { printf("Buffer overflow\n"); } } buffer_t dequeuebuffer() { if (buffer_index > 0) { return buffer[--buffer_index]; // buffer_index-- would be error! } else { printf("Buffer underflow\n"); } return 0; } void *producer(void *thread_n) { int thread_numb = *(int *)thread_n; buffer_t value; int i=0; while (i++ < PRODUCER_LOOPS) { sleep(rand() % 10); value = rand() % 100; sem_wait(&full_sem); // sem=0: wait. sem>0: go and decrement it /* possible race condition here. After this thread wakes up, another thread could aqcuire mutex before this one, and add to list. Then the list would be full again and when this thread tried to insert to buffer there would be a buffer overflow error */ pthread_mutex_lock(&buffer_mutex); /* protecting critical section */ insertbuffer(value); pthread_mutex_unlock(&buffer_mutex); sem_post(&empty_sem); // post (increment) emptybuffer semaphore printf("Producer %d added %d to buffer\n", thread_numb, value); } pthread_exit(0); } void *consumer(void *thread_n) { int thread_numb = *(int *)thread_n; buffer_t value; int i=0; while (i++ < PRODUCER_LOOPS) { sem_wait(&empty_sem); /* there could be race condition here, that could cause buffer underflow error */ pthread_mutex_lock(&buffer_mutex); value = dequeuebuffer(value); pthread_mutex_unlock(&buffer_mutex); sem_post(&full_sem); // post (increment) fullbuffer semaphore printf("Consumer %d dequeue %d from buffer\n", thread_numb, value); } pthread_exit(0); } int main(int argc, int **argv) { buffer_index = 0; pthread_mutex_init(&buffer_mutex, NULL); sem_init(&full_sem, // sem_t *sem 0, // int pshared. 0 = shared between threads of process, 1 = shared between processes SIZE); // unsigned int value. Initial value sem_init(&empty_sem, 0, 0); /* full_sem is initialized to buffer size because SIZE number of producers can add one element to buffer each. They will wait semaphore each time, which will decrement semaphore value. empty_sem is initialized to 0, because buffer starts empty and consumer cannot take any element from it. They will have to wait until producer posts to that semaphore (increments semaphore value) */ pthread_t thread[NUMB_THREADS]; int thread_numb[NUMB_THREADS]; int i; for (i = 0; i < NUMB_THREADS; ) { thread_numb[i] = i; pthread_create(thread + i, // pthread_t *t NULL, // const pthread_attr_t *attr producer, // void *(*start_routine) (void *) thread_numb + i); // void *arg i++; thread_numb[i] = i; // playing a bit with thread and thread_numb pointers... pthread_create(&thread[i], // pthread_t *t NULL, // const pthread_attr_t *attr consumer, // void *(*start_routine) (void *) &thread_numb[i]); // void *arg i++; } for (i = 0; i < NUMB_THREADS; i++) pthread_join(thread[i], NULL); pthread_mutex_destroy(&buffer_mutex); sem_destroy(&full_sem); sem_destroy(&empty_sem); return 0;

Computer Networking: A Top-Down Approach (7th Edition)
7th Edition
ISBN:9780133594140
Author:James Kurose, Keith Ross
Publisher:James Kurose, Keith Ross
Chapter1: Computer Networks And The Internet
Section: Chapter Questions
Problem R1RQ: What is the difference between a host and an end system? List several different types of end...
icon
Related questions
Question

The bounded-buffer solution in the below code uses a last-in-first-out strategy (LIFO).
Change the code to implement a FIFO (First-in-First-out) strategy. You may use the (in,out) pointer method
(using semaphores to test if the queue is full or empty should
alleviate the problem of only using up N-1 locations) or implement a FIFO queue. Use
the correct counting semaphore implementation.

C code below

*******************************************************************************************************************************

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

#define SIZE 5
#define NUMB_THREADS 6
#define PRODUCER_LOOPS 2

typedef int buffer_t;
buffer_t buffer[SIZE];
int buffer_index;

pthread_mutex_t buffer_mutex;
/* initially buffer will be empty. full_sem
will be initialized to buffer SIZE, which means
SIZE number of producer threads can write to it.
And empty_sem will be initialized to 0, so no
consumer can read from buffer until a producer
thread posts to empty_sem */
sem_t full_sem; /* when 0, buffer is full */
sem_t empty_sem; /* when 0, buffer is empty. Kind of
like an index for the buffer */



void insertbuffer(buffer_t value) {
if (buffer_index < SIZE) {
buffer[buffer_index++] = value;
} else {
printf("Buffer overflow\n");
}
}

buffer_t dequeuebuffer() {
if (buffer_index > 0) {
return buffer[--buffer_index]; // buffer_index-- would be error!
} else {
printf("Buffer underflow\n");
}
return 0;
}


void *producer(void *thread_n) {
int thread_numb = *(int *)thread_n;
buffer_t value;
int i=0;
while (i++ < PRODUCER_LOOPS) {
sleep(rand() % 10);
value = rand() % 100;
sem_wait(&full_sem); // sem=0: wait. sem>0: go and decrement it
/* possible race condition here. After this thread wakes up,
another thread could aqcuire mutex before this one, and add to list.
Then the list would be full again
and when this thread tried to insert to buffer there would be
a buffer overflow error */
pthread_mutex_lock(&buffer_mutex); /* protecting critical section */
insertbuffer(value);
pthread_mutex_unlock(&buffer_mutex);
sem_post(&empty_sem); // post (increment) emptybuffer semaphore
printf("Producer %d added %d to buffer\n", thread_numb, value);
}
pthread_exit(0);
}

void *consumer(void *thread_n) {
int thread_numb = *(int *)thread_n;
buffer_t value;
int i=0;
while (i++ < PRODUCER_LOOPS) {
sem_wait(&empty_sem);
/* there could be race condition here, that could cause
buffer underflow error */
pthread_mutex_lock(&buffer_mutex);
value = dequeuebuffer(value);
pthread_mutex_unlock(&buffer_mutex);
sem_post(&full_sem); // post (increment) fullbuffer semaphore
printf("Consumer %d dequeue %d from buffer\n", thread_numb, value);
}
pthread_exit(0);
}

int main(int argc, int **argv) {
buffer_index = 0;

pthread_mutex_init(&buffer_mutex, NULL);
sem_init(&full_sem, // sem_t *sem
0, // int pshared. 0 = shared between threads of process, 1 = shared between processes
SIZE); // unsigned int value. Initial value
sem_init(&empty_sem,
0,
0);
/* full_sem is initialized to buffer size because SIZE number of
producers can add one element to buffer each. They will wait
semaphore each time, which will decrement semaphore value.
empty_sem is initialized to 0, because buffer starts empty and
consumer cannot take any element from it. They will have to wait
until producer posts to that semaphore (increments semaphore
value) */
pthread_t thread[NUMB_THREADS];
int thread_numb[NUMB_THREADS];
int i;
for (i = 0; i < NUMB_THREADS; ) {
thread_numb[i] = i;
pthread_create(thread + i, // pthread_t *t
NULL, // const pthread_attr_t *attr
producer, // void *(*start_routine) (void *)
thread_numb + i); // void *arg
i++;
thread_numb[i] = i;
// playing a bit with thread and thread_numb pointers...
pthread_create(&thread[i], // pthread_t *t
NULL, // const pthread_attr_t *attr
consumer, // void *(*start_routine) (void *)
&thread_numb[i]); // void *arg
i++;
}

for (i = 0; i < NUMB_THREADS; i++)
pthread_join(thread[i], NULL);

pthread_mutex_destroy(&buffer_mutex);
sem_destroy(&full_sem);
sem_destroy(&empty_sem);

return 0; 

Expert Solution
steps

Step by step

Solved in 2 steps

Blurred answer
Recommended textbooks for you
Computer Networking: A Top-Down Approach (7th Edi…
Computer Networking: A Top-Down Approach (7th Edi…
Computer Engineering
ISBN:
9780133594140
Author:
James Kurose, Keith Ross
Publisher:
PEARSON
Computer Organization and Design MIPS Edition, Fi…
Computer Organization and Design MIPS Edition, Fi…
Computer Engineering
ISBN:
9780124077263
Author:
David A. Patterson, John L. Hennessy
Publisher:
Elsevier Science
Network+ Guide to Networks (MindTap Course List)
Network+ Guide to Networks (MindTap Course List)
Computer Engineering
ISBN:
9781337569330
Author:
Jill West, Tamara Dean, Jean Andrews
Publisher:
Cengage Learning
Concepts of Database Management
Concepts of Database Management
Computer Engineering
ISBN:
9781337093422
Author:
Joy L. Starks, Philip J. Pratt, Mary Z. Last
Publisher:
Cengage Learning
Prelude to Programming
Prelude to Programming
Computer Engineering
ISBN:
9780133750423
Author:
VENIT, Stewart
Publisher:
Pearson Education
Sc Business Data Communications and Networking, T…
Sc Business Data Communications and Networking, T…
Computer Engineering
ISBN:
9781119368830
Author:
FITZGERALD
Publisher:
WILEY