Oracle Solaris Studio 12.4 Man Pages

Exit Print View

Updated: January 2015
 
 

libtha(3)

Name

libtha - API that can be used in conjunction with the Oracle Solaris Studio Thread Analyzer

Synopsis

C and C++ Version of the API

cc  [options  ]  file  -Linstall_path/lib -Rinstall_path/lib
     -ltha

CC [ options ] file -ltha

#include "tha_interface.h"

void tha_notify_acquire_lock (uintptr_t id);
void tha_notify_lock_acquired (uintptr_t id);
void tha_notify_acquire_writelock (uintptr_t id);
void tha_notify_writelock_acquired (uintptr_t id);
void tha_notify_acquire_readlock (uintptr_t id);
void tha_notify_readlock_acquired (uintptr_t id);
void tha_notify_release_lock (uintptr_t id);
void tha_notify_lock_released (uintptr_t id);
void tha_notify_sync_post_begin (uintptr_t id);
void tha_notify_sync_post_end (uintptr_t id);
void tha_notify_sync_wait_begin (uintptr_t id);
void tha_notify_sync_wait_end (uintptr_t id);
void tha_check_datarace_mem (uintptr_t  addr,  size_t  size,
     int onoff);
void tha_check_datarace_thr (int selfall, int onoff);

Fortran Version of the API

f95 [ options ] file -ltha

include "tha_finterface.h"

subroutine tha_notify_acquire_lock (id)
integer(kind=tha_sobj_kind) :: id

subroutine tha_notify_lock_acquired (id)
integer(kind=tha_sobj_kind) :: id

subroutine tha_notify_acquire_writelock (id)
integer(kind=tha_sobj_kind) :: id

subroutine tha_notify_writelock_acquired (id)
integer(kind=tha_sobj_kind) :: id

subroutine tha_notify_acquire_readlock (id)
integer(kind=tha_sobj_kind) :: id

subroutine tha_notify_readlock_acquired (id)
integer(kind=tha_sobj_kind) :: id

subroutine tha_notify_release_lock (id)
integer(kind=tha_sobj_kind) :: id

subroutine tha_notify_lock_released (id)
integer(kind=tha_sobj_kind) :: id

subroutine tha_notify_sync_post_begin (id)
integer(kind=tha_sobj_kind) :: id

subroutine tha_notify_sync_post_end (id)
integer(kind=tha_sobj_kind) :: id

subroutine tha_notify_sync_wait_begin (id)
integer(kind=tha_sobj_kind) :: id

subroutine tha_notify_sync_wait_end (id)
integer(kind=tha_sobj_kind) :: id

subroutine tha_check_datarace_mem (addr, mem_size, onoff)
integer(kind=tha_sobj_kind), intent(in) :: addr
integer(kind=4), intent(in) :: mem_size
integer(kind=4), intent(in) :: onoff

subroutine tha_check_datarace_thr (selfall, onoff)
integer(kind=4), intent(in) :: selfall
integer(kind=4), intent(in) :: onoff

Description

The shared object, libtha.so, provides an API that can be used in conjunction with the Oracle Solaris Studio Thread Analyzer. The API routines may be used to notify the Thread Analyzer about synchronizations, or to control data race detection.

Note that libtha.so provides only "hook" (or dummy) entry points for the API routines. This allows programs that call these routines and that are linked with libtha.so to run outside of a Thread Analyzer experiment, as well as inside such an experiment.

If the program is run outside a Thread Analyzer experiment (i.e., the program is neither run under collect -r race nor run under collect -r deadlock), then the API routines will not have any effect.

If the program is run under a Thread Analyzer experiment (i.e., the program is run under collect -r race or collect -r deadlock), then the routines have an effect.

See collect(1) for more information about performing a Thread Analyzer experiment.

libtha Synchronization Routines

The Thread Analyzer can recognize most standard synchronization APIs and constructs provided by OpenMP, POSIX threads, and Solaris threads. However, the tool cannot recognize roll-your-own style synchronizations, and may report false data races if such synchronizations are used. For example, the tool cannot recognize spin locking implemented using hand-coded assembly.

