# Compaq OpenVMS
V7.3 リリース・ノート【翻訳版】

前へ | 次へ | 目次 | 索引

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

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

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

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

# 8.1 必要なコード・チェック

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

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

# 8.2 コード分析ツールの使用

SRM_CHECK ツールは，OpenVMS Alpha Version 7.3 Operating System 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 とリスト・ファイルを調べることで検出できます。

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

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

- OpenVMS コンパイラの一部のバージョンでは，「ループ・ローテーション」と呼ばれる最適化中に規則に準拠しないコード・シーケンスが発生します。この問題が発生するのは，ASM 関数を使用して C/C++ ソースに埋め込まれているアセンブリ言語コード内でLDx_L/STx_C 命令を使用する C または C++ プログラムの場合か， MACRO--32 または MACRO--64 で作成されたアセンブリ言語の場合だけです。LDx_L 命令と STx_C 命令の間に分岐が発生していることもありました。

  この問題は再コンパイルすることで対処できます。

- 非常に古い BLISS，MACRO--32，DEC Pascal，または DEC COBOL コンパイラでコンパイルされた一部のコードには，規則に準拠しないシーケンスが含まれていることがあります。これらのコンパイラの初期のバージョンには，コード・スケジューリングのバグがあり，load_locked の後にロードが誤ってスケジューリングされていました。

  この問題は再コンパイルすることで対処できます。

- ごくまれに，空きレジスタの数が少なすぎる場合には， MACRO--32 コンパイラは BBSSI 命令または BBCCI 命令に対して，規則に準拠しないコード・シーケンスを生成することがあります。

  この問題は再コンパイルすることで対処できます。

- MACRO--64 または MACRO--32 が誤ってコーディングされ，アセンブリ言語が ASM 関数を使用して C または C++ ソースに組み込まれ，誤ってコーティングされたために，エラーが発生することがあります。

  この問題が発生する場合は，ソース・コードを変更しなければなりません。新しい MACRO--32 コンパイラは，規則に準拠しないコードに対して，コンパイル時にフラグを付けます。

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

# 8.4 コーディングの必要条件

『Alpha Architecture Reference Manual 』では，プロセッサ間のデータの不可分な更新を実行する方法を説明しています。特に『Third Edition』には，この問題に関するさらに詳しい情報が含まれています。また，インターロックされたメモリ・シーケンスの規則について詳しく説明されています。

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

- インターロックされたシーケンスで，LDx_L (load locked) 命令と STx_C (store conditional) 命令の間にメモリ操作 (load または store) を指定できない。

- LDx_L 命令と STx_C 命令の間で分岐を実行できない。このような場合は，分岐を実行せずに，LDx_L からSTx_C に「フォール・スルー」しなければならない。

  ターゲットが LDx_L とそれに対応する STx_C の間にある分岐を実行すると，規則に準拠しないシーケンスが作成される。たとえば，次の例で "label" への分岐を実行すると，分岐命令自体がシーケンスの内部にあるか外部にあるかにかかわらず，規則に準拠しないコードが作成される。

                      LDx_L  Rx, n(Ry)
                      ...
               label: ...
                      STx_C  Rx, n(Ry)

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

- LDx_L とSTx_C の間のメモリ操作 (LDx/STx)

- LDx_L と STx_C の間に宛先がある分岐

- 先行する LDx_L 命令のない STx_C 命令

  これは通常，LDx_L から STx_C へ逆方向分岐が実行されることを示します。ただし，デバイス・メールボックス書き込みを実行するハードウェア・デバイス・ドライバは例外です。これらのドライバは，STx_C を使用してメールボックスに書き込みを実行します。この状況は初期の Alpha システムでのみ検出され，PCI ベースのシステムでは検出されません。

- LDx_L と STxC の間にある余分な命令

  AARM では，LDx_l と STx_C の間の命令の数を 40 未満にすることを推奨しています。理論的には，40 より多くの命令があると，シーケンスが完了しないようにするためにハードウェア割り込みが発生します。しかし，実際にはこの状況が発生したという報告はありません。

次の例に，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)

この例では，LDQ 命令が LDQ_L の後，STQ_C の前に検出されています。 LDQ は，再コンパイルまたはソース・コードの変更によって，このシーケンスの外部に移動しなければなりません ( 第 8.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.

# 8.5 コンパイラのバージョン

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

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

表 8-1 OpenVMS コンパイラ
旧いバージョン | 推奨最小バージョン
--- | ---
BLISS V1.1 | BLISS V1.3
DEC Ada V3.5 | Compaq Ada V3.5A
DEC C V5.x | DEC C V6.0
DEC C++ V5.x | DEC C++ V6.0
DEC COBOL V2.4，V2.5 | Compaq COBOL V2.6
DEC Pascal V5.0-2 | DEC Pascal V5.1-11
MACRO--32 V3.0 | OpenVMS バージョン 7.1-2 については V3.1 OpenVMS バージョン 7.2 については V4.1
MACRO--64 V1.2 | 下記参照

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

# 8.6 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 ルーチン (またはその変形) を呼び出すソース・モジュールは，再コンパイルする必要がありません 。これらのモジュールは，ユーザに意識させることなく，このリリースに含まれているルーチンの正しいバージョンを使用します。

前へ | 次へ | 目次 | 索引