Go to main content
Oracle® Developer Studio 12.5: Thread Analyzer User's Guide

Exit Print View

Updated: June 2016
 
 

Thread Analyzer Usage Model

The following steps show the process by which you can troubleshoot your multithreaded program with Thread Analyzer.

  1. Instrument the program, if doing data race detection.

  2. Create a data-race-detection or deadlock-detection experiment.

  3. Examine the experiment result and establish whether the multithreaded programming issues revealed by Thread Analyzer are legitimate bugs or benign phenomena.

  4. Fix the legitimate bugs and create additional experiments (step 2 above) with varied factors such as different input data, a different number of threads, varied loop schedules or even different hardware. This repetition helps locate non-deterministic problems.

Steps 1 through 3 above are described in the following sections.

Usage Model for Detecting Data Races

You must perform three steps to detect data races:

  1. Instrument the code to enable data race detection

  2. Create an experiment on the instrumented code

  3. Examine the experiment for data races

Instrument the Code for Data Race Detection

To enable data race detection in an application, the code must first be instrumented to monitor memory accesses at runtime, meaning calls to the runtime support library libtha.somust be inserted in the code to monitor memory accesses at runtime and determine whether there are any data races.

You can instrument your code at the application source-level during compilation, or at the application binary-level by running an additional tool on the binary.

Source-level instrumentation is done by the compiler when you use a special option. You can also specify the optimization level and other compiler options to use. Source-level instrumentation can result in faster runtime since the compiler can do some analysis and instrument fewer memory accesses.

Binary-level instrumentation is useful when the source code is not available. You might also use binary instrumentation if you have the source code, but cannot compile shared libraries that are used by the application. Binary instrumentation using the discover tool instruments the binary as well as all shared libraries as they are opened.

Source-level Instrumentation

To instrument at the source level, compile the source code with the special compiler option:

-xinstrument=datarace

With this compiler option, the code generated by the compiler will be instrumented for data race detection.

The –g compiler option should also be used when building application binaries. This option causes extra data to be generated which enables Thread Analyzer to display source code and line number information when reporting data races.

Binary-level Instrumentation

To instrument at the binary level, you must use the discover tool. If the binary is named a.out, you can create an instrumented binary a.outi by executing:

discover -i datarace -o a.outi a.out

The discover tool automatically instruments all shared libraries as they are opened, whether they are statically linked in the program or opened dynamically by dlopen(). By default, instrumented copies of libraries are cached in the directory $HOME/SUNW_Bit_Cache.

Some useful discover command line options are shown below. See the discover(1) man page for details.

-o file

Output the instrumented binary to the specified file name

-N lib

Do not instrument the specified library

-T

Do not instrument any libraries

-D dir

Change the cache directory to dir

Create an Experiment on the Instrumented Application

To create a data-race-detection experiment, use the collect command with the –r race flag to run the application and collect experiment data during the execution of the process. When you use the –r race option, the collected data includes pairs of data accesses that constitute a race.

Examine the Experiment for Data Races

You can examine the data-race-detection experiment with the tha command, which starts the Thread Analyzer graphical user interface. You can also use the er_print command-line interface.

Usage Model for Detecting Deadlocks

Two steps are involved in detecting deadlocks:

  1. Create a deadlock-detection experiment.

  2. Examine the experiment for deadlocks.

Create an Experiment for Detecting Deadlocks

To create a deadlock-detection experiment, use the collect command with the –r deadlock flag to run the application and collect experiment data during the execution of the process. When you use the –r deadlock option, the collected data includes lock holds and lock requests that form a circular chain.

Examine the Experiment for Deadlocks

You can examine the deadlock-detection experiment with the tha command, which starts the Thread Analyzer graphical user interface. You can also use the er_print command-line interface.

Usage Model for Detecting Data Races and Deadlocks

If you want to detect data races and deadlocks at the same time, follow the three steps in Usage Model for Detecting Data Races for detecting data races, but use the collect command with the –r race,deadlock flag to run the application. The experiment will contain both race-detection and deadlock-detection data.