Oracle Solaris Studio 12.4 Man Pages

Exit Print View

Updated: January 2015
 
 

tha(1)

Name

tha - GUI for analyzing a Thread Analyzer experiment

Synopsis

tha [ options ] [ thread-analyzer-experiment ]

Description

The tha command invokes a GUI for analyzing the various Thread Analyzer experiments collected by the Collector using the collect (1) command. The GUI is a version of the Performance Analyzer customized for examining Thread Analyzer experiments.

The Collector gathers thread analysis information to create a Thread Analyzer experiment during the execution of a process. The tha command reads in such an experiment and displays any errors detected. The current Thread Analyzer supports data race detection and deadlock detection. For further information on those, see the sections "DATA RACE DETECTION" and "DEADLOCK DETECTION" below.

A command-line version of the tha command is available as the er_print(1) utility.

To start tha, type the following on the command line:

tha [thread-analyzer-experiment]

Both the tha command and the analyzer(1) command can be used to read a Thread Analyzer experiment. The tha command has the same functionality and features as the analyzer command, but shows a simplified set of default tabs that pertain to Thread Analyzer experiments.

Options

-j | --jdkhome jvmpath

Specify the path to the Java[TM] virtual machine (JVM) software for running the analyzer. The default path is taken first by examining environment variables for a path to the JVM, in the order JDK_HOME, and then JAVA_PATH. If neither environment variable is set, the default path is where the Java[TM] 2 Platform, Standard Edition technology was installed with the Oracle Solaris Studio release, and if it was not installed, as set in the user's PATH. (The terms "Java virtual machine" and "JVM" mean a virtual machine for the Java(TM) platform.)

-J jvm-option

Specify JVM(TM) software options.

-f | --fontsize size

Specify the font size to be used in the analyzer.

-v | --verbose

Print version information and Java runtime arguments before starting.

-V | --version

Print version information and exit.

-? | -h| --help

Print usage information and exit.

THA WINDOW -- LEFT HAND TABS

The tha window has a menu bar, a tool bar, and a split pane that contains tabs for the various displays.

The left-hand pane contains tabs for the principal displays. The tabs that are actually present in the pane are controlled by a rtabs directive in a .er.rc file. The Experiments tab is always shown. The Races tab will be shown if data race data is in one or more of the loaded experiments. The Deadlocks tab will be shown if deadlock data is in one or more of the loaded experiments. The Dual Source tab will be shown if either the Races or Deadlocks tabs are shown.

By default, the Races tab is selected, if available. If it is not available, the Deadlocks tab is selected, if it is available. If neither is available, only the Experiments tab will be visible.

The Races Tab

The Races tab is shown if data for data races is in one or more of the experiments loaded. The tab presents the list of data races detected in the application. By default, the first data race in the list of data races is selected.

For each data race, the following information is shown:

  • A unique id that identifies the data race.

  • One or more virtual addresses (Vaddr) associated with the data race. If the data race occurs on multiple virtual addresses, then "(Multiple Addresses)" is shown instead of a single address.

  • The two accesses by two different threads that constitute the data race. For each access, the type of the access (Read or Write) is shown, as well as the function, offset, and line number in the source code where the access occurred.

  • The total number of traces associated with the data race. The individual traces can be displayed by clicking on the button to the left of the "Total Traces" label.

    Each trace refers to the pair of thread callstacks at the time the two data race accesses occurred. When a trace is selected, the two callstacks will be displayed in the Race Details tab in the right-hand pane of the tha window (see below). The frame at the top of the callstack for the first access is selected by default.

The Deadlocks Tab

The Deadlocks tab is shown if deadlock data is in one or more of the experiments loaded. The tab presents the list of deadlocks detected in the application. By default the first deadlock in the list of deadlocks is selected.

For each deadlock, the following information is shown:

  • A unique id that identifies the deadlock.

  • The type of the deadlock (potential or actual).

  • The total number of threads involved in the deadlock.

The context of each thread can be displayed by clicking on the button to the left of the "Total Threads" label. Each thread context shows the two operations corresponding to holding a first lock and deadlocking attempting to acquire a second lock.

When a thread context is selected, the two callstacks where the lock hold and lock request took place will be displayed in the Deadlock Details tab in the right-hand pane of the tha window (see below).

The Dual Source Tab

The Dual Source tab is shown if either data race or deadlock data is in one or more of the experiments loaded. The Dual Source tab shows the two source locations pertaining to the selected data race or deadlock.

For a selected data race, the Dual Source tab shows the source locations for the two accesses of the data race selected, as shown in the Race Details tab. For a selected deadlock, the Dual Source tab shows the two operations corresponding to holding a first lock and deadlocking attempting to acquire a second lock by the thread selected, as shown in the Deadlock Details tab.

The source line where the access occurred will appear highlighted. If the source code was compiled with -g, then compiler commentary may appear interleaved in the source code.

