日本-日本語 |
|
|
|
OpenVMS マニュアル |
|
HP OpenVMS MACRO コンパイラ
|
目次 | 索引 |
OpenVMS Alpha システムまたは OpenVMS I64 システムにアプリケーションを移植する際に,書き込み可能なグローバル・セクションにある共用データを複数のプロセスが変更する場合は,アプリケーションがシングル・プロセッサ上でのみ動作する場合であっても,特に注意してください。また,メインライン・プロセス・ルーチンが変更するプロセス空間のデータが,非同期システム・トラップ (AST) ルーチンや条件ハンドラでも変更される可能性がある場合は,アプリケーションを調べる必要があります。 Alpha システムにおける読み取り-変更-書き込み操作に関するプログラミング上の問題についての詳細は, Migrating to an OpenVMS AXP System: Recompiling and Relinking Applications 1を参照してください。
警告 不可分性を維持するときに,コンパイラは,Alpha PALcode の非アライン障害ハンドラで扱うことのできない,アラインされたメモリ命令を生成します。この命令では,アラインされていないアドレスに対して,回復不能な予約オペランド・フォルトが発生します。そのため,.PRESERVE ATOMICITY が指定されたすべてのメモリ参照は,アドレスがアラインされている必要があります ( 第 2.11.5 項 を参照)。 |
2.11.2 細分性の維持 |
Alpha 上で VAX MACRO のバイト,ワード,またはアラインされていないロングワードに対するメモリ書き込み命令の細分性を維持するということは,指定されたデータに対して命令が正常に実行され,周囲のデータの一貫性が維持されることを保証するということを意味します。
VAX アーキテクチャには,メモリ内のバイト,ワード,アラインされていないロングワードに対して独立にアクセスする命令があるため,アラインされた同じロングワードの異なるバイトに 2 つのプロセスが同時に書き込んでも,互いに干渉が起こりません。
Alpha アーキテクチャのオリジナルの実装では,アラインされたロングワードおよびクォドワード・オペランドのみをアドレス指定できる命令が定義されていました。ただし,バイトとワードのオペランドのロードと格納が後で追加されました。
Alpha では,長さがロングワード未満のメモリや,アラインされていないメモリにデータ・フィールドを書き込むコードは,クォドワードのロード,変更したデータのクォドワードへの挿入,クォドワードの格納を行う割り込み可能な命令シーケンスを使用する必要があります。この場合,同じクォドワード内の異なるバイトに書き込もうとしている 2 つのプロセスは,実際にはクォドワード全体をロードし,演算を行い,保存します。ロード操作と格納操作のタイミングによっては,どちらかのバイト書き込みが失われる可能性があります。
Itanium アーキテクチャでは,バイト,ワード,ロングワード,クォドワードのアドレス指定が可能なため,アクセスの細分性が簡単に確保でき,オプションや宣言も必要ありません。
コンパイラには,バイト,ワード,アラインされていないロングワードの書き込みの一貫性を保証する /PRESERVE=GRANULARITY オプションがあります。 /PRESERVE=GRANULARITY オプションを指定すると,バイト,ワード,アラインされていないロングワードへの書き込みを行うすべての VAX 命令に対して,細分性が保たれる Alpha 命令が生成されます。また,必要に応じて VAX MACRO ソース・コードのセクションに .PRESERVE GRANULARITY 指示文と .NOPRESERVE GRANULARITY 指示文を挿入し,細分性の維持を有効または無効にすることもできます。
たとえば,命令 MOVB R1, (R2) は,次の Alpha コード・シーケンスを生成します。
LDQ_U R23, (R2) INSBL R1, R2, R22 MSKBL R23, R2, R23 BIS R23, R22, R23 STQ_U R23, (R2) |
LDQ_U 命令と STQ_U 命令の間で,他のコード・スレッドが (R2) が指すデータの一部を変更した場合,そのデータは上書きされて失われます。
次の Itanium コード・シーケンスが生成されます。
st1 [r28] = r9 |
コマンド修飾子または指示文で,同じ命令に対して細分性を維持するように指定した場合, Alpha コード・シーケンスは次のようになります。
BIC R2,#^B0111,R24 RETRY: LDQ_L R28,(R24) MSKBL R28,R2,R28 INSBL R1,R2,R25 BIS R25,R28,R25 STQ_C R25,(R24) BEQ R25, FAIL . . . FAIL: BR RETRY |
この場合,(R2) が指すデータが別のコード・スレッドによって変更されると,操作はリトライされます。
Itanium では,コードはすでに影響のあるメモリ位置にだけ書き込むようになっているため,コード・シーケンスは変わりません。
MOVW R1,(R2) 命令で,細分性を維持するために生成される Alpha コードは,コンパイラのレジスタ・アラインメント・トラッキング機能によって,レジスタ R2 が現在アラインされていると見なされているかどうかに依存します。 R2 がアラインされていると見なされている場合は,コンパイラは基本的に上の MOVB の例と同じコードを生成します。ただし, INSBL 命令と MSKBL 命令の代わりに INSWL 命令と MSKWL 命令が使用され, R2 のアドレスに対する BIC で #^B0110 を使用します。 R2 がアラインされていないと見なされている場合は,ワードが仮にクォドワード境界にまたがっている場合でも正しく書き込まれるように,コンパイラは 2 つの個別の LDQ_L/STQ_C ペアを生成します。
同様に Itanium でも,アドレスがワードにアラインされている場合は,コンパイラは単に st2 [r28] = r9を生成します。
注意 細分性の維持が有効になっている場合,アラインされたワードを書き込むために生成されるコードでは,アドレスがアラインされていないと,実行時に回復不可能な予約オペランド・フォルトが発生します。書き込み先のアドレスがアラインされていない可能性がある場合は,アラインされていないワードに書き込むことができるコードを生成するようにコンパイラに指示します。それには,書き込み命令の直前で,コンパイラ指示文 .SET_REGISTERS UNALIGNED=Rn を使用します。 |
MOVL R1,(R2) 命令の細分性を維持するために,書き込み先のアドレスがアラインされていないと想定される場合でも,コンパイラは常に STL 命令を使用してロングワード全体を書き込みます。アドレスがアラインされていないと, STL 命令は非アライン・メモリ参照のフォルトになります。 PALcode の非アライン・フォルトのハンドラは,アラインされていないロングワードに書き込むために必要な,ロード,マスク,格納を行います。ただし,PALcode は割り込み可能でないため,これによって周囲のメモリが破壊されないことが保証されます。
アプリケーションを OpenVMS Alpha システムに移植する場合,ローカル・プロセッサで実行されているプロセスや,システム内の別のプロセッサで実行されているプロセス,AST ルーチンや条件ハンドラと共用しているメモリに対して,アプリケーションがバイト,ワード,またはアラインされていないロングワードの書き込みを行うかどうかを確認する必要があります。 OpenVMS Alpha システムでの細分性操作に関係する,プログラミング上の問題点についての詳細は, Migrating to an OpenVMS AXP System: Recompiling and Relinking Applications を参照してください。
注意 INSV 命令は,細分性の維持がオンになっている場合に,細分性が正しく維持されるコードを生成しません。 |
2.11.3 不可分性と細分性の優先順位 |
細分性と不可分性の維持をどちらも有効にし,両方の維持が必要な VAX コードをコンパイラが発見すると,細分性よりも不可分性が優先されます。
たとえば,.PRESERVE=GRANULARITY を指定してコンパイルすると,命令 INCW 1(R0) は,割り込まれたら新しいワード値の書き込みをリトライします。しかし,.PRESERVE=ATOMICITY を指定してコンパイルすると,割り込まれたら初期値をフェッチしてインクリメントします。両方のオプションを指定した場合は,後者の動作になります。
また,コンパイラは,細分性を維持するアラインされていないワードおよびロングワードに対するコードを正常に生成できますが,不可分性を維持するアラインされていないワードおよびロングワードに対するコードは生成できません。両方のオプションを指定した場合には,すべてのメモリ参照はアラインされているアドレスに対するものである必要があります。
2.11.4 不可分性が保証できない場合
コンパイラの不可分性の保証は, VAX 命令のメモリ変更操作に対してだけ影響を与えるため, OpenVMS Alpha システムまたは OpenVMS I64 システムにおいて, /PRESERVE=ATOMICITY で解決できない VAX MACRO ソースのコーディング上の問題を調べる際には,特に注意する必要があります。
たとえば,次の VAX 命令があるとします。
ADDL2 (R1),4(R1) |
この命令に対して, /PRESERVE=ATOMICITY (または .PRESERVE ATOMICITY) が指定されていると,コンパイラは次のような Alpha コード・シーケンスを生成します。
LDL R28,(R1) Retry: LDL_L R24,4(R1) ADDL R28,R24,R24 STL_C R24,4(R1) BEQ fail . . . fail: BR Retry |
このコード・シーケンスで,STL_C が失敗すると,加算の前に変更オペランドだけが再読み込みされます。データ (R1) は再読み込みされません。この動作は VAX の動作とは少し異なります。 OpenVMS VAX システムでは,命令全体が割り込みなしで実行されます。 OpenVMS Alpha システムや OpenVMS I64 システムでは,変更オペランドだけが不可分に更新されます。
その結果,データ (R1) の読み込みが不可分であることが必要なコードでは,ロックなどの別の方法を使用して,同じレベルの同期を実現する必要があります。
この命令では,コンパイラは次の Itanium コード・シーケンスを生成します。
ld4 r19 = [r9] sxt4 r19 = r19 adds r16 = 4, r9 $L4: ld4 r17 = [r16] mov.m apccv = r17 mov r15 = r17 sxt4 r17 = r17 add r17 = r19, r17 cmpxchg4.acq r17, [r16] = r17 cmp.eq pr0, pr7 = r15, r17 (pr7) br.cond.dpnt.few $L4 |
別の VAX 命令について考えます。
MOVL (R1),4(R1) |
この命令に対して,不可分性の維持がオンの場合もオフの場合も,コンパイラは次の Alpha コード・シーケンスを生成します。
LDL R28,(R1) STL R28,4(R1) |
この例の VAX 命令は単一の VAX CPU 上で不可分ですが, Alpha 命令シーケンスは単一の Alpha CPU 上で不可分ではありません。 4(R1) オペランドが書き込みオペランドであり,変更オペランドでないため,操作は LDL_L と STL_C を使用した不可分な操作にされません。
OpenVMS I64 システムでは,コード・シーケンスは次のようになります。
ld4 r14 = [r9] sxt4 r14 = r14 adds r24 = 4, r9 st4 [r24] = r14 |
最後に,より複雑な VAX INCL 命令について考えます。
INCL @(R1) |
この命令に対して, /PRESERVE=ATOMICITY (または .PRESERVE ATOMICITY) が指定されていると,コンパイラは次のような Alpha コード・シーケンスを生成します。
LDL R28,(R1) Retry: LDL_L R24,(R28) ADDL R24,#1,R24 STL_C R24,(R28) BEQ fail . . . fail: BR Retry |
ここで,変更データの更新だけが不可分です。変更データのアドレスを取得するために必要なフェッチは,不可分シーケンスの一部になっていません。
OpenVMS I64 システムでは,コード・シーケンスは次のようになります。
ld4 r16 = [r9] sxt4 r16 = r16 $L5: ld4 r14 = [r16] mov.m apccv = r14 mov r24 = r14 sxt4 r14 = r14 adds r14 = 1, r14 cmpxchg4.acq r14, [r16] = r14 cmp.eq pr0, pr8 = r24, r14 (pr8) br.cond.dpnt.few $L5 |
不可分性を維持する場合,コンパイラは変更データがアラインされているものと想定する必要があります。クォドワード境界にまたがったフィールドは, 2 つの読み取り-変更-書き込みシーケンスが必要となるため,不可分に更新できません。
OpenVMS Alpha システムでは,通常のロード命令や格納命令と異なり,アラインされていない LDx_L 命令や STx_C 命令はソフトウェアで処理できないため,アラインされていないアドレスに対する LDx_L 命令や STx_C 命令は,回復不可能な予約オペランド・フォルトを生成します。
OpenVMS I64 システムでは, compare-exchange (cmpxchg) 命令でのアラインされていないアドレスをソフトウェアで処理できないため,実行時に例外が発生します。
OpenVMS Alpha システムでは, /PRESERVE=ATOMICITY (または .PRESERVE ATOMICITY) が指定されていると, INCL (R1) 命令は LDL_L 命令および STL_C 命令を生成するため, R1 はアラインされたロングワードである必要があります。
次の命令があるとします。
INCW (R1) |
OpenVMS Alpha システムでは,この命令に対し,コンパイラは次のようなコード・シーケンスを生成します。
BIC R1,#^B0110,R28 ; Compute Aligned Address Retry: LDQ_L R24,(R28) ; Load the QW with the data EXTWL R24,R1,R23 ; Extract out the Word ADDL R23,#1,R23 ; Increment the Word INSWL R23,R1,R23 ; Correctly position the Word MSKWL R24,R1,R24 ; Zero the spot for the Word BIS R23,R24,R23 ; Combine Original and New word STQ_C R23,(R28) ; Conditionally store result BEQ fail ; Branch ahead on failure . . . fail: BR Retry |
最初の BIC 命令で, #^B0111 ではなく #^B0110 が使用されている点に注意してください。これは,ワードがクォドワード境界にまたがらないようにするためです。そうしないと,メモリの更新が不完全になります。 R1 に格納されているアドレスがアラインされているワードを指していない場合は,ビット 0 がオンになり,BIC 命令ではそのビットがクリアされません。この場合,LDQ_L (Load Quadword Locked) 命令は,回復不可能な予約オペランド・フォルトを生成します。
すべてのバイトはアラインされているため, INCB 命令では #^B0111 を使用し,アラインされたアドレスを生成します。
OpenVMS I64 システムでは, INCW (R1)命令に対して,コンパイラは次のようなコード・シーケンスを生成します。
$L5: ld2 r19 = [r9] mov.m apccv = r19 mov r18 = r19 sxt2 r19 = r19 adds r19 = 1, r19 cmpxchg2.acq r19, [r9] = r19 cmp.eq pr0, pr8 = r18, r19 (pr8) br.cond.dpnt.few $L5 |
コンパイラが不可分性を維持する方法には,コンパイルされた VAX MACRO コードにおいて興味深い副作用があります。
OpenVMS VAX システムでは,マルチプロセッサ・システムにおける共用データへのアクセスを同期させる方法としては,インターロックされる命令だけが正常に機能します。 OpenVMS Alpha のマルチプロセシング・システムでは,不可分性が維持される変更命令とインターロックされる命令をコンパイルした結果得られるコードは,どちらも正常に機能します。これは,コンパイラが両方の命令セットに対して生成する LDx_L と STx_C が,複数のプロセッサにわたって正しく動作するためです。同様に, OpenVMS I64 システムでは, compare-exchange (cmpxchg) 命令が,プロセッサにまたがったインターロック機能を提供します。
このコンパイラの副作用は OpenVMS Alpha システムと OpenVMS I64 システムに固有であり, OpenVMS VAX システムには該当しないため, VAX MACRO コードを OpenVMS Alpha または OpenVMS I64 に移植する際に,コードを両方のシステムで動作させる予定の場合は,この副作用に頼らないようにしてください。
しかし,不可分性が維持されない他の命令に対するインターロックとしてメモリ変更が使用されている場合は,インターロックされる命令を使用する必要があります。これは,Alpha アーキテクチャと Itanium アーキテクチャでは,書き込み順序が厳密には保証されないためです。
たとえば,次の VAX MACRO コード・シーケンスがあるとします。
.PRESERVE ATOMICITY INCL (R1) .NOPRESERVE ATOMICITY MOVL (R2),R3 |
このコード・シーケンスから,次の Alpha コード・シーケンスが生成されます。
Retry: LDL_L R28,(R1) ADDL R28,#1,R28 STL_C R28,(R1) BEQ R28, fail LDL R3, (R2) . . . fail: BR Retry |
Alpha アーキテクチャと Itanium アーキテクチャのデータ・フェッチ動作に起因して,(R1) への格納が処理されるよりも前に (R2) からデータが読み込まれる可能性があります。 INCL (R1) 命令をロックとして使用し,ロックが設定される前に (R2) のデータがアクセスされないようにすると, (R1) のインクリメントよりも前に (R2) の読み込みが行われる可能性があり,保護されません。
VAX のインターロックされる命令では,インターロックされる命令の前後に Alpha の MB (メモリ・バリア) 命令または Itanium の mf (メモリ・フェンス) 命令が生成されます。これにより,インターロックされる命令をまたいでメモリのロードが移動されなくなります。
OpenVMS I64 では,コード・シーケンスは次のようになります。
$L7: ld4 r16 = [r9] mov.m apccv = r16 mov r15 = r16 sxt4 r16 = r16 adds r16 = 1, r16 cmpxchg4.acq r16, [r9] = r16 cmp.eq pr0, pr10 = r15, r16 (pr10) br.cond.dpnt.few $L7 ld4 r3 = [r28] sxt4 r3 = r3 |
次のコード・シーケンスがあるとします。
ADAWI #1,(R1) MOVL (R2),R3 |
このコード・シーケンスは,次の Alpha コード・シーケンスを生成します。
MB Retry: LDL_L R28,(R1) ADDL R28,#1,R28 STL_C R28,(R1) BEQ R28, Fail MB LDL R3, (R2) . . . Fail: BR Retry |
OpenVMS I64 では,次のようなコード・シーケンスが生成されます。
mf $L8: ld2 r23 = [r9] mov.m apccv = r23 adds r24 = 1, r23 cmpxchg2.acq r14, [r9] = r24 cmp.eq pr0, pr11 = r23, r14 (pr11) br.cond.dpnt.few $L8 mf ld4 r3 = [r28] sxt4 r3 = r3 |
MB 命令または mf 命令があると,その前にあるすべてのメモリ操作が完了してからその後のメモリ操作が開始されるようになります。
1 このマニュアルはアーカイブ扱いになっています。このマニュアルの保守は行われておらず, OpenVMS ドキュメント・セットにも含まれていません。ただし,http://www.hp.com/go/openvms/doc からオンラインで参照することができます。 |
目次 | 索引 |
|