導入: なぜON-Unitでのレジスタ保護が重要なのか
メインフレーム開発において、例外処理はシステムの堅牢性を左右する生命線です。PL/Iなどで多用される「ON-Unit」は、ハードウェアやランタイムで発生した例外を捕捉するための強力な仕組みです。しかし、例外発生時にCPUの汎用レジスタ(R0-R15)が不適切に書き換えられてしまうと、制御がメイン処理に戻った瞬間にシステムが異常終了(アベンド)します。本稿では、レジスタの状態を保護し、安全に処理を継続または復帰させるための技術的ポイントを解説します。
基礎知識: レジスタとコンテキストの整合性
メインフレームのプログラムが実行される際、汎用レジスタにはアドレスや演算結果などの「現在のコンテキスト」が保持されています。例外が発生すると、ランタイムは即座にレジスタをスタック領域へ退避させます。
ON-Unitは、この退避されたレジスタセットを保持したまま実行されます。ここでのポイントは、ハンドラ内でレジスタを直接操作した場合、ハンドラ終了後に元の値へ正しくリストア(復旧)される必要があるという点です。これを意識しないと、呼び出し元のプログラムが予期せぬアドレスを参照し、深刻なデータ破壊を招く恐れがあります。
実装/解決策: 安全なコンテキスト復帰
例外処理から復帰する際は、必ず RESUME 文を使用してください。これにより、ランタイムが退避していたレジスタ値をハードウェアへ正確に書き戻し、中断直前の状態を完璧に再現します。もしハンドラ内で複雑な判定を行い、処理を別地点へ移す場合は GOTO を使用しますが、この場合もスタックフレームの整合性が保たれていることを確認する必要があります。
サンプルプログラム: 安全なON-Unitの実装例
以下は、ゼロ除算発生時にレジスタ保護を意識しつつ、安全に例外をハンドリングするPL/Iのコード例です。
/ ゼロ除算例外をトラップするハンドラ /
ON ZERODIVIDE
BEGIN;
/ このブロック内ではR0-R15はシステムによって保護されている /
PUT SKIP LIST(‘例外を検知しました。ログを記録します。’);
/
必要に応じて特定の処理を行い、
RESUMEによって中断直前のレジスタ状態へ確実に復帰させる
/
RESUME;
END;
/ メイン処理 /
DCL X FIXED BIN(31) INIT(0);
DCL Y FIXED BIN(31) INIT(10);
/ ここでゼロ除算が発生しても上記ハンドラが安全に処理を代行する /
Y = Y / X;
PUT SKIP LIST(‘正常に処理が継続されました。’);
応用・注意点: 現場での落とし穴
現代のマイグレーション環境やマルチスレッド環境では、単なるレジスタ保護だけでなく「スレッド状態(ThreadLocal)」の一貫性も考慮が必要です。
特に注意すべきは、外部APIやDBアクセス中に例外が発生した場合です。レジスタは復帰できても、外部リソース側の状態が「処理中」のまま取り残されるケースがあります。
1. クリーンアップの徹底: ON-Unitの最後には、必ずリソースの解放やロールバック処理を配置すること。
2. 状態一貫性の保証: 非同期処理や外部連携を行っている場合は、例外後の「再開ポイント」が論理的に正しいかを確認してください。
レジスタ保護は物理的な整合性の保証ですが、ビジネスロジックの一貫性はプログラマが明示的に保護する必要があることを忘れないでください。

コメント