pthread ライブラリー・オブジェクトを検査および変更するマルチスレッド・プログラムの開発

pthread デバッグ・ライブラリー (libpthdebug.a) には、アプリケーション開発者が pthread ライブラリー・オブジェクトを検査し、 変更できるようにする 1 組の関数が準備されています。

このライブラリーは、32 ビット・アプリケーションと 64 ビット・アプリケーションの両方で使用することができます。 このライブラリーは、スレッド・セーフです。 pthread デバッグ・ライブラリーには、32 ビット共有オブジェクトおよび 64 ビット共有オブジェクトが入っています。

pthread デバッグ・ライブラリーは、 アプリケーションが pthread ライブラリーの情報にアクセスする機能を提供します。 これには、pthread についての情報、pthread 属性、mutex、mutex 属性、条件変数、 条件変数属性、読み取り/書き込みロック、読み取り/書き込みロック属性、および pthread ライブラリーの状態に関する情報などがあります。

注: このライブラリーによって返されるすべてのデータ (アドレス、レジスター) は、64 ビット・アプリケーションと 32 ビット・アプリケーションの両方で 64 ビット・フォーマットです。 これらの値を 32 ビット・アプリケーション用に 32 ビット・フォーマットに変換するのは、アプリケーションの責任です。 32 ビット・アプリケーションのデバッグ時に、 アドレスとレジスターの上半分は無視されます。

pthread デバッグ・ライブラリーは、pshared 値が PTHREAD_PROCESS_SHAREDである mutex、mutex 属性、条件変数、条件変数属性、読み取り/書き込みロック、および読み取り/書き込みロック属性に関する情報を報告しません。

初期化

アプリケーションは、各 pthread プロセスの pthread デバッグ・ライブラリー・セッションを初期化する必要があります。 pthdb_sessison_init 関数は、プロセスがロードされた後に、各 pthreaded プロセスから呼び出される必要があります。 pthread デバッグ・ライブラリーは、単一プロセスごとに 1 つのセッションをサポートします。 アプリケーションは、固有のユーザー ID を割り当て、それを pthdb_session_init 関数に渡す必要があります。次に、この関数は、pthdb_session_pthreaded 関数を除く他のすべての pthread デバッグ・ライブラリー関数に、最初のパラメーターとして渡す必要がある固有のセッション ID を割り当てます。 pthread デバッグ・ライブラリーがコールバック関数を呼び出すときにはいつでも、 この関数は、アプリケーションが割り当てた固有のユーザー ID を元のアプリケーションに渡します。 pthdb_session_init 関数は、 アプリケーションによって提供されたコールバック関数 のリストを検査して、セッションのデータ構造体を初期化します。 また、この関数はセッション・フラグを設定します。 アプリケーションは、PTHDB_FLAG_SUSPEND フラグを pthdb_session_init 関数に渡す必要があります。 フラグの全リストについては、 pthdb_session_setflags 関数を参照してください。

コールバック関数

pthread デバッグ・ライブラリーは、コールバック関数を使用して、データの獲得と書き込み、およびアプリケーションに対する ストレージ管理を行います。 アプリケーションに必須のコールバック関数は、次のとおりです。
read_data
pthread ライブラリー・オブジェクト情報を検索します。
alloc
pthread デバッグ・ライブラリー内のメモリーを割り当てます。
realloc
pthread デバッグ・ライブラリー内のメモリーを割り当て直します。
dealloc
pthread デバッグ・ライブラリー内の割り当て済みメモリーを解放します。
アプリケーションがオプショナルで選択できるコールバック関数は、次のとおりです。
read_regs
pthdb_pthread_context および pthdb_pthread_setcontext サブルーチンにのみ必要です。
write_data
pthdb_pthread_setcontext サブルーチンにのみ必要です。
write_regs
pthdb_pthread_setcontext サブルーチンにのみ必要です。

UPDATE 機能

アプリケーションが停止するたびに、セッションが初期化された後で、 pthdb_session_update 関数を呼び出す必要があります。 この関数は、pthread、pthread 属性、mutex、mutex 属性、条件変数、条件変数属性、 読み取り/書き込みロック、読み取り/書き込みロック属性、pthread 固有のキーおよびアクティブ・キーのリストを設定またはリセットします。 これは、コールバック関数を使用してリスト用のメモリーを管理します。

コンテキスト関数

pthdb_pthread_context 関数はコンテキスト情報を取得し、 pthdb_pthread_setcontext 関数はコンテキストを設定します。 pthdb_pthread_context 関数は、カーネルかアプリケーションのアドレス・スペース内の pthread データ構造のどちらかから pthread のコンテキスト情報を獲得します。 pthread がカーネル・スレッドと関連していない場合、 pthread ライブラリーによって保管されたコンテキスト情報を獲得します。 pthread がカーネル・スレッドと関連している場合、 情報はコールバック関数を使用してアプリケーションから獲得されます。 アプリケーションは、カーネル・スレッドがカーネル・モードかユーザー・モードかを判別し、そのモードに関する正しい情報を提供する必要があります。