To the left of each source line, metrics that relate to that source line are shown. For data races, the default metric shown is the Exclusive Race Accesses metric; this metric gives a count of the number of times a data race access was reported on that line. For deadlocks, the default metric shown is the Exclusive Deadlocks metric; 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.

Exclusive metrics relate to the source line at which they appear only. Inclusive metrics relate to the source line at which they appear and to any functions that have been called from that source line. Count metrics are shown as an integer count. Percentages are shown to a precision of 0.01%. Because of rounding, percentages may not sum to exactly 100%.

The metrics that are shown can be changed using the Set Data Presentation dialog box (see "Selecting the Data Presentation Options" below).

To reorder the columns of metrics in the source display, drag the column header to the place you want it to appear.

The Experiments Tab

The Experiments tab is divided into two panels. The top panel shows a tree that contains nodes for the load objects in the experiment loaded. The bottom panel lists error and warning messages from the tha session.

For more information about the Experiments tab, refer to the analyzer(1) man page.

THA WINDOW -- RIGHT HAND TABS

The right-hand pane of the tha window contains tabs for displaying additional information about a data race. The Summary tab is always shown. The Race Details tab is shown if the Races tab is shown; the Deadlock Details tab is shown if the Deadlocks tab is shown.

The Summary Tab

The Summary tab shows summary information about a data race selected from the Races tab. This information includes the object file name, source file name, and PC (program counter) address.

The Race Details Tab

The Race Details tab is selected whenever the Races tab is raised, and a selection made from the Races tab. It shows detailed information about a data race or trace selected from the Races tab.

The Race Details tab is divided into two panes. The upper pane shows information about the first access of a selected data race or trace (Access 1). The lower pane shows information about the second access of a selected data race or trace (Access 2).

When a data race or a trace is selected from the Races tab, the Race Details tab shows the following:

  • The data race or trace id

  • The virtual address (Vaddr) associated with the data race. If the data race occurs on multiple virtual addresses, then "(Multiple Addresses)" is shown instead of a single address.

In addition, for each of the two accesses, the Race Details tab shows the following:

  • Whether the data race access is read or write

  • If a data race from the Races tab is selected, then the Race Details tab shows the leaf PC of the thread when the data race access occurred. If, on the other hand, a trace from the Races tab is selected, then the Race Details tab shows the callstack of the thread when the data race access occurred. By default, the frame at the top of the callstack is selected.

The Deadlock Details Tab

The Deadlock Details tab is selected whenever the Deadlocks tab is raised, and a selection made from the Deadlocks Tab. It shows detailed information about a thread context selected from the Deadlocks tab.

For each thread context selected, the deadlock id, deadlock type, and thread id are shown. In addition, for each of the two lock operations involved, the type of lock operation (lock being held or lock being requested) and the callstacks of the thread are shown. By default, the frame at the top of each callstack is selected.

DATA RACE DETECTION

A data race occurs when two or more threads in a single process access the same memory location concurrently, at least one of the accesses is for writing, and the threads are not using any exclusive locks to control their accesses to that memory. In such situations, the order of accesses is non-deterministic, and the computation may give different results depending on that order. Some data races may be benign (for example, when the memory access is used for a busy-wait), but many data races are bugs in the program.

Data-race-detection experiments record data races that are detected during the execution of a multithreaded process. Data race detection works on multithreaded applications written using POSIX thread APIs, Solaris thread APIs, OpenMP, or a mix of the above.

There are three steps involved in detecting data races:

Step 1: Instrument the code

To enable data race detection in an application, the code must first be instrumented to monitor memory accesses at runtime. The instrumentation can be done at the application source-level or binary-level.

If doing source-level instrumentation, the source code of the application should be compiled with the special compiler option:

-xinstrument=datarace

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

If doing binary-level instrumentation, the application binary should be instrumented using the Discover tool which is invoked by the discover(1) command. If the binary is named a.out, then an instrumented binary a.outi can be generated 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(). You can use the discover command line option -N to ignore certain libraries, or use the discover command line option -T to ignore all libraries.

To use the Discover tool, the input binary must be compiled with optimization flag -O[n] (n>=0) using Solaris Studio 12 Update 1 compilers or later versions, on a machine with Oracle Solaris 10 update 5 or higher, or Oracle Solaris 11. On older Solaris versions, try the -xbinopt=prepare compiler option (SPARC only).

For both source-level and binary-level instrumentation, it is recommended that the -g compiler option be used when building application binaries. This will allow tha to display source code and line number information when reporting data races.

Step 2: Create a data-race-detection experiment

Use the collect command with the -r race flag to run the application and create a data-race-detection experiment during the execution of the process.

Data-race-detection data collected consists of pairs of data-accesses that constitute a race. Data-race-detection data is converted into the "Race Accesses" metric.

See collect(1) man page for more information.

Step 3: Examine the data-race-detection experiment

A data-race-detection experiment can be examined with either the tha or analyzer command (GUI), or with the er_print utility (command-line).

