This section explains how to use the Thread Analyzer to investigate the deadlocks in the dining philosopher program. We'll start by executing runs that result in actual deadlocks and then examine runs that terminate normally but have the potential for deadlocks.
The following listing shows a run of the dining philosophers program that results in an actual deadlock.
prompt% cc din_philo.c -mt -g prompt% collect -r deadlock a.out Creating experiment database tha.1.er ... Philosopher 1 is done thinking and now ready to eat. Philosopher 2 is done thinking and now ready to eat. Philosopher 3 is done thinking and now ready to eat. Philosopher 0 is done thinking and now ready to eat. Philosopher 1: got right chopstick 1 Philosopher 3: got right chopstick 3 Philosopher 0: got right chopstick 0 Philosopher 1: got left chopstick 2 Philosopher 3: got left chopstick 4 Philosopher 4 is done thinking and now ready to eat. Philosopher 1: eating. Philosopher 3: eating. Philosopher 3: got right chopstick 3 Philosopher 4: got right chopstick 4 Philosopher 2: got right chopstick 2 Philosopher 0: got left chopstick 1 Philosopher 0: eating. Philosopher 1: got right chopstick 1 Philosopher 4: got left chopstick 0 Philosopher 4: eating. Philosopher 0: got right chopstick 0 Philosopher 3: got left chopstick 4 Philosopher 3: eating. Philosopher 4: got right chopstick 4 Philosopher 2: got left chopstick 3 Philosopher 2: eating. Philosopher 3: got right chopstick 3 Philosopher 1: got left chopstick 2 Philosopher 1: eating. Philosopher 2: got right chopstick 2 Philosopher 0: got left chopstick 1 Philosopher 0: eating. Philosopher 1: got right chopstick 1 Philosopher 4: got left chopstick 0 Philosopher 4: eating. Philosopher 0: got right chopstick 0 Philosopher 3: got left chopstick 4 Philosopher 3: eating. Philosopher 4: got right chopstick 4 Philosopher 2: got left chopstick 3 Philosopher 2: eating. Philosopher 3: got right chopstick 3 Philosopher 1: got left chopstick 2 Philosopher 1: eating. Philosopher 2: got right chopstick 2 Philosopher 0: got left chopstick 1 Philosopher 0: eating. Philosopher 1: got right chopstick 1 Philosopher 4: got left chopstick 0 Philosopher 4: eating. Philosopher 0: got right chopstick 0 Philosopher 3: got left chopstick 4 Philosopher 3: eating. Philosopher 4: got right chopstick 4 Philosopher 2: got left chopstick 3 Philosopher 2: eating. Philosopher 2: got right chopstick 2 Philosopher 3: got right chopstick 3 (hang) Execution terminated by pressing CTRL-C % er_print tha.1.er (er_print) deadlocks Deadlock #1, Potential deadlock Thread #2 Lock being held: 0x215a8, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x215c0, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Thread #3 Lock being held: 0x215c0, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x215d8, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Thread #4 Lock being held: 0x215d8, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x215f0, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Thread #5 Lock being held: 0x215f0, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x21608, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Thread #6 Lock being held: 0x21608, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x215a8, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Deadlock #2, Actual deadlock Thread #2 Lock being held: 0x215a8, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x215c0, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Thread #3 Lock being held: 0x215c0, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x215d8, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Thread #4 Lock being held: 0x215d8, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x215f0, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Thread #5 Lock being held: 0x215f0, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x21608, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Thread #6 Lock being held: 0x21608, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x215a8, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Deadlocks List Summary: Experiment: tha.1.er Total Deadlocks: 2 (er_print)
The following screen-shot shows the Thread Analyzer's presentation of the deadlock information:
The Thread Analyzer reports two deadlocks for din_philo.c, one potential and the other actual. On closer inspection, we find that the two deadlocks are identical. The circular chain involved in the deadlock is as follows:
Thread 2: holds lock at address |
Thread 3: holds lock at address |
Thread 4: holds lock at address |
Thread 5: holds lock at address |
Thread 6: holds lock at address |
Select the first thread in the chain (Thread #2) and then click on the
Dual Source tab to see where in the source code Thread #2 held the lock at
address 0x215a8
, and where in the source code it
requested the lock at address 0x215c0
. The following
screen-shot shows the Dual Source tab for thread number two. The default metric
(Exclusive Deadlocks metric) is shown to the left of each source line. This
metric gives a count of the number of times a lock-hold or lock-request operation,
which was involved in a deadlock, was reported on that line.
The dining philosophers program can avoid actual deadlock and terminate
normally if you supply a large enough sleep argument. Normal termination,
however, does not mean the program is safe from deadlocks. It simply means
that the locks held and requested did not form a deadlock chain during a given
run. If the timing changes in other runs, an actual deadlock can occur. The
following listing shows a run of the dining philosophers program that terminates
normally. However, the er_print
utility and the
Thread Analyzer report potential deadlocks.
% cc din_philo.c -mt -g % collect -r deadlock a.out 40 Creating experiment database tha.2.er ... Philosopher 0 is done thinking and now ready to eat. Philosopher 2 is done thinking and now ready to eat. Philosopher 1 is done thinking and now ready to eat. Philosopher 3 is done thinking and now ready to eat. Philosopher 2: got right chopstick 2 Philosopher 3: got right chopstick 3 Philosopher 0: got right chopstick 0 Philosopher 4 is done thinking and now ready to eat. Philosopher 0: got left chopstick 1 Philosopher 0: eating. Philosopher 3: got left chopstick 4 Philosopher 3: eating. Philosopher 0: got right chopstick 0 Philosopher 4: got right chopstick 4 Philosopher 2: got left chopstick 3 Philosopher 2: eating. Philosopher 0: got left chopstick 1 Philosopher 0: eating. Philosopher 3: got right chopstick 3 Philosopher 2: got right chopstick 2 Philosopher 4: got left chopstick 0 Philosopher 4: eating. Philosopher 0: got right chopstick 0 Philosopher 3: got left chopstick 4 Philosopher 3: eating. Philosopher 0: got left chopstick 1 Philosopher 0: eating. Philosopher 4: got right chopstick 4 Philosopher 2: got left chopstick 3 Philosopher 2: eating. Philosopher 4: got left chopstick 0 Philosopher 4: eating. Philosopher 3: got right chopstick 3 Philosopher 2: got right chopstick 2 Philosopher 0: got right chopstick 0 Philosopher 3: got left chopstick 4 Philosopher 3: eating. Philosopher 0: got left chopstick 1 Philosopher 0: eating. Philosopher 0: got right chopstick 0 Philosopher 2: got left chopstick 3 Philosopher 2: eating. ... Philosopher 0: got left chopstick 1 Philosopher 0: eating. Philosopher 4: got right chopstick 4 Philosopher 3: got right chopstick 3 Philosopher 4: got left chopstick 0 Philosopher 4: eating. Philosopher 0: got right chopstick 0 Philosopher 3: got left chopstick 4 Philosopher 0: got left chopstick 1 Philosopher 0: eating. Philosopher 3: eating. Philosopher 0: got right chopstick 0 Philosopher 2: got left chopstick 3 Philosopher 2: eating. Philosopher 0: got left chopstick 1 Philosopher 0: eating. Philosopher 4: got right chopstick 4 Philosopher 3: got right chopstick 3 Philosopher 2: got right chopstick 2 Philosopher 4: got left chopstick 0 Philosopher 4: eating. Philosopher 4 is done eating. Philosopher 3: got left chopstick 4 Philosopher 3: eating. Philosopher 0: got right chopstick 0 Philosopher 0: got left chopstick 1 Philosopher 0: eating. Philosopher 3 is done eating. Philosopher 2: got left chopstick 3 Philosopher 2: eating. Philosopher 0 is done eating. Philosopher 2 is done eating. Philosopher 1: got right chopstick 1 Philosopher 1: got left chopstick 2 Philosopher 1: eating. Philosopher 1 is done eating. % Execution terminated normally % er_print tha.2.er (er_print) deadlocks Deadlock #1, Potential deadlock Thread #2 Lock being held: 0x215a8, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x215c0, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Thread #3 Lock being held: 0x215c0, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x215d8, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Thread #4 Lock being held: 0x215d8, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x215f0, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Thread #5 Lock being held: 0x215f0, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x21608, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Thread #6 Lock being held: 0x21608, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Lock being requested: 0x215a8, at: grab_chopstick + 0x0000002C, line 101 in "din_philo.c" Deadlocks List Summary: Experiment: tha.2.er Total Deadlocks: 1 (er_print)
The following screen-shot shows the potential deadlock information in the Thread Analyzer interface: