ダンプ・リスト解析入門 ⑨:ダンプ解析に関連するOSコントロール・ブロック⑤

タスクで実行中のプログラムがGETMAINマクロなどで獲得した仮想記憶域は、サブプール毎に獲得済みの領域とフリー領域が管理されています。これを行うためのコントロール・ブロックがSPQE、DQEおよびFQEです。

SPQEとSPQA

SPQE(Subpool Queue Element)は、タスクで使用しているサブプールを示すコントロール・ブロックです。サブプール番号とストレージ・キー、オーナー・タスクおよびサブプール内の領域を管理するDQEへのアンカー領域であるSPQAへのポインターなどで構成されています。SPQEは、TCBのTCBMSSフィールドからポイントされ、サブプール単位にSPQEがチェインされます。
SPQA(Subpool Queue Anchors)は、サブプール内の獲得済み領域を示すDQEをポイントします。16MB境界より上の拡張域のDQEは、SPQAに代わりSPQX(SPQA Extension)からポイントされます。SPQAとSPQXはSPQEからそれぞれ別にポイントされ、サブプール番号が同じでも、獲得される領域の位置(16MB境界の上下いずれなのか)によって異なるアンカー領域が使われます。なお、対応するDQEが存在しない場合、DQEポインターはそのSPQAもしくはSPQX自身のアドレスを示しています。
SPQEはIHASPQEマクロによって、SPQA/SPQXはIHASPQAマクロによってマッピングできます。

SPQEの主なフィールド(MVSの場合)
オフセット フィールド名 意味、内容
+x00 SPQENEXT 次のSPQAへのポインター
+x04 SPQESPQX SPQXへのポインター
+x08 SPQESPQA SPQAへのポインター
+x0C SPQETCB オーナータスクのTCBアドレス
+x10 SPQESPID サブプール番号
+x12 SPQEKEY 記憶保護キー
+x13 SPQEFLGS 共用サブプールなのかどうかを示すフラグバイト
SPQAとSPQXの主なフィールド
オフセット フィールド名 意味、内容
+x00 SPQAFBDQ 先頭のDQEへのポインター(16MB境界より下の領域を示すDQEキュー)
+x04 SPQALBDQ 最後のDQEへのポインター(16MB境界より下の領域を示すDQEキュー)

オフセット フィールド名 意味、内容
+x00 SPQXFEDQ 先頭のDQEへのポインター(16MB境界より上の領域を示すDQEキュー)
+x04 SPQXLEDQ 最後のDQEへのポインター(16MB境界より上の領域を示すDQEキュー)

SPQEはタスク毎に作られてSPQEキューとしてチェインされます。ただしサブプール0についてはタスク間で共用できます。この場合、SPQEはタスク毎に作成されますが、そこからポイントされるSPQAとSPQXについては同じコントロール・ブロックを共用しています。サブプール0を共用しないタスクの場合は、SPQEからポイントされるSPQXとSPQEもそのタスク固有のコントロール・ブロックです。

DQEとFQE

DQE(Descriptor Queue Element)は、SPQEが示すサブプール内の獲得済み領域を示します。1つのDQEは1つの連続した領域ブロックを管理します。サブプール内に複数の獲得済み領域がある場合は、それぞれの領域毎にDQEが作られます。GETMAINが発行された際に新しい仮想ページが割り振られるとDQEが作られ、割り振られた仮想ページ内のすべての領域が解放されるとそこを管理していたDQEも消滅します。DQEはIHADQEマクロによって、FQEはIHAFQEマクロによってマッピングできます。
FQE(Free Queue Element)は、DQEが管理する仮想ページ内のフリー領域(GETMAINされていない領域)を管理します。DQEはSPQE/SPQAからチェインされていますが、FQEは1つ1つのDQE単位に管理されDQEからチェインされます。GETMAINが要求されると、指定されたサブプールのDQEからFQEをたどります。要求長を満たすフリー領域が見つかると、そのFQEが指すフリー領域の後方から前方に向かって領域を切り出します。

DQEの主なフィールド
オフセット フィールド名 意味、内容
+x00 DQENEXT 次のDQEへのポインター
+x08 DQEFFQE 最初のFQEへのポインター
空き領域がなければ、このDQE自身を指す
+x10 DQEAREA このDQEが管理する仮想ページのアドレス
+x14 DQESIZE このDQEが管理する仮想ページの長さ
FQEの主なフィールド
オフセット フィールド名 意味、内容
+x00 FQEAREA このFQEが示す空き領域のアドレス
+x04 FQESIZE このFQEが示す空き領域の長さ
+x08 FQENEXT 次のFQEへのポインター
最後のFQEの場合、このFQEを管理するDQE自身を指す
+x10 FQEDQE このFQEを管理するDQEへのバックポインター

FBQE

FQEは割り振られている仮想ページ内の空き領域を管理しますが、リージョン内で未だ仮想ページが割り振られていない領域はFBQE(Free Block Queue Element)によって管理されます。FBQEはどのタスクにも割り当てられていない未使用の領域を管理するもので、LDA(Local Data Area)からポイントされています。LDAは、アドレス空間に固有の仮想記憶域を管理するコントロール・ブロックで、16MB境界の上下それぞれのリージョン域の開始アドレスとサイズ、使用可能なリージョン・サイズ、使用済みの仮想ストレージサイズなどが格納されています。
FBQEはIHAFBQEマクロによって、LDAはIHALDAマクロによってマッピングできます。

FBQEの主なフィールド(MVSの場合)
オフセット フィールド名 意味、内容
+x00 FBQENEXT 次のFBQEへのポインター
+x08 FBQESIZE このFBQEが管理する未使用領域の長さ
+x0C FBQEAREA このFBQEが管理する未使用領域のアドレス

ダンプ・リスト上の仮想記憶マップ

プログラムがS878やS80AといったコードでABENDすることはよくあります。一般的には、JCLで指定したリージョンサイズが小さすぎる場合に起きるため、まずはJCL側のリージョン・サイズを修正して再実行する対応が行われます。しかしながら、いくらリージョン・サイズを増やしても再発するような場合は、リージョン・サイズの問題ではなくプログラム側で獲得した領域を解放していない、あるいは獲得時のサイズと解放時のサイズが異なっているといったバグによるものもあります。領域の未解放や誤ったサイズによる解放で仮想記憶域内でフラグメンテーションが起きているような場合は、ダンプ・リスト上に出力される「**VIRTUAL STORAGE MAP**」を参照することでわかる場合があります。