カーネル・スレッド付きの pthread がカーネル・モードである場合は、カーネルが一か所に保管しないので、 全ユーザー・モード・コンテキストを取得できません。 getthrds 関数は、常にユーザー・モード・スタックを保管するので、この情報の一部を取得するのに使用することができます。 アプリケーションは、thrdsinfo64.ti_scount 構造体を検査すれば発見できます。 この値がゼロでない場合、ユーザー・モード・スタックは thrdsinfo64.ti_ustk 構造体で使用可能です。 ユーザー・モード・スタックからは、命令アドレス・レジスター (IAR) とコールバック・フレームを判別できますが、他のレジスター値は判別できません。 thrdsinfo64 構造体は、 procinfo.h ファイル内で定義されています。

リスト関数

pthread デバッグ・ライブラリーは、タイプ固有のハンドルで表した pthreads、pthread 属性、mutex、 mutex 属性、条件変数、条件変数属性、 読み取り/書き込みロック、読み取り/書き込みロック属性、pthread 固有のキーとアクティブ・キーのリストを保守します。 pthdb_object 関数は、該当するリストの次のハンドルを戻します。ここで、 object は次のいずれかです。 pthread, attr, mutex、mutexattr、cond、condattr、rwlock、rwlockattr または key。 このリストが空であるか、またはリストの終わりに達した場合、PTHDB_INVALID_OBJECT が報告されます。ここで、OBJECT は、PTHREAD、ATTR、MUTEX、 MUTEXATTR、COND、CONDATTR、RWLOCK、RWLOCKATTR、または KEY のいずれかです。

フィールド関数

オブジェクトに関する詳細情報は、該当するオブジェクトのメンバー関数 pthdb_object_field を使用することによって取得できます。 ここで、object は、pthread、attr、mutex、mutexattr、cond、condattr、rwlock、rwlockattr、または key のいずれかです。 field は、オブジェクトの詳細情報のフィールドの名前です。

セッションのカスタマイズ

pthdb_session_setflags 関数を使用すると、アプリケーションはセッションをカスタマイズするフラグを変更することができます。 これらのフラグは、 コンテキスト操作時に読み取りまたは書き込まれるレジスターの数を制御します。

pthdb_session_flags 関数は、セッションの現行フラグを取得します。

セッションの終了

セッションが終了したときに、セッション・データ構造体の割り当てを解除し、セッション・データを削除する必要があります。 これを行うには、 pthdb_session_destroy 関数を呼び出します。この関数は、コールバック関数を使用してメモリーの割り振りを解除します。 pthdb_session_init、および pthdb_session_update 関数によって割り振られたすべてのメモリーが割り振り解除されます。

以下の例は、アプリケーションを pthread デバッグ・ライブラリーに接続する方法を示しています。
/* includes */

#include <thread.h>
#include <ys/pthdebug.h>

...

int my_read_data(pthdb_user_t user, pthdb_symbol_t symbols[],int count)
{
  int rc;

  rc=memcpy(buf,(void *)addr,len);                              
  if (rc==NULL) {                                               
    fprintf(stderr,&odq;Error message\n&cdq;);
    return(1);                                                  
  }                                                             
  return(0);                                                    
}
int my_alloc(pthdb_user_t user, size_t len, void **bufp)
{
  *bufp=malloc(len);                                            
  if(!*bufp) {                                                  
    fprintf(stderr,&odq;Error message\n&cdq;);
    return(1);                                                  
  }                                                             
  return(0);                                                    
}
int my_realloc(pthdb_user_t user, void *buf, size_t len, void **bufp)
{
  *bufp=realloc(buf,len);                                    
  if(!*bufp) {                                               
    fprintf(stderr,“Error message\n”);
    return(1);                                               
  }                                                          
  return(0);                                                 
}
int my_dealloc(pthdb_user_t user,void *buf)
{
  free(buf); 
  return(0); 
}

status()
{
  pthdb_callbacks_t callbacks =
                    {  NULL,                
                       my_read_data,  
                       NULL, 
                       NULL,                
                       NULL,                
                       my_alloc,            
                       my_realloc,          
                       my_dealloc,          
                       NULL                 
                    };

  ...

  rc=pthread_suspend_others_np();
  if (rc!=0)
    deal with error

  if (not initialized)
    rc=pthdb_session_init(user,exec_mode,PTHDB_SUSPEND|PTHDB_REGS,callbacks,
                          &session);
    if (rc!=PTHDB_SUCCESS)
       deal with error

  rc=pthdb_session_update(session);
  if (rc!=PTHDB_SUCCESS)
        deal with error
  
   retrieve pthread object information using the object list functions and 
   the object field functions

  ...
  
  rc=pthread_continue_others_np();
  if (rc!=0)
    deal with error
}

...

main()
{
  ...
}