0% found this document useful (0 votes)
21 views11 pages

Producer Consumer Problem and Memory Management Program

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views11 pages

Producer Consumer Problem and Memory Management Program

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

Introduction

The producer-consumer problem involves two types of processes: producers,


which generate data (or items), and consumers, which use or process that data.
A common way to manage this scenario is by using a shared buffer and
synchronization mechanisms to ensure that producers and consumers work
seamlessly without conflicts.

Includes and Definitions:


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

#define BUFFER_SIZE 5
#define NUM_ITEMS 10
Headers: Necessary for input/output, threading, and semaphore functions.
Definitions: Constants for the buffer size and number of items to
produce/consume.
Shared Variables:
int buffer[BUFFER_SIZE];
int in = 0; // Index for next item to produce
int out = 0; // Index for next item to consume
Buffer: A circular buffer where produced items are stored.
in and out: Indices to track where to produce and consume items

Semaphores and Mutex:


sem_t empty; // Semaphore to count empty slots
sem_t full; // Semaphore to count full slots
pthread_mutex_t mutex; // Mutex for critical section
Semaphores:

 empty: Counts how many empty slots are available in the buffer.
 full: Counts how many items are currently in the buffer.

Mutex: Ensures mutual exclusion when accessing the buffer.

Producer Function:
void* producer(void* arg) {
for (int i = 0; i < NUM_ITEMS; i++) {
int item = rand() % 100; // Produce an item

sem_wait(&empty); // Decrease the count of empty slots


pthread_mutex_lock(&mutex); // Enter critical section

// Add item to buffer


buffer[in] = item;
printf("Producer produced: %d\n", item);
in = (in + 1) % BUFFER_SIZE;

pthread_mutex_unlock(&mutex); // Exit critical section


sem_post(&full); // Increase the count of full slots

sleep(rand() % 2); // Simulate variable production time


}
return NULL;
}


 Semaphore Operations:
o sem_wait(&empty): Waits until there is an empty slot.
o sem_post(&full): Signals that a new item has been added.
 Mutex Operations:
o Locking around the buffer access ensures that only one producer or
consumer can modify the buffer at a time.

Consumer Function:

void* consumer(void* arg) {


for (int i = 0; i < NUM_ITEMS; i++) {
sem_wait(&full); // Decrease the count of full slots
pthread_mutex_lock(&mutex); // Enter critical section

// Remove item from buffer


int item = buffer[out];
printf("Consumer consumed: %d\n", item);
out = (out + 1) % BUFFER_SIZE;

pthread_mutex_unlock(&mutex); // Exit critical section


sem_post(&empty); // Increase the count of empty slots

sleep(rand() % 2); // Simulate variable consumption time


}
return NULL;
}

the buffer.

Main Function:
int main() {
pthread_t prod, cons;

// Initialize semaphores and mutex


sem_init(&empty, 0, BUFFER_SIZE); // All slots are empty initially
sem_init(&full, 0, 0); // No slots are full initially
pthread_mutex_init(&mutex, NULL);

// Create producer and consumer threads


pthread_create(&prod, NULL, producer, NULL);
pthread_create(&cons, NULL, consumer, NULL);

// Wait for threads to finish


pthread_join(prod, NULL);
pthread_join(cons, NULL);

// Cleanup
sem_destroy(&empty);
sem_destroy(&full);
pthread_mutex_destroy(&mutex);

return 0;
}
Thread Creation: Producer and consumer threads are created.
Joining Threads: The main thread waits for both the producer and
consumer to finish.
Cleanup: Semaphores and mutexes are destroyed to free resources.

How It Works

1. The producer creates items and waits if the buffer is full.


2. The consumer waits if the buffer is empty and consumes items.
3. Semaphores and mutexes ensure that the buffer is accessed safely,
preventing race conditions.

/* Producer –Consumer Program in C */


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

#define BUFFER_SIZE 5
#define NUM_ITEMS 10

int buffer[BUFFER_SIZE];
int in = 0; // Index for next item to produce
int out = 0; // Index for next item to consume

sem_t empty; // Semaphore to count empty slots