Both the tha and the analyzer commands present a GUI interface; the former presents a simplified set of default tabs, but is otherwise identical to the analyzer. The er_print utility, on the other hand, presents a command-line interface.

Note: The Thread Analyzer may report false positive data races if it does not recognize user-defined synchronizations in the application. The Thread Analyzer runtime library, libtha.so, provides an API that can be used to notify the Thread Analyzer about user-defined synchronizations and reduce the number of false positives reported. See libtha(3) man page for more information.

DEADLOCK DETECTION

Deadlock describes a condition where two or more threads are blocked (hung) forever, waiting for each other. There are many causes of deadlocks; these include erroneous program logic, inappropriate use of synchronizations and barriers, and so on.

The Thread Analyzer detects deadlocks that are caused by inappropriate use of mutual exclusion locks. This kind of deadlock is commonly encountered in multi-threaded applications. Suppose we have a process with two or more threads. A deadlock caused by inappropriate use of mutual exclusion locks occurs when the following three conditions hold:

  1. Threads already holding locks request new locks,

  2. The requests are made concurrently, and

  3. Two or more threads form a circular chain where each thread waits for a lock that the next thread in the chain holds.

Here is an example of a deadlock condition:

Thread 1:  holds lock A, requests lock B
Thread 2:  holds lock B, requests lock A

A deadlock in a particular run of the program can be a potential deadlock or an actual deadlock. A potential deadlock is a deadlock that did not actually occur in the run of the program, but can occur in other runs of the program, depending on the scheduling of threads and the timings of requests for locks by the threads. An actual deadlock is a deadlock that actually occurred in the run of the program. An actual deadlock causes the threads involved to hang, but may or may not cause the whole process to hang.

Deadlock-detection experiments record both potential and actual deadlocks that are detected during the execution of a multi-threaded process. Deadlock detection works on multi-threaded applications written using POSIX thread APIs, Solaris thread APIs, OpenMP, or a mix of the above.

There are two steps involved in detecting deadlocks:

Step 1: Create a deadlock-detection experiment

Use the collect command with the -r deadlock flag to run the application and create a deadlock-detection experiment during the execution of the process.

Deadlock-detection data collected consists of lock holds and lock requests that form a circular chain. Deadlock-detection data is converted into the "Deadlocks" metric.

See collect(1) man page for more information.

Step 2: Examine the deadlock-detection experiment

A deadlock-detection experiment can be examined with either the tha or analyzer command (GUI), or with the er_print utility (command-line).

Both the tha and the analyzer commands present a GUI interface; the former presents a simplified set of default tabs, but is otherwise identical to the analyzer. The er_print utility, on the other hand, presents a command-line interface.

It is recommended that the -g compiler option be used when building application binaries. This will allow tha to display source code and line number information when reporting deadlocks.

SELECTING DATA PRESENTATION OPTIONS

You can control the presentation of data from the Set Data Presentation dialog box. To open this dialog box, click on the Set Data Presentation button in the tool bar, or choose Set Data Presentation from the View menu.

The Set Data Presentation dialog box has a tabbed pane with seven tabs. Refer to the analyzer(1) man page for more information.

DEFAULTS

The Thread Analyzer processes directives from a .er.rc file in the current directory, if present; from a .er.rc file in the user's home directory, if present; and from a system er.rc file installed with the product.

These .er.rc files can contain default settings for which tabs are visible (rtabs), when the Thread Analyzer is brought up. The tabs are named by the er_print command for the corresponding report, except for the Experiments Tab, named headers, the Timeline Tab, named timeline, the Dual Source Tab, named dsrc, and the Source/Disassembly tab, named srcdis.

The .er.rc files can also contain default settings for metrics, sorting, and for specifying compiler commentary options and highlighting thresholds for source and disassembly output. The files also specify a path for C++ name demangling for other compilers, as well as default settings for the Timeline tab, and for name formatting, and setting View Mode (viewmode).

The .er.rc files can also contain a setting, en_desc {on|off} to control whether or not descendant experiments are selected and read when the founder experiment is read.

The .er.rc files can also contain directives to control the search path for source and object files. In the Thread Analyzer, an .er.rc file can be saved by clicking on the Save button in the Set Data Presentation dialog box, which you can open from the View menu. Saving an .er.rc file from the Set Data Presentation dialog box not only affects subsequent invocations of the Thread Analyzer, but also the er_print utility and er_src utility. See the description of these directives and files, and their processing, in the er_print(1) man page.

The Thread Analyzer puts a message into its Errors/Warning logs areas naming the user .er.rc files it processed, including any processing message generated when any tab is loaded.

See also

analyzer (1) , collect (1) , discover (1) , er_archive (1) , er_cp (1) , er_export (1) , er_mv (1) , er_print (1) , er_rm (1) , er_src (1) , tha (1) , libtha (3)

Thread Analyzer User's Guide

Performance Analyzer manual