If your program includes roll-your-own style synchronizations, then you can insert calls to the libtha.so API in the program to inform the Thread Analyzer of those synchronizations. These calls allow the tool to recognize the synchronizations, thus reducing the number of false-positive data races reported.

The libtha.so API consists of the following synchronization routines:

tha_notify_acquire_lock(): This routine can be called immediately before the program tries to acquire a user-defined lock.

tha_notify_lock_acquired(): This routine can be called immediately after a user-defined lock has been acquired successfully.

tha_notify_acquire_writelock(): This routine can be called immediately before the program tries to acquire a user-defined read/write lock in write mode.

tha_notify_writelock_acquired(): This routine can be called immediately after a user-defined read/write lock has been acquired successfully in write mode.

tha_notify_acquire_readlock(): This routine can be called immediately before the program tries to acquire a user-defined read/write lock in read mode.

tha_notify_readlock_acquired(): This routine can be called immediately after a user-defined read/write lock has been acquired successfully in read mode.

tha_notify_release_lock(): This routine can be called immediately before a user-defined lock (including a read/write lock) is to be released.

tha_notify_lock_released(): This routine can be called immediately after a user-defined lock (including a read/write lock) has been released successfully.

tha_notify_sync_post_begin(): This routine can be called immediately before a user-defined post synchronization is performed.

tha_notify_sync_post_end(): This routine can be called immediately after a user-defined post synchronization has been performed.

tha_notify_sync_wait_begin(): This routine can be called immediately before a user-defined wait synchronization is performed.

tha_notify_sync_wait_end(): This routine can be called immediately after a user-defined wait synchronization has been performed.

In the C/C++ version of the libtha API, each of the above routines takes a single argument, id, whose value should uniquely identify the synchronization object. The type of id is uintptr_t, which is defined in <sys/types.h>. The size of id is 4 bytes in 32-bit mode and 8 bytes in 64-bit mode.

In the Fortran version of the libtha API, each of the above routines takes a single argument, id, whose value should uniquely identify the synchronization object. The type of id is integer, and its size is given by tha_sobj_kind which is defined in tha_finterface.h to be 8 bytes in both 32-bit and 64-bit modes.

To uniquely identify a synchronization object, you should make sure that the argument id has a different value for each different synchronization object. One way to do this is to let the value of id be the address of the synchronization object. That address can be obtained using the & operator in C/C++, or using the loc() library routine in Fortran. See Example 1 under the EXAMPLES section below.

libtha Routines for Controlling Data Race Detection

You can insert calls in your program to the libtha.so API to control data race detection.

tha_check_datarace_mem(): This routine instructs the Thread Analyzer to monitor or ignore accesses to a specified block of memory when doing data race detection. When the onoff parameter is THA_CHK_OFF, data race detection on the specified block of memory is turned off. When the onoff parameter is THA_CHK_ON, data race detection on the specified block of memory is turned on. When onoff is neither THA_CHK_OFF nor THA_CHK_ON, the behavior of the call is undefined. The block of memory starts at addr and has size bytes. When addr is NULL and size is zero, the block of memory is considered to be all memory. The Thread Analyzer monitors all memory accesses by default when data race detection is on. Note that if multiple calls that affect the same block of memory are made by different threads, the calls take effect in the order they are received by the Thread Analyzer. You might want to properly synchronize these calls. Calls to this routine have no effect when data race detection is not turned on by the collect (1) command.

tha_check_datarace_thr(): This routine instructs the Thread Analyzer to monitor or ignore memory accesses by one or more specified threads when doing data race detection. When the onoff parameter is THA_CHK_OFF, data race detection on the specified threads is turned off. When the onoff parameter is THA_CHK_ON, data race detection on the specified threads is turned on. When onoff is neither THA_CHK_OFF nor THA_CHK_ON, the behavior of the call is undefined. When the selfall parameter is THA_CHK_THR_SELF, it only affects the calling thread (that is, data race detection on the calling thread only is turned on/off). When the selfall parameter is THA_CHK_THR_ALL, it affects all threads including new threads created after this call (that is, data race detection is turned off for all threads). When the selfall parameter is neither THA_CHK_THR_SELF nor THA_CHK_THR_ALL, the behavior of the call is undefined. The Thread Analyzer monitors all threads by default when data race detection is on. Note that if multiple calls that affect the same thread are made by different threads, the calls take effect in the order they are received by the Thread Analyzer. You might want to properly synchronize these calls. Calls to this routine have no effect when data race detection is not turned on by the collect (1) command.

