【実務・中級編】OPTIONS(REENTRANT)とマルチタスク環境 – PL/Iの基本構文とデータ制御実践ガイド

メインフレームの真髄:再入可能(REENTRANT)なPL/Iプログラム設計と静的ストレージの罠

諸君、お疲れ様。今日も今日とて、数十年前に書かれたレガシーコードの解析と格闘していることだろう。

PL/Iという言語は、COBOLのような「お作法」で縛り付ける言語とは異なり、自由度が極めて高い。しかし、その自由度は「マルチタスク環境」や「CICS」といったシビアな舞台では、一歩間違えればメモリ破壊という名の地獄への入り口となる。

今日は、特にCICS環境やマルチスレッド環境における「REENTRANT(再入可能)」コードの設計について、現場の知見を叩き込んでいく。これが理解できていないと、複数のトランザクションが同時に動いた瞬間にデータが化けるという、最も精神を削るデバッグ案件に追われることになるからな。

1. なぜ「REENTRANT」が必要なのか?

CICSやマルチスレッド環境において、一つのプログラムコードは複数のユーザー(タスク)によって同時に共有される。もし、プログラムの中に「静的ストレージ(STATIC変数)」を置いて、そこに作業中のデータを保持しようとすればどうなるか?

Aさんのトランザクションが書き込んだ値が、実行中にBさんのトランザクションによって上書きされる。これが「データ競合」だ。これを防ぐ唯一の解が、「プログラムを再入可能(REENTRANT)にする」ことだ。

基本ルール:STATICを捨て、AUTOMATICを愛せ

PL/Iのデフォルトのストレージクラスを理解しているか?

  • AUTOMATIC: プロシージャが呼び出されるたびにスタック上に確保される。これが再入可能性の鍵だ。
  • STATIC: プログラム実行中、常に同じメモリ番地を占有する。これが再入可能性の敵だ。

REENTRANTを宣言するということは、「このコードは自分自身の静的領域には何も書き込まないし、依存もしない」とシステムに誓約書を出すようなものだ。

2. 実践的なコーディング例:REENTRANTな構造

以下のコードを見てほしい。CICS環境を想定した、ある種の標準的なアプローチだ。

1
/ ————————————————————- /
/ プログラム名: DEMOREENT /
/ 概要: 再入可能(REENTRANT)なPL/Iプログラムの構造例 /
/ ————————————————————- /
DEMOREENT: PROCEDURE OPTIONS(MAIN, REENTRANT);

/ ビルトイン関数の宣言は明示的に行うのが現場の鉄則 /
DCL SUBSTR BUILTIN;
DCL LENGTH BUILTIN;

/

  • [ポイント]
  • ここでSTATIC宣言をしてはならない。
  • 自動変数(AUTOMATIC)はスタック上に生成されるため、
  • 複数のタスクが並行動作しても競合しない。

/
DCL WORK_AREA_CHAR CHAR(80) AUTOMATIC;
DCL RC FIXED BIN(31) AUTOMATIC;

/

  • ONユニットの制御フロー
  • 異常終了を捕捉し、制御を安全に終了させる

/
ON ERROR BEGIN;
PUT SKIP LIST(‘予期せぬエラーが発生しました。ログを調査してください。’);
SIGNAL FINISH;
END;

/

  • VSAMアクセスやファイル操作もこのAUTOMATIC変数経由で行う。
  • 静的な作業領域は厳禁だ。

/
WORK_AREA_CHAR = ‘処理開始’;

/

  • メイン処理ロジック
  • ここに業務ロジックを記述する

/
CALL PROCESS_DATA(WORK_AREA_CHAR);

RETURN;

/ 内部サブプロシージャも同様に再入可能にする /
PROCESS_DATA: PROCEDURE(IO_DATA);
DCL IO_DATA CHAR(80) PARM;
/ … 処理ロジック … /
END PROCESS_DATA;

END DEMOREENT;

3. 現場で生き残るための「警告」

静的ストレージは「読み取り専用」と心得る

どうしても定数テーブル(ルックアップテーブルなど)をSTATICで持ちたい場合があるだろう。その場合は、`DCL MY_TABLE CHAR(100) STATIC INIT(…)` と宣言し、絶対に実行時に値を書き換えない(Read-Onlyとして扱う)こと。書き換える必要があるなら、それはSTATICに置くべきではない。

ONユニットの罠

`ON ERROR`や`ON ENDFILE`といったONユニットは、再入可能なコード内では特に注意が必要だ。ONユニット内で使用するフラグ変数なども、必ずAUTOMATICとして管理すること。グローバルなフラグで状態制御を行おうとすると、高負荷時に必ず障害が再発する。

VSAMアクセスと再入可能性

VSAMを扱う際は、ACB(Access Control Block)やRPL(Request Parameter List)をどこに配置するかが重要になる。これらをプログラム内にハードコードしたSTATIC領域に置くと再入不可能になる。
現場では、「GETMAIN」命令を使って、実行時に必要なメモリ領域を動的に獲得するのが定石だ。獲得したメモリのポインタを`BASED`変数としてマッピングすることで、各タスクが自分専用の作業領域を持つことができる。

最後に:アーキテクトからの助言

「動けばいい」というコードは、単一バッチ環境なら許されるかもしれない。だが、現代のメインフレーム運用において、再入可能性を軽視したコードは時限爆弾だ。

マイグレーションや保守の現場で、もしあなたが「何故か特定条件下でしか再現しない謎のデータ化け」に遭遇したら、まず疑うべきは「STATIC領域の不適切な書き込み」である可能性が極めて高い。

コードを書くとき、常に「この変数は今、他のタスクから覗かれても大丈夫か?」と自問自答してほしい。その視点こそが、ベテランと駆け出しを分かつ境界線だ。

何か具体的な実装で詰まっている箇所があれば、いつでも相談してくれ。PL/Iの深淵はまだまだ深いぞ。

コメント

タイトルとURLをコピーしました