Transcript Document

The Problem…
Five silent philosophers sit at a table around a bowl of
spaghetti. A fork is placed between each pair of adjacent
philosophers. Each philosopher must alternately think
and eat. However, a philosopher can only eat spaghetti
when he has both left and right forks. Each fork can be
held by only one philosopher and so a philosopher can
use the fork only if it's not being used by another
philosopher. After he finishes eating, he needs to put
down both forks so they become available to others. A
philosopher can grab the fork on his right or the one on
his left as they become available, but can't start eating
before getting both of them.

Eating is not limited by the amount of
spaghetti left: assume an infinite supply.

The problem is how to design a discipline of
behavior (a concurrent algorithm) such that
each philosopher won't starve; i.e., can
forever continue to alternate between eating
and thinking assuming that any philosopher
cannot know when others may want to eat or
think.
The problem was designed to illustrate the
problem of avoiding deadlock.
 To see that designing a proper solution to this
problem isn't obvious, instruct each philosopher
to behave as follows:

 think until the left fork is available; when it is, pick it





up;
think until the right fork is available; when it is, pick it
up;
when both forks are held, eat for a fixed amount of
time;
then, put the right fork down;
then, put the left fork down;
repeat from the beginning.
This attempt at a solution fails: it allows the
system to reach a deadlock state.
 This is the state in which each philosopher
has picked up the fork to the left, waiting for
the fork to the right to be put down. With the
given instructions, this state can be reached,
and when it is reached, the philosophers will
eternally wait for each other to release a fork.

Resource starvation might also occur
independently of deadlock if a particular
philosopher is unable to acquire both forks
because of a timing problem.
 For example there might be a rule that the
philosophers put down a fork after waiting
ten minutes for the other fork to become
available and wait a further ten minutes
before making their next attempt.

This scheme eliminates the possibility of
deadlock, but still suffers from the problem of
livelock.
 If all five philosophers appear in the dining
room at exactly the same time and each
picks up the left fork at the same time the
philosophers will wait ten minutes until they
all put their forks down and then wait a
further ten minutes before they all pick them
up again

The various kinds of failures these
philosophers may experience are analogous
to the difficulties that arise in real computer
programming when multiple programs need
exclusive access to shared resources.
 These issues are studied in the branch of
Concurrent Programming. The original
problems of Dijkstra were related to external
devices like tape drives.

However, the difficulties studied in the Dining
Philosophers problem arise far more often
when multiple processes access sets of data
that are being updated.
 Systems that must deal with a large number
of parallel processes, such as operating
system kernels, use thousands of locks and
synchronizations
that
require
strict
adherence to methods and protocols if such
problems as deadlock, starvation, or data
corruption are to be avoided.



Now, the philosophers basically go
through the following steps.
while(1)
{
think for a random number of seconds
pickup(p);
eat for a random number of seconds
putdown(p);
}





p is the philosopher's Phil_struct.
The pickup() call is timed and this time is added to the
total blocked time for each thread.
Each solution to this problem must implement
initialize_v(), pickup() and putdown() to manage the
chopsticks.
pickup() and putdown() should be written so that no
philosopher starves (i.e. wants to eat, but never gets a
chopstick), and so that deadlock doesn't occur (a subset
of the above, because it would mean that all
philosophers starve...)
It should also attempt to try to minimize the amount of
time that the philosopher's spend waiting for chopsticks.
IPC: Semaphores
Semaphores are a programming construct
designed by E. W. Dijkstra in the late 1960s.
 Dijkstra's model was the operation of railroads:

 Consider a stretch of railroad in which there is a
single track over which only one train at a time is
allowed. Guarding this track is a semaphore.
 A train must wait before entering the single track until
