JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Oracle Solaris Studio 12.3: Thread Analyzer User's Guide     Oracle Solaris Studio 12.3 Information Library
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 1

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

You can download the source files used in this tutorial from the samples download area of the Oracle Solaris Studio developer portal.

After you download and unpack the sample files, you can find the samples in the SolarisStudioSampleApplications/ThreadAnalyzer directory. The samples are located in the din_philo subdirectory. The din_philo directory includes a Makefile and a DEMO file of instructions, but this tutorial does not follow those instructions or use the Makefile. Instead, you are instructed to execute commands individually.

To follow the tutorial, you can copy the din_philo.c file from the SolarisStudioSampleApplications/ThreadAnalyzer/din_philo 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  }