JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Oracle Solaris Studio 12.2: Thread Analyzer User's Guide
search filter icon
search icon

Document Information

Preface

1.  What is the Thread Analyzer and What Does It Do?

2.  The Data Race Tutorial

3.  The Deadlock Tutorial

3.1 About Deadlocks

3.2 Getting the Deadlock Tutorial Source Files

3.2.1 Source Code Listing for din_philo.c

3.3 The Dining Philosophers Scenario

3.3.1 How the Philosophers Can Deadlock

3.3.2 Introducing a Sleep Time for Philosopher One

3.4 How to Use the Thread Analyzer to Find Deadlocks

3.4.1 Compile the Source Code

3.4.2 Create a Deadlock Detection Experiment

3.4.3 Examine the Deadlock Detection Experiment

3.4.3.1 Using Thread Analyzer to View the Deadlock Detection Experiment

3.4.3.2 Using er_print to View the Deadlock Detection Experiment

3.5 Understanding the Deadlock Experiment Results

3.5.1 Examining Runs That Deadlock

3.5.2 Examining Runs That Complete Despite Deadlock Potential

3.6 Fixing the Deadlocks and Understanding False Positives

3.6.1 Regulating the Philosophers With Tokens

3.6.1.1 A False Positive Report

3.6.2 An Alternative System of Tokens

A.  APIs Recognized by the Thread Analyzer

B.  Useful Tips

3.2 Getting the Deadlock Tutorial Source Files

The din_philo.c source file used in this tutorial is located in the directory /opt/solstudio12.2/prod/examples/tha/din_philo on Oracle Solaris systems, or /opt/oracle/solstudio12.2/prod/examples/tha/din_philo on Linux systems. The example directory includes a Makefile and a DEMO file of instructions, but this tutorial does not follow those instructions or use the Makefile. Instead, the tutorial instructs you to execute commands individually.

To follow the tutorial, you can copy the din_philo.c file from the examples directory to a different directory, or you can create your own file and copy the code from the following code listing.

The din_philo.c sample program which simulates the dining-philosophers problem is a C program that uses POSIX threads. The program can exhibit both potential and actual deadlocks.

3.2.1 Source Code Listing for din_philo.c

The source code for din_philo.c is shown below:

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