the semaphore is in a state that permits travel. When
the train enters the track, the semaphore changes
state to prevent other trains from entering the track. A
train that is leaving this section of track must again
change the state of the semaphore to allow another
train to enter.
In the computer version, a semaphore appears
to be a simple integer. A process (or a thread)
waits for permission to proceed by waiting for
the integer to become 0. The signal if it
proceeds signals that this by performing
incrementing the integer by 1. When it is
finished, the process changes the semaphore's
value by subtracting one from it.
Algorithm
Step 1: Initialize number of forks N=5, a
semaphore
array S[N] , left[N+n]%N,
right=n%N
Step 2:while i less than N do
.
i) Create five semaphore with value 1
Step 3:i=0
Step 4: while i less than N do
i) Create a thread with argument I,
namely
philo
ii) Increment i
Step 5: End While
Step 6:In the thread Philo do
i)Call the think function with argument
ii)Wait till it obtain the left and right semaphore as
value 1
iii)call the cat function
iv)Release left and right semaphore
Step 7: End the thread
Step 8:In think function do
i)Display “philosopher i is thinking
Step 9:End function
Step 10:In eat function do
i)display “philosopher I is eating”
Step 11:End Function
Step 12:Stop
Important Functions Used
sem_init
 sem_post
 sem_wait
 sem_destroy
 pthread_create

sem_init

sem_init()
 Initialize an unnamed semaphore

Synopsis:
#include <semaphore.h>
int sem_init( sem_t * sem, int pshared,
unsigned value );

Sem
 A pointer to the sem_t object for the semaphore
that you want to initialize.

pshared
 Nonzero if you want the semaphore to be shared
between processes via shared memory.

value
 The initial value of the semaphore. A positive
value (i.e. greater than zero) indicates an
unlocked semaphore, and a value of 0 (zero)
indicates a locked semaphore. This value must
not exceed SEM_VALUE_MAX.

Library:
 libc
○ Use the -l c option to gcc to link against this
library.
○ This library is usually included automatically.
You can use the initialized semaphore in
subsequent calls to sem_wait(), sem_trywait(),
sem_post(), and sem_destroy().
 An initialized semaphore is valid until it's
destroyed by the sem_destroy() function, or until
the memory where the semaphore resides is
released.
 If the pshared argument is nonzero, then the
semaphore can be shared between processes
via shared memory.
 Any process can then use sem with the
sem_wait(), sem_trywait(), sem_post() and
sem_destroy() functions.

Return Value

0
 Success.
 The semaphore referred to by sem is
initialized.

-1
 An error occurred (errno is set).
sem_post()
Increment a named or unnamed
semaphore
 Synopsis :

#include <semaphore.h>
int sem_post( sem_t * sem );

sem
 A pointer to the sem_t object for the
semaphore whose value you want to
increment.



The sem_post() function increments the semaphore
referenced by the sem argument. If any processes
are currently blocked waiting for the semaphore,
then one of these processes will return successfully
from its call to sem_wait.
The process to be unblocked is determined in
accordance with the scheduling policies in effect for
the blocked processes. The highest priority waiting
process is unblocked, and if there is more than one
highest priority process blocked waiting for the
semaphore, then the highest priority process that
has been waiting the longest is unblocked.
The sem_post() function is reentrant with respect to
signals, and can be called from a signal handler.
Return Value

0
 Success.

-1
 An error occurred (errno is set).
sem_wait()
Wait on a named or unnamed
semaphore
Synopsis:

#include <semaphore.h>
int sem_wait( sem_t * sem );

sem
 A pointer to the sem_t object for the
semaphore that you want to wait on.
The sem_wait() function decrements the
semaphore referred to by the sem argument.
If the semaphore value is not greater than
zero, then the calling process blocks until it
can decrement the counter, or the call is
interrupted by signal.
 Some process should eventually call
sem_post() to increment the semaphore.

Return Value

0
 The semaphore was successfully
decremented.

-1
 The state of the semaphore is unchanged
(errno is set).
sem_destroy()
Destroy a semaphore
Synopsis:

#include <semaphore.h>
int sem_destroy( sem_t * sem );

sem
 A pointer to the sem_t object for the
semaphore that you want to destroy.
The sem_destroy() function destroys the
unnamed semaphore referred to by the sem
argument. The semaphore must have been
previously initialized by the sem_init()
function.
 The effect of using a semaphore after it has
been destroyed is undefined. If you destroy a
semaphore that other processes are
currently blocked on, they're unblocked, with
an error (EINVAL).

Return Value

0
 Success.

-1
 An error occurred (errno is set).