Compaq OpenVMS
デバッガ説明書


前へ 次へ 目次 索引


  1. この STEP コマンドは,プログラムの実行を VVDIVD 命令が実行される直前の行 99 で中断する。この例では,命令が浮動小数点ゼロ除算例外を発生するものと想定する。

  2. この STEP コマンドは,VVDIVD 命令を実行する。ただし,プログラムの実行中に,この時点では例外の実行要求は行われない。

  3. EXAMINE/FLOAT コマンドは,デコードされた例外メッセージをデスティネーション・レジスタ V2 の要素 1 に表示する(第 16.7 節 を参照)。その結果,浮動小数点ゼロ除算例外が発生し,実行要求が保留になっていることを確認する。

  4. SYNCHRONIZE VECTOR_MODE コマンドは,保留中のベクタ例外を即座に実行するように要求する。プログラムがベクタ・プロセッサのハードウェアでなく VVIEF を使用している場合は,異なる診断メッセージが発行されることがあるので注意する。

SYNCHRONIZE VECTOR_MODE コマンドを使用する代わりに,SET VECTOR_MODE SYNCHRONIZED コマンドを入力すると,同期化ベクタ・モードでデバッガを稼働することもできます。このコマンドを使用すると,デバッガは,ベクタ命令が実行されるたびに,スカラ型プロセッサとベクタ型プロセッサ間の同期を自動的にとります。また,ベクタ命令を実行するたびにそのあとで SYNC 命令を実行し,さらにメモリにアクセスするベクタ命令を実行したあとで MSYNC 命令を実行します。その結果,次のように同期化の対象となっているベクタ命令に関連したすべての処理が終了します。

次の例は,SET VECTOR_MODE SYNCHRONIZED コマンドを上記の例で使用したのと同じ命令ストリーム上で実行した場合の影響を示しています。


DBG> SHOW VECTOR_MODE
Vector mode is nonsynchronized
DBG> SET VECTOR_MODE SYNCHRONIZED   (1)
DBG> SHOW VECTOR_MODE
Vector mode is synchronized
DBG> STEP   (2)
stepped to .MAIN.\SUB\%LINE 99 
    99:         VVDIVD  V1,V0,V2
DBG> STEP   (3)
%SYSTEM-F-VARITH, vector arithmetic fault, summary=00000002, 
                  mask=00000004, PC=000002E1, PSL=03C00010 
break on unhandled exception preceding .MAIN.\SUB\%LINE 100 
   100:         CLRL    R0
DBG>

次の番号は,上記の例の番号に対応しています。

  1. SET VECTOR_MODE SYNCHRONIZED コマンドを使用すると,ベクタ命令が実行されるたびに,デバッガはスカラ型プロセッサとベクタ型プロセッサの自動同期化を指示する。

  2. この STEP コマンドは VVDIVD 命令が実行される直前の行 99 でプログラムの実行を中断する。前の例と同様に,命令が浮動小数点ゼロ除算例外を発生したものとみなす。

  3. この STEP コマンドが VVDIVD 命令を実行し,この命令が例外を発生する。デバッガは同期化ベクタ・モードで動作中であるので,ベクタ例外の実行要求が直ちに行われる。

SYNCHRONIZE VECTOR_MODE や SET VECTOR_MODE SYNCHRONIZED のほかにも,同期化に影響を及ぼすデバッガ・コマンド(SET WATCH など)がいくつかあります。

16.9 プログラムのベクタ状態に影響を与えることがある呼び出しルーチン

CALL コマンドとともに /[NO]SAVE_VECTOR_STATE 修飾子を指定すると,ベクタ型プロセッサの現在の状態を保存し,ルーチンが呼び出されたときに復元するかどうかを制御できます。

VAX ベクタ・プロセッサの状態は,次のもので決まります。

CALL コマンドを使用してルーチンを実行すると,ルーチンの実行により,ベクタ・プロセッサの状態が次の動機により変化することがあります。

CALL/SAVE_VECTOR_STATE コマンドは,CALL コマンドを実行する前に存在したベクタ型プロセッサの状態を,呼び出したルーチンの実行が完了したあとにデバッガが復元することを指定します。その結果,呼び出したルーチンの実行が完了したあとに次の各項が確認されます。

