PROCESS SYNCHRONIZATION – SEMAPHORES – PC problem

PROCESS SYNCHRONIZATION USING SEMAPHORES
(Producer Consumer Problem)

PTHREAD MUTEX FUNCTIONS:
Mutex is a data type used in Pthreads to  provide functions that will block a thread if another thread is accessing data that it is using. Mutex has two basic operations, lock and unlock. If a mutex is unlocked and a thread calls lock, the mutex locks and the thread continues. If however the mutex is locked, the thread blocks until the thread ‘holding’ the lock calls unlock.
There are 5 basic functions for dealing with mutex.
  • Initialize a mutex with specified attributes
    • int pthread_mutex_init (pthread_mutex_t *mut, const pthread_mutexattr_t *attr);
  • Lock the Mutex
    • int pthread_mutex_lock (pthread_mutex_t *mut);
  • Unlock the Mutex.
    • int pthread_mutex_unlock (pthread_mutex_t *mut);
  • Acquires the lock on the Mutex.
    • int pthread_mutex_trylock (pthread_mutex_t *mut);
  • Deallocate any memory or other resources associated with the Mutex.
    • int pthread_mutex_destroy (pthread_mutex_t *mut);

// Producer Consumer Problem
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include </usr/include/semaphore.h>
#include <unistd.h>       // for sleep
#define BUFSIZE      5       /* total number of slots */
#define NP               1       /* total number of producers */
#define NC               1       /* total number of consumers */
#define NITEMS       5       /* number of items produced/consumed */
typedef struct
{
     int buf[BUFSIZE];     /* shared var */
     int in;                       /* buf[in%BUFSIZE] – first empty slot */
     int out;                     /* buf[out%BUFSIZE] – first full slot */
     sem_t full;                /* keep track of number of full spots */
     sem_t empty;             /* keep track of number of empty spots */
     /* enforce mutual exclusion to shared data */
     pthread_mutex_t mutex;
} sbuf_t;
sbuf_t shared;

void *Producer(void *arg)
{
int i, item;
for (i=1; i <=NITEMS; i++)
{
item = i;      /* Produce item */
/* Prepare to write item to buf */
/* If there are no empty slots, wait */
sem_wait(&shared.empty);
/* If another thread uses the buffer, wait */
pthread_mutex_lock(&shared.mutex);
shared.buf[shared.in] = item;
shared.in = (shared.in+1)%BUFSIZE;
printf(“Produced : %d\n”, item);
fflush(stdout);
/* Release the buffer */
pthread_mutex_unlock(&shared.mutex);
/* Increment the number of full slots */
sem_post(&shared.full);
/* Interleave  producer and consumer execution */
sleep(1);
}
return NULL;
}

void *Consumer(void *arg)
{
int i, item;
for (i=NITEMS; i > 0; i–)
{
sem_wait(&shared.full);
pthread_mutex_lock(&shared.mutex);
item=i;
item=shared.buf[shared.out];
shared.out = (shared.out+1)%BUFSIZE;
printf(“\tConsumed : %d\n”, item);
fflush(stdout);
/* Release the buffer */
pthread_mutex_unlock(&shared.mutex);
/* Increment the number of full slots */
sem_post(&shared.empty);
/* Interleave  producer and consumer execution */
sleep(1);
}
return NULL;
}

int main()
{
pthread_t idP, idC;
sem_init(&shared.full, 0, 0);
sem_init(&shared.empty, 0, BUFSIZE);
pthread_mutex_init(&shared.mutex, NULL);
/* Create a new producer */
pthread_create(&idP, NULL, Producer, (void*)NP);
/*create a new Consumer*/
pthread_create(&idC, NULL, Consumer, (void*)NC);
pthread_exit(NULL);
}

OUTPUT:
[anu@localhost OS]$ cc pc.c -lpthread
[anu@localhost OS]$ ./a.out
Produced : 1
        Consumed : 1
Produced : 2
        Consumed : 2
Produced : 3
        Consumed : 3
Produced : 4
        Consumed : 4
Produced : 5
        Consumed : 5
[anu@localhost OS]$