AIX トランザクション・メモリー・ プログラミング
トランザクション・メモリー (TM) は、その他のプロセス・スレッドや アプリケーションからアトミックに見えるストレージ操作を、 プロセス・スレッドが実行できるようにする共有メモリー同期構造です。
概説
TM は、ロック・ベースのコードのクリティカル・セクションを、ロックをかけずに実行できる構造です。 IBM® POWER 8 プロセッサーは、 TM プログラミングを実装した最初のプロセッサーです。
- ロック・ベースのアプリケーションのオプティミスティック実行 – TM は、ロックを獲得せずに、コードのクリティカル・セクションの投機的実行をサポートします。 この方法には、パフォーマンスに適した調整がされていない 現行のロックを使用して、アプリケーションにきめ細かくロックをかけられるという利点が あります。
- 高水準言語でのトランザクションのプログラミング – トランザクション・プログラミング・モデルは、ロック・ベースの共有メモリー・プログラムに比べて高い生産性が得られる、業界全体の標準として普及しつつあります。
- チェックポイント/ロールバックの使用 – TM は、アーキテクチャーの状態を復元するためのチェックポイントとして使用されます。 この方法を使用して、 ランタイム・コードの最適化または生成時の予測的コンパイラー最適化、およびチェックポイントのシミュレーションを 使用可能にします。
TM 機能を使用するために、プロセス・スレッドは、
ストレージ・アクセスやトランザクションのシーケンスの最初と最後に、tbegin.
命令および tend.
命令を使用してマークを付けます。
tbegin.
命令は、トランザクション実行を開始します。
トランザクション実行中に、ロードおよび保管はアトミックに発生するように見えます。
tend.
命令は、トランザクション実行を終了します。
トランザクションが
完了前に停止すると、tbegin.
命令の
実行後に行われたストレージ更新は
ロールバックされます。同様に、レジスターのサブセットの内容も
tbegin.
命令が実行される前の状態に
ロールバックされます。トランザクションが完了前に停止すると、ソフトウェア障害ハンドラーが
開始されます。障害は、一時的なタイプの可能性または永続的なタイプの
可能性があります。障害ハンドラーは、トランザクションを再試行するか、
障害の性質に応じて異なるロック構造または論理パスの採用を
選択することができます。
AIX® オペレーティング・システムは、 TM の使用をサポートし、これにはコンテキスト・スイッチおよび割り込みを網羅する TM 状態管理処理が 含まれます。
チェックポイント状態
トランザクションが開始されると、
プロセッサーのチェックポイント状態を表すレジスター・セットが
保存されます。トランザクションで障害が発生した場合、レジスター・セットは、
トランザクション開始前の時点に復元されます。プロセッサーのチェックポイント状態は、
トランザクション開始前状態とも
呼ばれます。チェックポイント状態には、問題プログラム状態書き込み可能レジスター
(CR0
、FXCC
、EBBHR
、EBBRR
、BESCR
のレジスターを除く)、パフォーマンス・モニター・レジスター、および TM SPR が含まれます。
treclaim.
命令が実行されると、それぞれのレジスターに
コピーされます。このプロセスを使用して、特権コードは値の保存または変更を
行うことができます。チェックポイント状態は、
新規の trechkpt.
命令が実行されると、ユーザー・アクセス可能なそれぞれのレジスターから
見込みレジスターに再度コピーされます。名前 | 名称 | 説明 | 特権 mtspr | 特権 mfspr | サイズ (ビット) | SPR |
---|---|---|---|---|---|---|
FSCR | 機能の状況および制御のレジスター | 問題プログラム状態にある使用可能な機能を 制御するとともに、機能使用不可割り込みの原因を示します。 | yes | あり | 64 | 153 |
TEXASR | トランザクションの例外および要約のレジスター | トランザクション障害ハンドラーで使用される、 トランザクション・レベル情報および要約情報が入っています。ビット 0 から 31 には、 障害の原因が入っています。 | なし | なし | 64 | 130 |
TFHAR | トランザクション障害ハンドラー・アドレス・レジスター | ソフトウェア障害ハンドラーの EA を記録します。
TFHAR レジスターは、トランザクションを開始した tbegin. 命令用に
常に NIA に設定されます。 |
なし | no | 64 | 128 |
TFIAR | トランザクション障害命令アドレス・レジスター | 障害の原因となった命令の正確な EA を 設定します (可能な場合)。TFIAR レジスターの正確性は、 TEXASR レジスターの「正確」フィールド (ビット 37) に記録されます。 | なし | no | 64 | 129 |
TEXASRU | トランザクションの例外および要約のレジスター (上位半分) | TEXASR レジスターの上位半分。 | no | なし | 32 | 131 |
名前 | フィールド | 値の意味 | ビット |
---|---|---|---|
TEXASR | 障害コード (注: ビット 7 は「障害の永続」フィールドと 呼ばれる) | トランザクション障害コード | 0:7 |
不許可 | 0b1 - アクセス・タイプの命令は許可されません。 | 8 | |
ネスティング・オーバーフロー | 0b1 - 最大トランザクション・レベルを超えました。 | 9 | |
フットプリント・オーバーフロー | 0b1 - トランザクション・ストレージ・アクセスのトラッキング限度を 超えました。 | 10 | |
自己誘発競合 | 0b1 - 自己誘発競合が中断状態で 発生しました。 | 11 | |
非トランザクション競合 | 0b1 - 他のプロセッサーによる非トランザクション・アクセスと 競合が発生しました。 | 12 | |
トランザクション競合 | 0b1 - 別のトランザクションと競合が発生しました。 | 13 | |
変換無効化競合 | 0b1 - TLB 無効化と競合が発生しました。 | 14 | |
実装固有 | 0b1 - トランザクション失敗の原因となった 実装固有の状態。 | 15 | |
命令取り出し競合 | 0b1 - スレッドによる命令取り出しまたはトランザクションにより以前書き込まれた ブロックから実行された別のスレッドによる 命令取り出し。 | 16 | |
今後の障害事例用に予約済み | 17:30 | ||
異常終了 | 0b1 – 特定の TM 命令の実行が原因で中止されました。 | 31 | |
中断状態 | 0b1 – 中断状態で障害が記録されました。 | 32 | |
予約済み | 33 | ||
特権 | 障害記録時にスレッドは
特権状態 ([MSRHV||PR] ) でした。 |
34:35 | |
障害要約 (FS) | 0b1 - 障害が検出されて記録されました。 | 36 | |
TFIAR 正確 | 0b0 - 「TFIAR」フィールドの値は概算値です。 0b1 - 「TFIAR」フィールドの値は 正確な値です。 |
37 | |
ROT | ROT 以外の ROT が開始されると 0b1 に設定されます。 |
38 | |
予約済み | 39:51 | ||
トランザクション・レベル (TL) | アクティブなトランザクションのトランザクション・レベル (ネストの深さ + 1) には、
以下の値が入ります。
注: 1 という値は、外部トランザクションに対応します。
1 より大きい値は、ネストされたトランザクションに対応します。
|
52:63 |
- トランザクション障害が記録されると、
TEXASR
レジスターの 8 ビットから 31 ビットの範囲にある 1 ビットのみが設定されます。 設定される単一ビットは、 特定の命令やイベントが原因で障害が発生したことを示します。 - トランザクションのみロールバック (ROT) は、1 つの単位としてのみ実行され、それ以外は実行されない一連の命令です。 この構造により、大量の命令を最小のコストで予測的に実行することが可能になります。ROT は、通常のトランザクションとしてのアトミックな性質 (通常のトランザクションの同期化属性および逐次化属性) を完全には備えていません。 したがって、ROT を共有データの操作に使用してはなりません。
ソフトウェア障害ハンドラー
tbegin.
命令の後の命令にリダイレクトされ、
CR0 は次のように設定されます。0b101 || 0
または
0b010 || 0
tbegin.
命令の後の命令は、
CR0 のビット 2 に指定されたブランチ命令でなければなりません。例えば、
tbegin.
命令が実行されると beq
ブランチ命令が
CR0 のビット 2 に指定されます。ブランチのターゲットは、トランザクション失敗を処理する
コード・セクションにする必要があります。トランザクション開始時に tbegin.
命令が
正常に実行されると、CR0 は
次のいずれかに設定されます。0b000 || 0 or 0b010 || 0
TEXASR
の
ビット 0 から 31 は、障害の原因を報告します。
ビット 0 から 7 の障害コード (FC) フィールドは、
以下のシナリオで使用されます。
treclaim.
命令を使用することにより、特権スーパーバイザー・コードまたは特権ハイパーバイザー・コードで 障害を発生させる。tabort.
命令の形式を使用することにより、問題プログラム状態のコードで障害を発生させる。
TEXASR
の
ビット 7 に 1 の値がある場合は、障害は永続的であるため、トランザクションが再試行されると
失敗することを表します。AIX オペレーティング・システムで
予約された障害コードは、/usr/include/sys/machine.h. ディレクトリーに定義された
障害の原因を示します。サンプル・トランザクション
lock_based_update
ラベルにある別のコード・パスにフォールバックします。
代替パスのコードは表示されていません。trans_entry:
tbegin # Start transaction
beq failure_hdlr # Handle transaction failure
stw r5, 0(r4) # Write to memory pointed to by r4.
tend. # End transaction
b trans_exit
failure_hdlr: # Handle transaction failures:
mfspr r4, TEXASRU # Read high-order half of TEXASR
andis. r5, r4, 0x0100 # Is the failure persistent?
bne lock_based_update # If persistent, acquire lock and
# then perform the write.
b trans_entry # If transient, try again.
lock_based_update:
trans_exit:
トランザクション・メモリー機能のランタイム判別
プログラムでは、POWER ISA の TM カテゴリーをシステムがサポートするかどうかを、
getsystemcfg
サブルーチンを使用して
SC_TM_VER
システム変数を読み取ることにより判断できます。
プログラム内の TM 機能を判別するために、__power_tm()
マクロが /usr/include/sys/systemcfg.h ファイルに
提供されています。このマクロが役に立つのは、
TM 機能がある時に TM 機能を条件付きで使用するソフトウェア、
または TM 機能がない時にロック・ベースのコード・パスと同等の機能を
使用するソフトウェアの場合です。
拡張コンテキスト構造
ベクトル状態およびユーザー・キーを サポートするための拡張コンテキスト構造のサポートは、 以前のバージョンの AIX オペレーティング・システムで 導入されました。既存の拡張コンテキスト構造の サポートはさらに拡張されて、TM に必要なマシン状態を サポートします。
拡張コンテキストは、トランザクション・プロセス・スレッドが最初に TM を使用する時に、
スレッドごとに割り振られて固定されます。拡張コンテキスト領域の
割り振りおよび固定を行えないと、プロセスは、プロセスを終了させる
SIGSEGV
シグナルを
受け取ります。
マシン・コンテキスト情報は、シグナル・ハンドラーに提供される sigcontext
構造に
含まれています。シグナル・ハンドラーが戻ると、
sigcontext
構造に存在するマシン・コンテキストが
アクティブになります。sigcontext
構造は、実際はより大きな ucontext
構造のサブセットです。
この 2 つの構造は
sizeof(struct sigcontext)
までに関しては同じです。
AIX オペレーティング・システムがシグナル・コンテキストを
作成してシグナル・ハンドラーに受け渡されるようにすると、ucontext
構造がシグナル・ハンドラーのスタック上に
作成されます。シグナル・コンテキストのマシン・コンテキスト部分には、
アクティブなマシン状態すべて (意識せずに中断された
コンテキストの揮発性および不揮発性の状態を
含む) が含まれている必要があります。ucontext
構造には、
拡張コンテキスト情報を使用できるかどうかを判別するインジケーターが
含まれています。
ucontext
構造内の __extctx
フィールドは、
/usr/include/sys/context.h ファイルに定義された拡張コンテキスト構造のアドレスです。
ucontext
構造内の __extctx_magic
フィールドは、
__extctx_magic
フィールドの値が __EXTCTX_MAGIC
と等しい場合に
拡張コンテキスト情報が有効かどうかを示します。
TM 機能を使用するスレッドの追加のマシン状態は、コンテキスト拡張のメンバーとして
復元されて、シグナルの引き渡しと戻しの一部である ucontext
構造に
保存されます。
アプリケーションは、トランザクション・メモリーの使用を明示的に使用可能にした場合、コンパイラーによる __EXTABI__
の暗黙的定義によって組み込まれる __extctx
フィールド用のスペースを既に持つ、拡張サイズの ucontext
構造を選択します。
拡張 ucontext
構造は、
__AIXEXTABI
を明示的に定義することによって選択することもできます。
トランザクション状態または中断状態にある場合、libc のサブルーチンgetcontext()
、setcontext()
、makecontext()
、
および swapcontext()
は、
サポートされません。トランザクション内でサブルーチンが呼び出されると、
サブルーチン getcontext()
、setcontext()
、makecontext()
では、
TM_LIBC
タイプの永続的トランザクション障害が発生します。
この障害は /usr/include/sys/machine.h ファイルに定義されています。
swapcontext()
サブルーチンが
トランザクション内で呼び出されると、
以下のような動作になります。swapcontext()
サブルーチンがトランザクション状態の場合、TM_LIBC
タイプの永続的なトランザクション障害が発生します。swapcontext()
サブルーチンが中断状態の場合、 トランザクションは失敗し、指定されたucontext
構造がスワップインされて、 指定されたucontext
構造によりプログラムの実行が再開されます。swapcontext()
サブルーチンが戻った後の結果の状態および後続の動作は 定義されていません。
サブルーチン getcontext()
、setcontext()
、
および swapcontext()
がトランザクション状態以外で呼び出されると、
サブルーチンは、ucp
または oucp
パラメーターで指し示される
ucontext
構造との間で拡張 TM コンテキストの
取得も復元も行いません。
現在の拡張 TM コンテキストを使用して setcontext()
サブルーチンまたは swapcontext()
サブルーチンが
呼び出される場合、エラーは発生しません。
拡張コンテキストについて詳しくは、 /usr/include/sys/context.h ヘッダー・ファイルを参照してください。
シグナルの送達
トランザクション中、アプリケーションが受け取った非同期シグナルは非トランザクション状態で送達されます。トランザクション状態の場合、同期シグナルの送達は
許可されないだけではなく、/usr/include/sys/machine.h ファイルに定義されている
TM_SYNC_SIGNAL
タイプの永続的トランザクション障害が
発生します。
位置合わせ割り込みおよびプログラム割り込み
トランザクション状態では、
正しくない操作または、
TM_ALIGN_INT
タイプまたは TM_INV_OP
タイプの
永続的トランザクション障害 (/usr/include/sys/machine.h ファイルに定義) のエミュレーション結果が
要求される操作が原因で、位置合わせ割り込みおよびプログラム割り込みが発生します。
中断状態の場合、位置合わせ割り込みおよびプログラム割り込みは、非推定セマンティクスを使用して正常に処理されます。
システム・コール
システム・コールは、トランザクション内で
起動しないことをお勧めします。システム・コールがトランザクション内でサポートされるのは、
トランザクションが tsuspend.
命令により
中断される場合のみです。
プロセッサーまたはスレッドがトランザクションを処理しており、
そのトランザクションが中断されない間にシステム・コールが呼び出されると、
システム・コールは AIX カーネルによって起動されず、関連するトランザクションは
永続的に失敗します。このエラーが発生すると、TEXASR
レジスターの FC フィールドには
TM_ILL_SC
障害コードが入ります。このコードは、
/usr/sys/include/machine.h ファイルに定義されています。
アプリケーション・プログラマーが トランザクションを明示的に中断している場合、中断された トランザクション配下で実行されるいずれの操作も持続するものと 見なされます。中断状態の間に起動されたシステム・コールにより実行される操作はいずれも、トランザクションが失敗した場合でもロールバックされません。
AIX オペレーティング・システムは、 トランザクション状態の間のシステム・コールの実行をサポートしていません。これは、システム・コールの背後で AIX により実行されるあらゆる操作 (入出力を含む) をロールバックする方法がないためです。
setjmp() サブルーチンおよび longjmp() サブルーチン
setjmp()
サブルーチンおよび longjmp()
サブルーチンは、
トランザクション状態または中断状態ではサポートされません。これは、ジャンプ・バッファーの設定およびバッファーへのジャンプ・バックの影響があるためです。
以下のシナリオを考えてみます。-
setjmp()
サブルーチンがトランザクション内で呼び出され、 対応するlongjmp()
サブルーチンがトランザクション終了後に 呼び出されると、これは、現在は無効になっている見込み状態に 対してのジャンプです。 -
setjmp()
サブルーチンがトランザクションより前に 呼び出されると、対応するlongjmp()
サブルーチンは、 トランザクションの実行結果が終了、失敗、または異常終了であるかどうかに 関わらず、トランザクションが開始される前の状態にジャンプします。 -
setjmp()
サブルーチンがトランザクション内で 呼び出され、その後でトランザクションが異常終了すると、setjmp()
サブルーチンにより 行われたジャンプ・バッファーへの更新は、行われていないように 見えます。
setjmp()
サブルーチンがトランザクション内で
呼び出されると、/usr/include/sys/machine.h ファイルに定義されている
TM_LIBC
タイプまたは TM_ILL_SC
タイプの永続的トランザクション障害が
発生します。
longjmp()
サブルーチンがトランザクション内で呼び出されると、以下のような動作になります。longjmp()
サブルーチンがトランザクション状態の場合、 /usr/include/sys/machine.h ファイルに定義されているTM_LIBC
タイプまたはTM_ILL_SC
タイプの永続的トランザクション障害が発生します。longjmp()
サブルーチンが中断状態の場合、 トランザクションは失敗し、指定されたジャンプ・バッファーが復元されて、プログラムの実行は 対応するsetjmp()
サブルーチンに戻ります。setjmp()
サブルーチンがlongjmp()
サブルーチンから 戻った後の結果の状態および後続の動作は定義されていません。
コンパイラー
トランザクション・メモリーを
サポートする AIX オペレーティング・システムのコンパイラーは、
AIX ABI に準拠している必要があります。TM が使用可能な場合、
C または C++ のコンパイラーは、 __EXTABI__
を事前定義する必要があります。
詳しくは、コンパイラーの資料を参照してください。
アセンブラー
AIX オペレーティング・システムの アセンブラーは、/usr/ccs/bin/as にあり、 POWER ISA 内の TM 用に定義され、 POWER8 プロセッサーにより実装された追加の命令セットをサポートします。ソース・ファイル内で –m pwr8 アセンブリー・モードまたは .machine pwr8 疑似 op を使用して、TM 命令のアセンブリーを可能にすることができます。 詳しくは、アセンブリー言語解説書を参照してください。
デバッガー
/usr/ccs/bin/dbx デバッガーは、
TM プログラムのマシン・レベルのデバッグをサポートします。このサポートには、新規のトランザクション・メモリー命令の逆アセンブルと、
TM SPR (TEXASR
、TEXASRU
、TFIAR
、および TFHAR
レジスター) の表示が含まれます。
トランザクション内に
ブレークポイントを設定すると、トランザクションは、ブレークポイントが検出されるたびに必ず無条件に失敗します。したがって、推奨される方法は、失敗しているトランザクションをデバッグしてトランザクションの障害ハンドラーにブレークポイントを設定し、ブレークポイントが検出された時点で TEXASR
レジスターおよび TFIAR
レジスターを表示して障害の原因と場所を特定することです。
TEXASR
、TFIAR
、
および TFHAR
のレジスターは、$texasr
、$tfiar
、または $tfhar
のパラメーターを指定した print サブコマンドを使用して表示することができます。TFIAR
レジスター、
および TFHAR
レジスターで検出されたアドレスに関連するコード行は、
次の例のような list サブコマンドを使用して表示できます。(dbx) list at $tfiar
dbx tm_status
サブコマンドは、
TEXASR
レジスターの内容の
表示および解釈を行うために使用されます。このサブコマンドは、トランザクション障害の
特性を判別するために使用されます。サード・パーティーのデバッガーは、
スレッドの TM 状態を読み取るための新しい PTT_READ_TM
ptrace
操作の形式で使用できます。詳しくは、
ptrace
の資料を参照してください。
トレース・サポート
AIX トレース機能は、 AIX オペレーティング・システムで実行される TM 操作用の一連のトレース・イベントを含むように拡張されており、これには、 トランザクション障害の原因となる優先使用およびトランザクション障害の原因になる可能性のある その他のさまざまな操作が含まれています。トレース・イベント ID 675 を trace コマンドおよび trcrpt コマンドへの入力として使用し、 TM 関連のトレース・イベントを表示できます。
コア・ファイル
AIX スレッド・ライブラリー
トランザクション・メモリーの使用は、
M:N スレッドを使用するアプリケーションではサポートされません。複数のスレッドが単一カーネル・スレッドを
共有する環境では、トランザクション・スレッドで未定義の動作が
発生する可能性があります。M:N スレッドを使用するアプリケーションで
トランザクション・メモリーを使用すると、
TM_PTH_PREEMPTED
の障害コードが TEXASR
レジスターに設定されて、
永続的トランザクション障害になるおそれがあります。