EXPERIMENT-5
CONTROL THE NUMBER OF PORTS OPENED BY THE OPERATING SYSTEM WITH
A)
a)SEMAPHORE
SOURCE CODE:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#define MAX_PORTS 3
sem_t portSemaphore;
void* open_port(void* arg)
{
    int port = *(int*)arg;
    sem_wait(&portSemaphore);
    printf("Port %d opened by thread %ld\n", port, pthread_self());
    sleep(2);
    printf("Port %d closed by thread %ld\n", port, pthread_self());
    sem_post(&portSemaphore);
    free(arg);
    return NULL;
}
int main()
{
    pthread_t threads[10];
    int i;
    sem_init(&portSemaphore, 0, MAX_PORTS);
    for (i = 0; i < 10; i++)
    {
        int *port = malloc(sizeof(int));
        *port = 8000 + i;
        pthread_create(&threads[i], NULL, open_port, port);
        sleep(1);
    }
    for (i = 0; i < 10; i++)
    {
        pthread_join(threads[i], NULL);
    }
    sem_destroy(&portSemaphore);
    return 0;
}
Output:
B) MONITORS IN C LANGUAGE
SOURSE CODE:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define MAX_PORTS 3
pthread_mutex_t lock;
pthread_cond_t cond;
int open_ports = 0;
void* open_port(void* arg)
{
    int port = *(int*)arg;
    pthread_mutex_lock(&lock);
    while (open_ports >= MAX_PORTS)
    {
        pthread_cond_wait(&cond, &lock);
    }
    open_ports++;
    printf("Port %d opened by thread %ld\n", port, pthread_self());
    pthread_mutex_unlock(&lock);
    sleep(2);
    pthread_mutex_lock(&lock);
    open_ports--;
    printf("Port %d closed by thread %ld\n", port, pthread_self());
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&lock);
    free(arg);
    return NULL;
}
int main()
{
    pthread_t threads[10];
    int i;
    pthread_mutex_init(&lock, NULL);
    pthread_cond_init(&cond, NULL);
    for (i = 0; i < 10; i++)
    {
        int *port = malloc(sizeof(int));
        *port = 8000 + i;
        pthread_create(&threads[i], NULL, open_port, port);
        sleep(1);
    }
    for (i = 0; i < 10; i++)
    {
        pthread_join(threads[i], NULL);
    }
    pthread_mutex_destroy(&lock);
    pthread_cond_destroy(&cond);
    return 0;
}
Output:
B) Dining Philosophers Problem Using Semaphores
Source code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#define N 5
sem_t forks[N];
sem_t room;
void* philosopher(void* arg) {
    int id = *(int*)arg;
    while (1) {
        printf("Philosopher %d is thinking...\n", id);
        sleep(1);
        sem_wait(&room);
        sem_wait(&forks[id]);
        sem_wait(&forks[(id + 1) % N]);
        printf("Philosopher %d is eating...\n", id);
        sleep(2);
        sem_post(&forks[id]);
        sem_post(&forks[(id + 1) % N]);
        sem_post(&room);
    }
    return NULL;
}
int main() {
    pthread_t philosophers[N];
    int id[N];
    int i;
    sem_init(&room, 0, N - 1);
    for (i = 0; i < N; i++) {
        sem_init(&forks[i], 0, 1);
    }
    for (i = 0; i < N; i++) {
        id[i] = i;
        pthread_create(&philosophers[i], NULL, philosopher, &id[i]);
        sleep(1);
    }
    for (i = 0; i < N; i++) {
        pthread_join(philosophers[i], NULL);
    }
    for (i = 0; i < N; i++) {
        sem_destroy(&forks[i]);
    }
    sem_destroy(&room);
    return 0;
}
Output:
C) Dining Philosophers Problem using Monitors
Source code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define N 5
#define THINKING 0
#define HUNGRY 1
#define EATING 2
pthread_mutex_t lock;
pthread_cond_t cond[N];
int state[N];
void test(int id) {
  if (state[id] == HUNGRY && state[(id + 4) % N] != EATING && state[(id
+ 1) % N] != EATING) {
        state[id] = EATING;
        printf("Philosopher %d is eating...\n", id);
        pthread_cond_signal(&cond[id]);
    }
}
void take_forks(int id) {
    pthread_mutex_lock(&lock);
    state[id] = HUNGRY;
    test(id);
    while (state[id] != EATING) {
        pthread_cond_wait(&cond[id], &lock);
    }
    pthread_mutex_unlock(&lock);
}
void put_forks(int id) {
    pthread_mutex_lock(&lock);
    state[id] = THINKING;
    printf("Philosopher %d is thinking...\n", id);
    test((id + 4) % N);
    test((id + 1) % N);
    pthread_mutex_unlock(&lock);
}
void* philosopher(void* arg) {
    int id = *(int*)arg;
    while (1) {
        printf("Philosopher %d is thinking...\n", id);
        sleep(1);
        take_forks(id);
        sleep(2);
        put_forks(id);
    }
    return NULL;
}
int main() {
    pthread_t philosophers[N];
    int i;
    pthread_mutex_init(&lock, NULL);
    for (i = 0; i < N; i++) {
        pthread_cond_init(&cond[i], NULL);
        state[i] = THINKING;
    }
    for (i = 0; i < N; i++) {
        int* id = malloc(sizeof(int));
        if (id == NULL) {
            perror("Failed to allocate memory");
            exit(EXIT_FAILURE);
        }
        *id = i;
        pthread_create(&philosophers[i], NULL, philosopher, id);
        sleep(1);
    }
    for (i = 0; i < N; i++) {
        pthread_join(philosophers[i], NULL);
    }
    pthread_mutex_destroy(&lock);
    for (i = 0; i < N; i++) {
        pthread_cond_destroy(&cond[i]);
    }
    return 0;
}
Output: