[ 前のページ ] [ 次のページ ] [ 目次 ] [ 索引 ] [ DOC Home ]

7 インターロックされたメモリ命令の使用(Alphaのみ)

Alpha Architecture Reference Manual, Third Edition (AARM) に,インターロックされたメモリ命令を使用するための厳密な規則が説明されています。 新しいAlpha 21264 (EV6)プロセッサと将来のすべてのAlpha プロセッサは,これらの規則で決められている必要条件に関して, 以前のプロセッサよりさらに厳しくなっています。この結果,規則に準拠していないにもかかわらず, 以前は正常に動作していたコードが,新しい21264 プロセッサを搭載したシステムで正しく実行できないことがあります。 このような規則に準拠していないコード・シーケンスが発生することは非常にまれであると考えています。 21264プロセッサは, OpenVMS Alphaバージョン7.1-2より以前のバージョンではサポートされません。

規則に従っていないコードを実行すると,インタープロセッサ・ロックが使用されるときに, プロセッサ間の同期が失われる可能性があり,インターロックされたシーケンスが常にエラーになる場合は, 無限ループになることがあります。BLISS コンパイラの以前のバージョン,MACRO-32コンパイラとMACRO-64 アセンブラの一部のバージョンでコンパイルされたプログラムや, 一部のDEC CおよびC++プログラムのコード・シーケンスで,このような動作が発生することがあります。

影響を受けるコード・シーケンスでは,LDx_L/STx_C命令をアセンブリ言語ソースで直接使用しているか, コンパイラで生成されたコードで使用しています。 インターロックされた命令を使用する可能性の高いアプリケーションは複雑であるか, マルチスレッドされたアプリケーションであるか, または高度に最適化され,手作りのロックおよび同期化手法を使用しているデバイス・ ドライバです。

7.1 必要なコード・チェック

OpenVMSでは,21264プロセッサで実行されるコードにこのようなシーケンスがないかどうか確認するように推奨しています。 プロセス間ロック,マルチスレッド, プロセッサ間通信を行うコードでは,特に注意を払う必要があります。

規則に準拠していないコード・シーケンスがないかどうか,Alpha実行可能プログラムを分析するために,SRM_CHECK ツールが開発されました(Alpha アーキテクチャを定義したSystem Reference Manualの後に開発されました) 。このツールは,エラーが発生する可能性のあるシーケンスを検出し, エラーを報告し,問題のあるシーケンスのマシン・コードを表示します。

7.2 コード分析ツールの使用

SRM_CHECKツールは,OpenVMS Alphaバージョン7.2オペレーティング・システムのCD-ROM の次の場所にあります。

     SYS$SYSTEM:SRM_CHECK.EXE

SRM_CHECKツールを実行するには,フォーリン・コマンドとして定義し( またはDCL$PATH機能を使用し),チェックするイメージの名前を指定して起動します。 問題が検出されると,マシン・コードが表示され,イメージ情報の一部が印刷されます。 次の例では,このツールを使用してmyimage.exe というイメージを分析する方法を示しています。

     $ define DCL$PATH []
     $ srm_check myimage.exe

このツールでは,ワイルドカード検索がサポートされます。ワイルドカード検索を開始するには, 次のコマンド行を使用します。

     $ srm_check [*...]* -log

チェックされたイメージのリストを作成するには,-log修飾子を指定します。-output 修飾子を使用すれば,出力をデータ・ファイルに書き込むことができます。 たとえば,次のコマンドは出力をCHECK.DATという名前のファイルに書き込みます。

     $ srm_check 'file' -output check.dat

ツールからの出力を使用し,イメージのMAPファイルを調べれば,シーケンスを生成したモジュールを検索することができます。 表示されるアドレスはMAP ファイルから見つけることができるアドレスに直接対応します。

次の例では,SYSTEM_SYNCHRONIZATION.EXEというイメージに対して,分析ツールを使用した結果作成される出力を示しています。

     ** Potential Alpha Architecture Violation(s) found in file...
     ** Found an unexpected ldq at 00003618
     0000360C   AD970130     ldq_l          R12, 0x130(R23)
     00003610   4596000A     and            R12, R22, R10
     00003614   F5400006     bne            R10, 00003630
     00003618   A54B0000     ldq            R10, (R11)
     Image Name:    SYSTEM_SYNCHRONIZATION
     Image Ident:   X-3
     Link Time:      5-NOV-1998 22:55:58.10
     Build Ident:   X6P7-SSB-0000
     Header Size:   584
     Image Section: 0, vbn: 3, va: 0x0, flags: RESIDENT EXE (0x880)

system_synchronization.exeのMAPファイルには,次の情報が格納されます。

        EXEC$NONPAGED_CODE       00000000 0000B317 0000B318 (      45848.) 2 **
     5
        SMPROUT         00000000 000047BB 000047BC (      18364.) 2 **  5
        SMPINITIAL      000047C0 000061E7 00001A28 (       6696.) 2 **  5

アドレス360CはSMPROUTモジュールにあり,0〜47BBのアドレスを格納しています。 モジュールから出力されたマシン・コードを確認することで,コードの位置を調べ, リスト行番号を使用して,対応するソース・コードを突き止めることができます。SMPROUT のベースが0以外の場合は,アドレス( この場合は360C)からベースを減算して,リスト・ファイル内での相対アドレスを求める必要があります。

このツールは,出力に可能性のある違反を報告します。SRM_CHECK は通常,セクションの属性によってイメージ内のコード・セクションを識別することができますが,OpenVMS イメージの場合は,同じ属性を持つデータ・ セクションが格納されることがあります。この結果,SRM_CHECKはデータをコードであるかのようにスキャンし, データ・ブロックが規則に準拠していないコード・ シーケンスであると解釈することがあります。このような状況はあまり発生することがなく,MAP とリスト・ファイルを調べることで検出できます。

7.3 規則に準拠しないコードの特徴

SRM_CHECKツールによって検出される規則に準拠しないコードは,次の4種類に分類できます。 これらの大部分は,新しいコンパイラで再コンパイルすることで修正できます。 ソース・コードを変更しなければならないことがありますが, そのような場合はまれです。コンパイラのバージョンの詳細については, 第7.5節を参照してください。

SRM_CHECKツールがイメージから違反を検出した場合は,適切なコンパイラを使用してイメージを再コンパイルしなければなりません( 第7.5節を参照)。再コンパイルした後, イメージを再び分析する必要があります。 再コンパイルの後も違反が発生する場合は, ソース・コードを調べ,コード・スケジューリング違反が発生する理由を突き止めなければなりません。 その後,必要に応じてソース・コードを変更します。

7.4 コーディングの必要条件

Alpha Architecture Reference Manualには,プロセッサ間のデータの不可分な更新を行う方法が説明されています。 特に,Third Edition にはこの問題について非常に詳しい説明があります。このエディションの5.5 節「Data Sharing」と,LDx_L命令について説明した4.2.4項には,インターロックされたメモリ・ シーケンスの規則について詳しく説明されています。

次の2つの必要条件が満たされない場合は,規則に準拠しないコードが生成されます。

したがって,SRM_CHECKツールは次の条件を検索します。

次の例は,SRM_CHECKでフラグが付けられたコードを示しています。

             ** Found an unexpected ldq at 0008291C
             00082914   AC300000     ldq_l          R1, (R16)
             00082918   2284FFEC     lda            R20, 0xFFEC(R4)
             0008291C   A6A20038     ldq            R21, 0x38(R2)

この例で,対応するSTQ_Cより前に,LDQ_Lの後からLDQ命令が検出されています。LDQ は再コンパイルするか,ソース・コードを変更することで, シーケンスの外部に移動しなければなりません(第7.3 節を参照)。

             ** Backward branch from 000405B0 to a STx_C sequence at 0004059C
             00040598   C3E00003     br             R31, 000405A8
             0004059C   47F20400     bis            R31, R18, R0
             000405A0   B8100000     stl_c          R0, (R16)
             000405A4   F4000003     bne            R0, 000405B4
             000405A8   A8300000     ldl_l          R1, (R16)
             000405AC   40310DA0     cmple          R1, R17, R0
             000405B0   F41FFFFA     bne            R0, 0004059C

この例では,LDL_LとSTQ_Cの間から分岐が検出されています。この場合, LDx_LとSTx_Cの間に,アーキテクチャで要求されている"フォール・スルー" パスがありません。


注意
LDx_LからSTx_Cへのこの逆向きの分岐は, 「ループ・ローテーション」最適化によって発生する,規則に準拠しないコードの特徴です。

次のMACRO-32ソース・コードは"フォール・スルー"パスがあるものの,ロック・ シーケンス内に可能性のある分岐とメモリ参照があるために,規則に準拠しないコードを示しています。

             getlck: evax_ldql  r0, lockdata(r8)  ; Get the lock data
                     movl       index, r2         ; and the current index.
                     tstl       r0                ; If the lock is zero,
                     beql       is_clear          ; skip ahead to store.
                     movl       r3, r2            ; Else, set special index.
             is_clear:
                     incl       r0                ; Increment lock count
                     evax_stqc  r0, lockdata(r8)  ; and store it.
                     tstl       r0                ; Did store succeed?
                     beql       getlck            ; Retry if not.

このコードを修正するには,INDEXの値を読み込むためのメモリ・アクセスを最初にLDQ_L/STQ_C シーケンスの外部に移動しなければなりません。 次に,ラベルIS_CLEARへの,LDQ_LとSTQ_Cの間の分岐を取り除かなければなりません。 この場合,CMOVEQ命令を使用して分岐を取り除くことができます。 単純な値の移動の周囲にある分岐を取り除くには,多くの場合, CMOVxx命令が役立ちます。次の例では修正されたコードを示しています。

                     movl       index, r2         ; Get the current index
             getlck: evax_ldql  r0, lockdata(r8)  ; and then the lock data.
                     evax_cmoveq r0, r3, r2       ; If zero, use special index.
                     incl       r0                ; Increment lock count
                     evax_stqc  r0, lockdata(r8)  ; and store it.
                     tstl       r0                ; Did write succeed?
                     beql       getlck            ; Retry if not.

7.5 コンパイラのバージョン

ここでは,規則に準拠しないコード・シーケンスを生成する可能性のあるコンパイラのバージョンと, 再コンパイルするときに使用する推奨バージョンについて説明します。

表 7-1にOpenVMSコンパイラの情報を示します。

表 7-1 OpenVMSコンパイラ

以前のバージョン 推奨されるバージョン
BLISS V1.1 BLISS V1.3 以上
DEC C V5.x DEC C V6.0以上
DEC C++ V5.x DEC C++ V6.0以上
DEC Pascal V5.0- 2 DEC Pascal V5.1-11以上
MACRO-32 V3.0 V3.1 for OpenVMS Version 7.1-2以上
V4.1 for OpenVMS Version 7.2以上
MACRO-64 V1.2 下記参照

MACRO-64アセンブラの現在のバージョンでも,ループ回転の問題がまだ発生することがあります。 しかし,MACRO-64ではデフォルトでコードの最適化が実行されないので, この問題が発生するのは,最適化が有効に設定されている場合だけです。SRM_CHECK がMACRO-64コードから規則に準拠しないシーケンスを検出した場合は, 最初に最適化せずに再コンパイルする必要があります。 その後,再びテストしてもシーケンスにフラグが付けられる場合は, ソース・コード自体に修正の必要な非準拠シーケンスが含まれています。

7.6 MACRO-32コンパイラのための,インターロックされたメモリ・シーケンス・ チェック

MACRO-32 Compiler for OpenVMS Alphaバージョン4.1では,非準拠コード・ シーケンスを検出するための追加コード・チェックが実行され,警告メッセージが表示されるようになりました。 次の警告メッセージが表示されることがあります。

BRNDIRLOC branch directive ignored in locked memory sequence

説明: コンパイラはLDx_L/STx_Cシーケンスの内部から.BRANCH_LIKELY ディレクティブを検出しました。

対処法: 対処は必要ありません。コンパイラは.BRANCH_LIKELYディレクティブを無視します。 他にコーディング・ガイドラインの違反がない限り, コードは指定されたとおりに動作します。

BRNTRGLOC branch target within locked memory sequence in routine 'routine_name'

説明: 分岐命令のターゲットがLDx_L/STx_Cシーケンスの内部にあります。

対処法: この警告を回避するには, ソース・コードを変更して,LDx_L/STx_Cシーケンスの内部の分岐またはこのシーケンスへの分岐をなくさなければなりません。 インターロックされたシーケンスからの分岐は有効であり, フラグは付けられません。

MEMACCLOC memory access within locked memory sequence in routine 'routine_name'

説明: LDx_L/STx_Cシーケンスの内部でメモリ読み込みまたは書き込みが発生します。 これは,"MOVL data, R0"などのように,ソース・ コード内の明示的な参照であるか,またはメモリへの暗黙の参照です。 たとえば,データ・ラベルのアドレスのフェッチ(たとえば"MOVAB label, R0")は,リンク・セクション,外部参照を解決するために使用されるデータ領域からの読み込みによって行われます。

対処法: この警告を回避するには, すべてのメモリ・アクセスをLDx_L/STx_Cシーケンスの外部に移動します。

RETFOLLOC RET/RSB follows LDx_L instruction

説明: コンパイラがLDx_L命令の後,STx_C命令の前にRET またはRSB命令を検出しました。これは不正な形式のロック・シーケンスを示します。

対処法: LDx_L命令とSTx_C命令の間にRET 命令やRSB命令が指定されないように,コードを変更します。

RTNCALLOC routine call within locked memory sequence in routine 'routine_name'

説明: ルーチン呼び出しがLDx_L/STx_Cシーケンスの内部で発生します。 これは"JSBサブルーチン"などのソース・コード内の明示的なCALL/JSB であるか,または他の命令の結果発生する暗黙の呼び出しです。 たとえば,MOVCやEDIVなどの一部の命令は,実行時ライブラリへの呼び出しを生成します。

対処法: この警告を回避するには,コンパイラで示されたルーチン呼び出しまたはその呼び出しを生成する命令をLDx_L/STx_C シーケンスの外部に移動します。

STCMUSFOL STx_C instruction must follow LDx_L instruction

説明: コンパイラがLDx_L命令より前にSTx_C命令を検出しました。 これは不正な形式のロック・シーケンスを示します。

対処法: STx_C命令がLDx_L命令の後にくるように, コードを変更します。

7.7 ALONONPAGED_INLINEまたはLAL_REMOVE_FIRSTマクロによるコードの再コンパイル

OpenVMS AlphaのMACRO-32コードのうち,SYS$LIBRARY:LIB.MLBマクロ・ライブラリからALONONPAGED_INLINE またはLAL_REMOVE_FIRSTマクロを起動するコードは,OpenVMS バージョン7.2で再コンパイルして,これらのマクロの正しいバージョンが取得されるようにしなければなりません。 これらのマクロを変更すると, 新しいAlpha 21264 (EV6)プロセッサで検出される可能性のある同期化に関する問題を修正できます。


注意
EXE$ALONONPAGEDルーチン(またはその変形) を呼び出すソース・モジュールは,再コンパイルする必要がありません 。これらのモジュールは,このリリースに含まれているルーチンの正しいバージョンを使用します。


[ 前のページ ] [ 次のページ ] [ 目次 ] [ 索引 ] [ DOC Home ]