Semaphores and Deadlocks


Presentation by Pruthvik N Narayanaswamy

Introduction

  • What is a semaphore ?

  • Why are they used ?


Then...


What is a mutex?

Usage and functions

The Types

System V Semaphores


//System semaphore initialisation
int semctl(int  semid, int semnum, int cmd, ...);

//Operation
int semop(int  semid, struct sembuf *sops, size_t nsops);

//User-defined array of semaphore structure
struct  sembuf {
   ushort sem_num; /* identifies which semaphore in the set */
   short sem_op; /* could be positive,negative or zero */
   short sem_flg; /*coud be IPC_NOWAIT ,SEM_UNDO*/
};
  						

POSIX Semaphore


						 sem_t *sem_open(const char *name,  int oflag, mode_t mode , int value);

/*This call locks the semaphore if the semaphore count is greater than
 zero. After locking the semaphore, the count is reduced by 1. If the
  semaphore count is zero, the call blocks.*/
int  sem_wait(sem_t *sem);

/*
This call increases the semaphore count by 1 and then returns.
*/
int  sem_post(sem_t *sem);

//close
sem_close();

sem_unlink();

What is the difference ?

Deadlock


The four necessary conditions

Mutual Exclusion

Hold and Wait

No Preemption

Circular Wait

Solution ?

Dining Philosophers Problem


Solution


params_t struct and functions


#include 'stdio.h'
#include 'stdlib.h'
#include 'pthread.h'
#include 'semaphore.h'

typedef struct {
  int position;
  int count;
  sem_t *forks;
  sem_t *lock;
} params_t;

void initialize_semaphores(sem_t *lock, sem_t *forks, int num_forks);
void run_all_threads(pthread_t *threads, sem_t *forks, sem_t *lock, int num_philosophers);

void *philosopher(void *params);
void think(int position);
void eat(int position);

void think(int position)
{
  printf("Philosopher %d thinking...\n", position);
}

void eat(int position)
{
  printf("Philosopher %d eating...\n", position);
}
						

main function


int main(int argc, char *args[])
{
  int num_philosophers = 5;

  sem_t lock;
  sem_t forks[num_philosophers];
  pthread_t philosophers[num_philosophers];

  initialize_semaphores(&lock, forks, num_philosophers);
  run_all_threads(philosophers, forks, &lock, num_philosophers);
  pthread_exit(NULL);
}
						

the initialize semaphores function


void initialize_semaphores(sem_t *lock, sem_t *forks, int num_forks)
{
  int i;
  for(i = 0; i < num_forks; i++) {
    sem_init(&forks[i], 0, 1);
  }

  sem_init(lock, 0, num_forks - 1);
}						
						

run_all_threads function


void run_all_threads(pthread_t *threads, sem_t *forks, sem_t *lock, int num_philosophers)
{
  int i;
  for(i = 0; i < num_philosophers; i++) {
    params_t *arg = malloc(sizeof(params_t));
    arg->position = i;
    arg->count = num_philosophers;
    arg->lock = lock;
    arg->forks = forks;

    pthread_create(&threads[i], NULL, philosopher, (void *)arg);
  }
}
						

the philosopher function


void *philosopher(void *params)
{
  int i;
  params_t self = *(params_t *)params;

  for(i = 0; i < 3; i++) {
    think(self.position);

    sem_wait(self.lock);
    sem_wait(&self.forks[self.position]);
    sem_wait(&self.forks[(self.position + 1) % self.count]);
    eat(self.position);
    sem_post(&self.forks[self.position]);
    sem_post(&self.forks[(self.position + 1) % self.count]);
    sem_post(self.lock);
  }

  think(self.position);
  pthread_exit(NULL);
}
						

Thank you