OPコマンドを待ち合わせるECBをECBLISTでWAITする時の注意
オペレーター・コマンド待ち合わせのECBをECBLISTに含める場合の注意
MODIFY/STOPコマンドによってオペレーター・コマンドを受け取るには、EXTRACTマクロでCOMエリアのアドレスを求め、そこからポイントされているMODIFY/STOPコマンドECBを求めます。その後QEDITマクロによってコマンド・キューを初期設定してから、MODIFY/STOPコマンドECBでWAITします。コンソールからMODIFY/STOPコマンドが投入されるとECBがPOSTされます。COMエリアからCIBをたどり、入力されたコマンド文字列を得る、という流れになります。
MSPでもVOS3でもこの流れに関しては同じです。しかしMODIFY/STOPコマンドECBによって単独でWAITするのではなく、自分自身のプログラム・イベントのECBと共にマルチイベントでWAITする場合は注意が必要です。MODIFY/STOPコマンドECBを含めたマルチイベントでのWAITを行う場合、MODIFY/STOPコマンドECB領域の記憶保護キーが0になっていることが理由です。
何が起きるのか
MSPとVOS3では、ECBLISTにプログラムの記憶保護キー(通常は8)のECBに加え、MODIFY/STOPコマンドのECBも含めてWAITマクロを発行すると、WAITルーチン内で相当な量のCPUを消費します。そのことが注意を必要とする点です。
WAITマクロを発行後、WAITルーチンの処理としてECBアドレスの妥当性検査やECBフィールドにWAITビットを立てたり、WAIT発行元のRBアドレスをセットしたりを行います。この際ECBへのアクセスにWAIT SVC発行時のPSWキー(あるいはTCBのプログラム・キー)が使用されるようです。このため内部で記憶保護キー矛盾によりS0C4ABENDが起きます。本来ならばこのような場合はWAIT SVCがS201ABENDしますが、MODIFY/STOPコマンドのECBがキー0の領域(SQA内に置かれるCSCB、MVSの場合はCSCX)にあること自体はWAITを発行したプログラムのバグでも何でもなく、どうしようもないことです。オペレーター・コマンドの受け取りに関して、COMエリアからポイントされるMODIFY/STOPコマンドのECBをWAITマクロで指定する際は、記憶保護キーを変更しなければならない、などという制限はありません。ましてやオペレーター・コマンドの受け取り処理はAPF許可されていない一般のPPモードのプログラムにも認められています。
そこでOSはWAITマクロの発行元をABENDさせることはできないので、このエラーをリカバって正しいECBであるということでサービスを継続しなければなりません。実際にかなりなCPUが消費されるのはこのあたりの内部リカバリーに掛かるオーバーヘッドではないかと考えられます。もちろん私は富士通のOSのソースなどを見られる立場ではなかったので、実際に使われたCPU量を測定したり、GTFで何が起きているのかをトレースしたりした結果の考えです。しかしほぼ合っていると思います。
同じようなプログラムでもMVSではこのようなこと(WAITマクロの発行で大量のCPUが消費されること)は起きません。VOS3でも同じ事は起きるので、恐らく昔のMVSでは起きていたのでしょう。なのでMVS用に作成されたプログラムがMODIFY/STOPコマンドのECBとその他のECBを混在してECBLISTに入れてWAITしても表面上も性能数値上も何ら問題はないのに、そのプログラムを再アセンブルなどしただけでストレートにMSPやVOS3に持って行くと、同じ操作や同じ量のデータであっても妙にCPUを使っている、ということになります。
どうすれば回避できるか
そのまま使ってもプログラムの動き自体には問題は起きません。しかしいらないCPUを消費するのも確かなので何とかしたいところです。MODIFY/STOPコマンドの受け取り処理を別タスクにして単独のECBで待ち合わせるようにして、オペレーター・コマンドが入力されたらサブタスクからメインタスクに改めてPOSTする、とか、MODIFY/STOPコマンドのECBをECBLISTからはずし、別のタイミングでオペレーター・コマンドが入力されたかPOSTビットだけチェックする、なども考えられます。実際あるデータベース・ソフトでは、MODIFY/STOPコマンドのECBをECBLISTからはずし、データベースへのアクセス要求やタイマー時間が経過したなどの他のイベントが起きた際に、オペレーター・コマンドが入力されているかをチェックする、といった方法を取っていました。そうしたやり方でもいいのですが、そんなことのために元のロジックを直すのも面倒です。私は次の2つの方法から選んでいました。
PSWキーを0にしてWAITを発行する
一番簡単で、元のプログラムのロジック修正も不要な方法として、WAITマクロを発行する際にPSWキーを0にする方法があります。キー0でWAIT SVCを出せば、WAITマクロの発行で大量のCPUが消費されるような動きにはなりませんでした。このことからもECBのチェックと書き換えにWAIT発行時のキーが使われ、キー0のMODIFY/STOPコマンドのECBにアクセスした際に記憶保護キーエラーで内部でABENDしているのではないかと考えたわけです。この方法は簡単ですが、プログラムがAPF許可を持たなければなりません。
SPKA 0 CHANGE TO KEY0 TO AVOID CPU + OVERHEAD WAIT ECBLIST=........ WAIT ANY EVENT COMPLETION SPKA X'80' BACK TO SAFE KEY : :
WAITではなくEVENTSマクロを使う
同じマルチイベントでの待ち合わせであっても、EVENTSマクロを使った場合はこのようなことは起きません。プログラムがAPF許可を持たなければEVENTSマクロを使用するといいでしょう。ECB数が少ない場合はECBLISTの方が手軽ですが、この場合はやむを得ません。
※MSP/VOS3におけるこのような現象は、1990年代前半頃に調査した結果です。データベース製品を担当してた先輩から「昔、お客さんからソフトを立ち上げてるだけで使ってないのに何でこんなにCPUが上がってるの?って聞かれたことがある、そしたらさ...」という話が発端でした。同じようにECBLISTでマルチイベントのWAITしている自分の担当製品では同じMSPでそんなことは起きてないのに何で?ということから自分でもいろいろ調べてみたわけです。その後機会があって2001年にもテストしましたが変わっていませんでした。しかしそれから10年近く経ってますので、もしかしたらOSの動きも変わっているかも知れません。
Comment from caspar
Time 2013年5月9日 at 15:23
ところで今回初めてEVENTSを使おうとしています。何でだか標準形式しか見当たらないので、マクロの展開形だけ確認しようとアセンブルしたら、ICM命令のマスク値がバグってる気がして困惑したりしています。