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);
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
共有オブジェクト libtha.so は、Oracle Solaris Studio スレッドアナライザとともに使用できる API を提供します。この API ルーチンは、同期についてスレッドアナライザに通知したり、データ競合の検出を制御するために使用できます。
libtha.so は API ルーチンの「フック」(またはダミー) エントリポイントしか提供しないことに注意してください。このため、これらのルーチンを呼び出して、libtha.so とリンクされたプログラムは、スレッドアナライザ実験の外部だけでなく、それらの実験の内部でも実行できます。
プログラムがスレッドアナライザ実験の外部で実行する場合 (つまりプログラムが collect -r race の下でも collect -r deadlock の下でも実行していない場合)、API ルーチンは機能しません。
プログラムがスレッドアナライザ実験の下で実行する場合 (つまり、プログラムが collect -r race または collect -r deadlock の下で実行する場合) は、ルーチンは機能します。
スレッドアナライザ実験の実行の詳細は、collect(1) を参照してください。
スレッドアナライザは、OpenMP、POSIX スレッド、および Solaris スレッドで提供されるほとんどの標準同期 API と構文を認識できます。ただし、ツールはユーザーが作成した同期を認識できず、このような同期を使用する場合、誤検知のデータの競合を報告することがあります。たとえば、直接書いたアセンブリを使用して実装したスピンロックは、このツールでは認識できません。
プログラムにユーザーが作成した同期が含まれている場合、libtha.so API の呼び出しをプログラムに挿入して、スレッドアナライザにこれらの同期について通知できます。これらの呼び出しによって、ツールは同期を認識でき、報告される誤検知のデータ競合数が減ります。
libtha.so API は次の同期ルーチンから構成されます。
tha_notify_acquire_lock(): このルーチンは、プログラムがユーザー定義のロックを取得しようとする直前に呼び出せます。
tha_notify_lock_acquired(): このルーチンは、ユーザー定義のロックが正しく取得された直後に呼び出せます。
tha_notify_acquire_writelock(): このルーチンは、プログラムが書き込みモードでユーザー定義の読み取り/書き込みロックを取得しようとする直前に呼び出せます。
tha_notify_writelock_acquired(): このルーチンは、書き込みモードでユーザー定義の読み取り/書き込みロックが正しく取得された直後に呼び出せます。
tha_notify_acquire_readlock(): このルーチンは、プログラムが読み取りモードでユーザー定義の読み取り/書き込みロックを取得しようとする直前に呼び出せます。
tha_notify_readlock_acquired(): このルーチンは、読み取りモードでユーザー定義の読み取り/書き込みロックが正しく取得された直後に呼び出せます。
tha_notify_release_lock(): このルーチンは、ユーザー定義のロック (読み取り/書き込みロックを含む) が解除される直前に呼び出せます。
tha_notify_lock_released(): このルーチンは、ユーザー定義のロック (読み取り/書き込みロックを含む) が正しく解除された直後に呼び出せます。
tha_notify_sync_post_begin(): このルーチンは、ユーザー定義の送信同期が実行される直前に呼び出せます。
tha_notify_sync_post_end(): このルーチンは、ユーザー定義の送信同期が実行された直後に呼び出せます。
tha_notify_sync_wait_begin(): このルーチンは、ユーザー定義の待機同期が実行される直前に呼び出せます。
tha_notify_sync_wait_end(): このルーチンは、ユーザー定義の待機同期が実行された直後に呼び出せます。
C/C++ バージョンの libtha API では、上記の各ルーチンは単一の引数 id を取り、その値は同期オブジェクトを一意に識別する値にする必要があります。id の型は uintptr_t であり、<sys/types.h> に定義されています。id のサイズは 32 ビットモードで 4 バイト、64 ビットモードで 8 バイトです。
Fortran バージョンの libtha API では、上記の各ルーチンは単一の引数 id を取り、その値は同期オブジェクトを一意に識別する値にする必要があります。id の型は整数で、サイズは tha_finterface.h に定義されている tha_sobj_kind で指定され、32 ビットと 64 ビットモードの両方で 8 バイトです。
同期オブジェクトを一意に識別できるように、引数 id には、必ず同期オブジェクトごとに異なる値を割り当てる必要があります。これを行う 1 つの方法は、id の値を同期オブジェクトのアドレスにすることです。このアドレスは、C/C++ では & 演算子を使用して、Fortran では loc() ライブラリルーチンを使用して取得できます。後述の「使用例」セクションの例 1 を参照してください。
データ競合の検出を制御するために、libtha.so API の呼び出しをプログラムに挿入できます。
tha_check_datarace_mem(): このルーチンは、データ競合検出の実行中に、指定されたメモリーブロックへのアクセスをモニターするか無視するように、スレッドアナライザに指示します。onoff パラメータが THA_CHK_OFF である場合、指定されたメモリーブロックでのデータ競合の検出はオフになります。 onoff パラメータが THA_CHK_ON である場合、指定されたメモリーブロックでのデータ競合の検出はオンになります。onoff が THA_CHK_OFF でも THA_CHK_ON でもない場合、呼び出しの動作は定義されていません。メモリーブロックは addr から始まり、size バイトになります。addr が NULL で size がゼロの場合、メモリーブロックはメモリー全体と見なされます。スレッドアナライザは、データ競合の検出がオンのときに、デフォルトですべてのメモリーアクセスをモニターします。同じメモリーブロックに影響する複数の呼び出しが別々のスレッドから行われた場合、呼び出しは、スレッドアナライザが受信した順に効力を発することに注意してください。これらの呼び出しを適切に同期できます。collect(1) コマンドによって、データ競合の検出がオンになっていない場合、このルーチンの呼び出しは効果がありません。
tha_check_datarace_thr(): このルーチンは、データ競合の検出の実行中に、指定された 1 つ以上のスレッドによるメモリーアクセスをモニターするか無視するように、スレッドアナライザに指示します。onoff パラメータが THA_CHK_OFF である場合、指定されたスレッドでのデータ競合の検出はオフになります。onoff パラメータが THA_CHK_ON である場合、指定されたスレッドでのデータ競合の検出はオンになります。onoff が THA_CHK_OFF でも THA_CHK_ON でもない場合、呼び出しの動作は定義されていません。selfall パラメータが THA_CHK_THR_SELF である場合、これは、呼び出し側スレッドにのみ影響します (つまり、呼び出し側スレッドでのみデータ競合の検出がオン/オフになります)。selfall パラメータが THA_CHK_THR_ALL である場合、これは、この呼び出し後に作成された新しいスレッドを含むすべてのスレッドに影響します (つまり、データ競合の検出はすべてスレッドでオフになります)。selfall が THA_CHK_THR_SELF でも THA_CHK_THR_ALL でもない場合、呼び出しの動作は定義されていません。スレッドアナライザは、データ競合の検出がオンのときに、デフォルトですべてのスレッドをモニターします。同じスレッドに影響する複数の呼び出しが別々のスレッドから行われた場合、呼び出しは、スレッドアナライザが受信した順に効力を発することに注意してください。これらの呼び出しを適切に同期できます。collect(1) コマンドによって、データ競合の検出がオンになっていない場合、このルーチンの呼び出しは効果がありません。
後述の「使用例」セクションの例 3 と例 4 を参照してください。
例 1:
次の Fortran の使用例では、tha_notify_acquire_lock() および tha_notify_release_lock() を使用して、それぞれユーザー定義ロックが取得、解除されたことをスレッドアナライザに通知する方法を示しています。この例では、ロックオブジェクトのアドレスを id として使用してオブジェクトを一意に識別しています。
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)
例 2:
次の C/C++ の使用例は、tha_notify_sync_wait_begin() および tha_notify_sync_wait_end() を使用して、それぞれユーザー定義の待機同期の開始と終了をスレッドアナライザに通知する方法を示しています。
さらに、この例では、送信同期の直前と直後にそれぞれtha_notify_sync_post_begin() および tha_notify_sync_post_end() を使用する方法も示しています。
#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);
例 3:
次の C/C++ の使用例は、tha_check_datarace_mem() を使用して、影響のないデータの競合の報告を回避する方法を示しています。
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); }
例 4:
次の C/C++ の使用例は、プログラマーが 2 つの特定のスレッド間におけるデータの競合だけを調べる場合、tha_check_datarace_thr() を使用して、データ競合の検出のオーバーヘッドを低減する方法を示しています。
/* * 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);
形式に示しているように、cc() を使用して libtha とリンクさせる方法としては、次を指定することをお勧めします:
-Rinstall-path/lib -Linstall-path/lib -ltha
(コマンド行で)。ここで、install-path はコンパイラがインストールされている場所を示します。
_________________________________________________________ | ATTRIBUTE TYPE | ATTRIBUTE VALUE | |__________________|______________________________________| | Stability Level | Evolving | |__________________|______________________________________|
analyzer (1) , collect (1) , collector (1) , er_print (1) , tha (1) , attributes (5)
スレッドアナライザのユーザーガイド
パフォーマンスアナライザマニュアル