sem_t full; // Semaphore to count full slots
pthread_mutex_t mutex; // Mutex for critical section

void* producer(void* arg) {


for (int i = 0; i < NUM_ITEMS; i++) {
int item = rand() % 100; // Produce an item

sem_wait(&empty); // Decrease the count of empty slots


pthread_mutex_lock(&mutex); // Enter critical section

// Add item to buffer


buffer[in] = item;
printf("Producer produced: %d\n", item);
in = (in + 1) % BUFFER_SIZE;

pthread_mutex_unlock(&mutex); // Exit critical section


sem_post(&full); // Increase the count of full slots

sleep(rand() % 2); // Simulate variable production time


}
return NULL;
}

void* consumer(void* arg) {


for (int i = 0; i < NUM_ITEMS; i++) {
sem_wait(&full); // Decrease the count of full slots
pthread_mutex_lock(&mutex); // Enter critical section

// Remove item from buffer


int item = buffer[out];
printf("Consumer consumed: %d\n", item);
out = (out + 1) % BUFFER_SIZE;

pthread_mutex_unlock(&mutex); // Exit critical section


sem_post(&empty); // Increase the count of empty slots
sleep(rand() % 2); // Simulate variable consumption time
}
return NULL;
}

int main() {
pthread_t prod, cons;

// Initialize semaphores and mutex


sem_init(&empty, 0, BUFFER_SIZE); // All slots are empty initially
sem_init(&full, 0, 0); // No slots are full initially
pthread_mutex_init(&mutex, NULL);

// Create producer and consumer threads


pthread_create(&prod, NULL, producer, NULL);
pthread_create(&cons, NULL, consumer, NULL);

// Wait for threads to finish


pthread_join(prod, NULL);
pthread_join(cons, NULL);

// Cleanup
sem_destroy(&empty);
sem_destroy(&full);
pthread_mutex_destroy(&mutex);
return 0;
}
Write a C program to simulate the following contiguous memory allocation
Techniques a) Worst fit b) Best fit c) First fit.
#include <stdio.h>

void worstFit(int b[], int m, int p[], int n) {


for (int i = 0; i < n; i++) {
int maxIdx = -1;
for (int j = 0; j < m; j++) {
if (b[j] >= p[i] && (maxIdx == -1 || b[maxIdx] < b[j])) {
maxIdx = j;
}
}
if (maxIdx != -1) {
printf("Process %d allocated to Block %d\n", i + 1, maxIdx + 1);
b[maxIdx] -= p[i];
} else {
printf("Process %d not allocated\n", i + 1);
}
}
}

void bestFit(int b[], int m, int p[], int n) {


for (int i = 0; i < n; i++) {
int bestIdx = -1;
for (int j = 0; j < m; j++) {
if (b[j] >= p[i] && (bestIdx == -1 || b[bestIdx] > b[j])) {
bestIdx = j;
}
}
if (bestIdx != -1) {
printf("Process %d allocated to Block %d\n", i + 1, bestIdx + 1);
b[bestIdx] -= p[i];
} else {
printf("Process %d not allocated\n", i + 1);
}
}
}

void firstFit(int b[], int m, int p[], int n)


{
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (b[j] >= p[i]) {
printf("Process %d allocated to Block %d\n", i + 1, j + 1);
b[j] -= p[i];
break;
}
}
}
}

int main() {
int blockSize[10], processSize[10], m, n;

printf("Enter number of blocks: ");


scanf("%d", &m);
printf("Enter block sizes:\n");
for (int i = 0; i < m; i++) {
scanf("%d", &blockSize[i]);
}

printf("Enter number of processes: ");


scanf("%d", &n);
printf("Enter process sizes:\n");
for (int i = 0; i < n; i++) {
scanf("%d", &processSize[i]);
}

printf("\nWorst Fit Allocation:\n");


worstFit(blockSize, m, processSize, n);

// Reset block sizes for other methods


printf("\nBest Fit Allocation:\n");
bestFit(blockSize, m, processSize, n);

// Reset block sizes for other methods


printf("\nFirst Fit Allocation:\n");
firstFit(blockSize, m, processSize, n);

return 0;
}

You might also like