See Examples 3 and 4 under the EXAMPLES section below.

Examples

Example 1:

The following Fortran example shows how tha_notify_acquire_lock() and tha_notify_release_lock() can be used to inform the Thread Analyzer that a user-defined lock has been acquired and released, respectively. In this example, the address of the lock object is used as id to uniquely identify the object.

 
include "tha_finterface.h"

integer :: my_lock
integer(kind= tha_sobj_kind) :: id

id = loc (my_lock)
tha_notify_acquire_lock (id)
call my_lock_routine(my_lock)
tha_notify_lock_acquired (id)
...
call my_unlock_routine(my_lock)
tha_notify_lock_released (id)

Example 2:

The following C/C++ example shows how tha_notify_sync_wait_begin() and tha_notify_sync_wait_end() can be used to inform the Thread Analyzer of the start and end of a user-defined wait synchronization, respectively.

In addition, the example shows how tha_notify_sync_post_begin() and tha_notify_sync_post_end() can be used immediately before and after a post synchronization, respectively.

 
#include "tha_interface.h"

int busy_wait = 1;

/* Code executed by thread 1 */
tha_notify_sync_wait_begin(&busy_wait);
while (busy_wait) {
   no_op();
}
tha_notify_sync_wait_end(&busy_wait);

/* Code executed by thread 2 */
tha_notify_sync_post_begin(&busy_wait);
busy_wait =  0;
tha_notify_sync_post_end(&busy_wait);

Example 3:

The following C/C++ example shows how tha_check_datarace_mem() can be used to avoid reporting benign data races.

 
volatile int is_bad = 0;

/*
 * Each thread checks its assigned portion of data_array,
 * and sets the global flag is_bad to 1 once it finds a
 * bad data element.
 */
void check_bad_array (volatile data_t *data_array,
                      unsigned int thread_id) {

  /* Do not check is_bad. */
  tha_check_datarace_mem(&is_bad, sizeof(int), THA_CHK_OFF);

  int i;
  for (i=my_start(thread_id); i<my_end(thread_id); i++) {
     if (is_bad)
         break;
     else {
         if (is_bad_element(data_array[i])) {
            is_bad = 1;
            break;
         }
     }
  }

 tha_check_datarace_mem(&is_bad, sizeof(int), THA_CHK_ON);
}

Example 4:

The following C/C++ example shows how tha_check_datarace_thr() can be used to lower the overhead of data race detection, supposing that the programmer wishes only to check data race between 2 particular threads.

 
/*
 * The following code is executed by the master thread.
 * Before creating any slave threads, the master thread
 * turns data race detection off for all threads.
 */
tha_check_datarace_thr(THA_CHK_THR_ALL, THA_CHK_OFF);
pthread_create(...);

/*
 * The following code is executed by the slave threads.
 * After a slave thread is created, it checks whether
 * it should turn data race detection on for itself.
 */
pthread_t tid = pthread_self();
if(tid == TID_TO_CHECK_1 || tid == TID_TO_CHECK_2)
    tha_check_datarace_thr(THA_CHK_THR_SELF, THA_CHK_ON);

Notes

As shown in the synopsis, the recommended way to link with libtha using cc() is to specify

-Rinstall-path/lib -Linstall-path/lib -ltha

on the command line, where install-path refers to the location in which the compilers are installed.

Attributes

 
 _________________________________________________________
| ATTRIBUTE TYPE   |           ATTRIBUTE VALUE            |
|__________________|______________________________________|
| Stability Level  | Evolving                             |
|__________________|______________________________________|

See also

analyzer (1) , collect (1) , collector (1) , er_print (1) , tha (1) , attributes (5)

Thread Analyzer User's Guide

Performance Analyzer manual