Sun Studio 12: Thread Analyzer User's Guide

3.1 The Dining Philosophers Source File

The sample program which simulates the dining-philosophers problem is a C program that uses POSIX threads. The source file is called din_philo.c. The program can exhibit both potential and actual deadlocks. Here is the listing of the code which is followed by an explanation:

/* din_philo.c */    
     1  #include <pthread.h>
     2  #include <stdio.h>
     3  #include <unistd.h>
     4  #include <stdlib.h>
     5  #include <errno.h>
     6  #include <assert.h>
     7
     8  #define PHILOS 5
     9  #define DELAY 5000
    10  #define FOOD 50
    11
    12	void *philosopher (void *id);
    13	void grab_chopstick (int,
    14	                     int,
    15	                     char *);
    16	void down_chopsticks (int,
    17	                      int);
    18	int food_on_table ();
    19	
    20	pthread_mutex_t chopstick[PHILOS];
    21	pthread_t philo[PHILOS];
    22	pthread_mutex_t food_lock;
    23	int sleep_seconds = 0;
    24	
    25	
    26	int
    27	main (int argn,
    28	      char **argv)
    29	{
    30	    int i;
    31	
    32	    if (argn == 2)
    33	        sleep_seconds = atoi (argv[1]);
    34	
    35	    pthread_mutex_init (&food_lock, NULL);
    36	    for (i = 0; i < PHILOS; i++)
    37	        pthread_mutex_init (&chopstick[i], NULL);
    38	    for (i = 0; i < PHILOS; i++)
    39	        pthread_create (&philo[i], NULL, philosopher, (void *)i);
    40	    for (i = 0; i < PHILOS; i++)
    41	        pthread_join (philo[i], NULL);
    42	    return 0;
    43	}
    44	
    45	void *
    46	philosopher (void *num)
    47	{
    48	    int id;
    49	    int i, left_chopstick, right_chopstick, f;
    50	
    51	    id = (int)num;
    52	    printf ("Philosopher %d is done thinking and now ready to eat.\n", id);
    53	    right_chopstick = id;
    54	    left_chopstick = id + 1;
    55	
    56	    /* Wrap around the chopsticks. */
    57	    if (left_chopstick == PHILOS)
    58	        left_chopstick = 0;
    59	
    60	    while (f = food_on_table ()) {
    61	
    62	        /* Thanks to philosophers #1 who would like to take a nap
    63	         * before picking up the chopsticks, the other philosophers
    64	         * may be able to eat their dishes and not deadlock.  
    65	         */
    66	        if (id == 1)
    67	            sleep (sleep_seconds);
    68	
    69	        grab_chopstick (id, right_chopstick, "right ");
    70	        grab_chopstick (id, left_chopstick, "left");
    71	
    72	        printf ("Philosopher %d: eating.\n", id);
    73	        usleep (DELAY * (FOOD - f + 1));
    74	        down_chopsticks (left_chopstick, right_chopstick);
    75	    }
    76	
    77	    printf ("Philosopher %d is done eating.\n", id);
    78	    return (NULL);
    79	}
    80	
    81	int
    82	food_on_table ()
    83	{
    84	    static int food = FOOD;
    85	    int myfood;
    86	
    87	    pthread_mutex_lock (&food_lock);
    88	    if (food > 0) {
    89	        food--;
    90	    }
    91	    myfood = food;
    92	    pthread_mutex_unlock (&food_lock);
    93	    return myfood;
    94	}
    95	
    96	void
    97	grab_chopstick (int phil,
    98	                int c,
    99	                char *hand)
   100	{
   101	    pthread_mutex_lock (&chopstick[c]);
   102	    printf ("Philosopher %d: got %s chopstick %d\n", phil, hand, c);
   103	}
   104	
   105	void
   106	down_chopsticks (int c1,
   107	                 int c2)
   108	{
   109	    pthread_mutex_unlock (&chopstick[c1]);
   110	    pthread_mutex_unlock (&chopstick[c2]);
   111	}