CALL/NOSAVE_VECTOR_STATE コマンドは省略時の設定であり,CALL コマンドが実行される前に存在したベクタ型プロセッサの状態は,呼び出したルーチンの実行が完了したあとに復元しないことを指定します。この場合,ルーチン呼び出し後のベクタ型プロセッサの状態は,呼び出したルーチンの影響によって異なります。

/[NO]SAVE_VECTOR_STATE 修飾子は,VAX 汎用(スカラ)レジスタには影響しません。これらのレジスタの値は必ず保存され,CALL コマンドでルーチンを実行すると復元されます。

16.10 画面モードでのベクタ・レジスタ・データの表示

画面モードでは,レジスタ表示が VAX 汎用レジスタの現在の値を示します。第 7.4.5 項 を参照してください。

ベクタ・レジスタまたはベクタ制御レジスタに入っているデータを画面モードで表示するには,DO 表示を使用します。第 7.2.1 項 を参照してください。

たとえば,次のコマンドは,V2_DISP という DO 表示を作成します。これは,レジスタ V2 の要素 4 から 7 までの内容を示します(Fortran 配列構文)。この表示は,プログラムからデバッガに制御が戻るたびに,自動的に更新されます。


DBG> DISPLAY V2_DISP AT RQ2 DO(EXAMINE %V2(4:7))

16.11 問題点と制限事項

この節では,ベクタ化されたプログラムに対するデバッガのサポートについて,問題と制限事項をまとめます。


第 17 章
タスキング・プログラムのデバッグ

本章では,タスキング・プログラム(マルチスレッド・プログラムとも呼ぶ)に固有のデバッガ機能について説明します。タスキング・プログラムは 1 つのプロセス内に複数のタスクまたは実行スレッドを持っています。デバッガで使用する タスク という用語は制御の流れのことであり,言語や実現方法とは関係ありません。デバッガのタスキング・サポートは,それらのプログラムすべてに適用されます。次のものを含んでいます。

注意

デバッガの中では,タスクとスレッドという用語は同義語として使われます。

PTHREAD$RTL バージョン 7.1 またはそれ以降のバージョンがリンクされたプログラムをデバッグするときには,PTHREAD コマンドを使って Compaq POSIX Threads デバッガに直接アクセスすることができます。

本章では,POSIX Threads 固有か言語固有の情報にはそのことを明記します。第 17.1 節 に POSIX Threads 用語と Ada のタスキング用語の対応表を示します。

本章の機能を使用すれば,次のような処理を行うことができます。

これらの機能を使用するときには,同じタスキング・プログラムを実行してもそのときの状況によっては動作がデバッガにより変更されることがあるので注意してください。たとえば,現在アクティブなタスクの実行をあるブレークポイントで中断しているとき,入出力(I/O)の終了による POSIX 信号か非同期システム・トラップ(AST)が届いた場合は,ユーザの続行指示後ただちにその他のタスクが適格になることがあります。

POSIX Threads や POSIX スレッドについての詳しい説明は,『Guide to POSIX Threads Library』を参照してください。Ada タスクについての詳しい説明は Compaq Ada のマニュアルを参照してください。

マルチプロセス・プログラム(2つ以上のプロセスに分けて実行されるプログラム)のデバッグについては 第 15 章 を参照してください。

17.1 POSIX Threads 用語とAda用語の対応表

表 17-1 に POSIX Threads と Ada の用語とその意味の対応を示します。

表 17-1 POSIX Threads用語と Ada 用語の対応
POSIX Threads 用語 Ada用語 意味
スレッド タスク 同じプロセス内の制御の流れ
スレッド・オブジェクト タスク・オブジェクト 制御の流れを表すデータ項目
オブジェクト名または式 タスク名または式 制御の流れを表すデータ項目
開始ルーチン タスク本体 制御の流れに従って実行されるコード
該当なし 親タスク 親タスクの制御の流れ
該当なし 依存タスク なんらかの親タスクに制御される子タスクの制御の流れ
同期化オブジェクト(ミューテクス,条件変数) ランデブ構造(エントリ呼び出しやaccept文など) 制御の流れを同期化する方法
スケジューリング方針およびスケジューリング優先順位 タスク優先順位 実行のスケジューリング方法
警告処理 abort文 制御の流れの取り消し方法
スレッド状態 タスク状態 実行の状態(待ち,レディ,実行中,終了)
スレッド作成属性(優先順位,スケジューリング方針など) プラグマ パラレル・エンティティの属性

17.2 タスキング・プログラムの例

次の各項では,タスキング・プログラムのデバッグ時によく起こるエラーを含んでいるタスキング・プログラムの例を示します。

本章のその他の例は,これらのプログラムを引用したものです。

17.2.1 Cのマルチスレッド・プログラムの例

例 17-1 はマルチスレッドの C のプログラムです。条件変数の使用法が間違っているのでブロッキングを起こします。

例のあとに説明が続いています。その説明のあとに,デバッガを使用してスレッドの相対的な実行を制御することによってブロッキングを診断する方法を示しています。

例 17-1 では,初期スレッドにより,計算作業を行う 2 つのワーカ・スレッドが作成されます。これらのワーカ・スレッドの作成後に SHOW TASK/ALL コマンドを実行すれば,それぞれが 1 つのスレッドに対応する 4 つのタスクが表示されます。第 17.4 節 に SHOW TASK コマンドの使用法が説明されています。

例 17-1 では,ワーカ・スレッドのパスの行 3893 に同期化点(条件待ち)が設けられています。行 3877 から始まるコメントは,このような直接的な呼び出しは間違ったプログラミング方法であることを示したうえで,正しいコーディング方法を示しています。

このプログラムを実行すると,ワーカ・スレッドが大量の計算を行っているときに初期スレッドが条件変数をブロードキャストします。条件変数をモニタしている最初のスレッドは初期スレッドのブロードキャストを検出してクリアし,残りのスレッドを放置します。実行が妨げられ,プログラムは終了できなくなります。

例 17-1 Cのマルチスレッド・プログラムの例

3777  /* 定義  */ 
3778  #define NUM_WORKERS 2           /* ワーカ・スレッドの数    */ 
3779 
3780  /* マクロ                                                  */ 
3781  #define check(status,string)\
3782      if(status == -1)perror(string); \
3783 
3784  /* グローバル変数                                          */ 
3785  int              cv_pred1;     /* 条件変数の述語           */ 
3786  pthread_mutex_t  cv_mutex;     /* 条件変数のミューテクス   */ 
3787  pthread_cond_t   cv;           /* 条件変数                 */ 
3788  pthread_mutex_t  print_mutex;  /* プリント・ミューテクス   */ 
 
 
3789 
3790  /* ルーチン                                                */ 
3791  static pthread_startroutine_t 
3792  worker_routine(pthread_addr_t  arg); 
3793 
3794  main()
3795     { 
3796     pthread_t  threads[NUM_WORKERS];  /* ワーカ・スレッド   */ 
3797     int        status;                /* 戻り状態値         */ 
3798     int        exit;                  /* Join終了状態値     */ 
3799     int        result;                /* Join結果値         */ 
3800     int        i;                     /* ループ索引         */ 
3801 
3802     /* ミューテクスの初期化                                 */ 
3803     status = pthread_mutex_init(&cv_mutex, pthread_mutexattr_default); 
3804     check(status, "cv_mutex initilization bad status"); 
3805     status = pthread_mutex_init(&print_mutex, pthread_mutexattr_default); 
3806     check(status, "print_mutex intialization bad status"); 
3807 
3808     /* 条件変数の初期化                                     */ 
3809     status = pthread_cond_init(&cv, pthread_condattr_default); 
3810     check(status, "cv condition init bad status"); 
3811 
3812     /* 条件変数の述語の初期化                               */ 
3813     cv_pred1 = 1;                                            (1)
3814 
3815     /* ワーカ・スレッドの作成                               */ 
3816     for(i = 0; i < num_workers; i++){                      (2)
3817         status = pthread_create(
3818                         &threads[i], 
3819                         pthread_attr_default, 
3820                         worker_routine, 
3821                         0); 
3822         check(status, "threads create bad status"); 
3823         } 
3824 
3825     /* cv_pred1を偽に設定。可視性を保つためにロック内で行う。*/ 
3826 
3827     status = pthread_mutex_lock(&cv_mutex); 
3828     check(status, "cv_mutex lock bad status"); 
3829 
3830     cv_pred1 = 0;                                            (3)
3831 
3832     status = pthread_mutex_unlock(&cv_mutex); 
3833     check(status, "cv_mutex unlock bad status"); 
3834 
3835     /* ブロードキャストの実施 */ 
3836     status = pthread_cond_broadcast(&cv);                   (4)
3837     check(status, "cv broadcast bad status"); 
3838 
3839     /* 両方のワーカ・スレッドの結合を試行                      */ 
3840     for(i = 0; i < num_workers; i++){                      (5)
3841         exit = pthread_join(threads[i],(pthread_addr_t*)&result); 
3842         check(exit, "threads join bad status"); 
3843         } 
3844     } 
3845 
3846  static pthread_startroutine_t 
3847  worker_routine(arg)
3848     pthread_addr_t   arg;                                    (6)
3849     { 
3850     int   sum; 
3851     int   iterations; 
3852     int   count; 
3853     int   status; 
3854 
3855     /* 大量の計算を実施                                        */ 
3856     for(iterations = 1; iterations < 10001; iterations++){ 
3857         sum = 1; 
3858         for(count = 1; count < 10001; count++){ 
3859             sum = sum + count; 
3860             } 
3861         } 
3862 
3863     /* Printfはリエントラントとは限らないので,一度に1スレッドを実行 */ 
3864 
3865     status = pthread_mutex_lock(&print_mutex); 
3866     check(status, "print_mutex lock bad status"); 
3867     printf(" The sum is %d \n", sum); 
3868     status = pthread_mutex_unlock(&print_mutex); 
3869     check(status, "print_mutex unlock bad status"); 
3870 
3871     /* この条件変数のミューテクスをロックする。スレッドにより条件変数がブ*/ 
3872     /* ロックされるとpthread_condによりそのミューテクスがアンロックされる*/ 
3873 
3874     status = pthread_mutex_lock(&cv_mutex); 
3875     check(status, "cv_mutex lock bad status"); 
3876 
3877     /* 次の文では,条件待ち呼び出しのまわりをループし,その条件変数の述 */ 
3878     /* 語をチェックするのが正しい条件待ちの構文ということになります。  */ 
3879     /* そうすれば,ブロードキャスト済みの可能性がある条件変数を待った   */ 
3880     /* り,間違ったウェイクアップによって起動されるのを回避できます。そ */ 
3881     /* のスレッドがウェイクアップされ,しかもその述語が偽であれば,実  */ 
3882     /* 行が再開されます。正しい呼び出しは,たとえば次のようになります。*/ 
3883     /*                                                                  */ 
3884     /*    while(cv_pred1){                                             */ 
3885     /*      status = pthread_cond_wait(&cv, &cv_mutex);                */ 
3886     /*      check(status, "cv condition wait bad status");             */ 
3887     /*    }                                                             */ 
3888     /*                                                                  */ 
3889     /* 次のコーディングで使用されているような直接的な呼び出しでは,   */ 
3890     /* スレッドが間違ってウェイクアップされたり,この例のワーカ・       */ 
3891     /* スレッドの1つと同様に永続的にブロックされることがあります。     */ 
3892 
3893     status = pthread_cond_wait(&cv, &cv_mutex);             (7)
3894     check(status, "cv condition wait bad status"); 
3895 
3896     /* 条件待ちでブロックされている間,そのルーチンはミューテクスを手放 */ 
3897     /* しますが,制御が戻ったらミューテクスを取り出します。            */ 
3898 
3899     status = pthread_mutex_unlock(&cv_mutex); 
3900     check(status, "cv_mutex unlock bad status"); 
3901 
3902     return(int)arg; 
3903     } 

次の番号は,例 17-1 の番号に対応しています。


前へ 次へ 目次 索引