タスクで実行中のプログラムがGETMAINマクロなどで獲得した仮想記憶域は、サブプール毎に獲得済みの領域とフリー領域が管理されています。これを行うためのコントロール・ブロックがSPQE、DQEおよびFQEです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
TCB +------------+ I I I I +------------+ +----+ TCBMSS I I +------------+ I I I I I I I I I I +------------+ I +---> SPQE(SP=0) +---> SPQA/SPQX +-------> DQE +---> FQE +------------+ I +------------+ I +--------------+ I +------------------+ +----+ I I I +-----+ +----+ I I I 空き領域アドレス I I +------------+ I +------------+ I +--------------+ I +------------------+ I I +------+ I I I I +-----+ I 空き領域長 I I +------------+ I I I +--------------+ +------------------+ I I SP番号+KEY I I I I I I I I I +------------+ +------------+ I +--------------+ +------------------+ I I I I I 領域アドレス I I I I I I I +--------------+ +------------------+ I +------------+ I I 領域長 I I I +--------------+ I I +---> SPQE(次のサブプール) +---> DQE +------------+ +--------------+ +----+ I + I I +------------+ +--------------+ I I I I I I +------------+ +--------------+ I I SP番号+KEY I I I I +------------+ +--------------+ I I I I 領域アドレス I I I I +--------------+ I +------------+ I 領域長 I I +--------------+ V さらに次のサブプールのSPQEへ |
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マクロによってマッピングできます。
オフセット | フィールド名 | 意味、内容 |
---|---|---|
+x00 | SPQENEXT | 次のSPQAへのポインター |
+x04 | SPQESPQX | SPQXへのポインター |
+x08 | SPQESPQA | SPQAへのポインター |
+x0C | SPQETCB | オーナータスクのTCBアドレス |
+x10 | SPQESPID | サブプール番号 |
+x12 | SPQEKEY | 記憶保護キー |
+x13 | SPQEFLGS | 共用サブプールなのかどうかを示すフラグバイト |
オフセット | フィールド名 | 意味、内容 |
---|---|---|
+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が指すフリー領域の後方から前方に向かって領域を切り出します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
+---------------------------------------------------------+ I I I V +-I----------+ +------------------------+ +------------+ I + DQE I ---> x8000 I FREE I <--- I FQE I I I I I I + I +------------+ I I +---------I--+ I I I I I I I I I +------------------------+ +-------+ x8DA0 I 304byte Allocated I I I I I I I V +------------------------+ +------------+ x8ED0 I FREE I <--- I FQE I I I I I +------------------------+ +------------+ x8F98 I 104byte Allocated I +------------------------+ x9000 I I I I |
オフセット | フィールド名 | 意味、内容 |
---|---|---|
+x00 | DQENEXT | 次のDQEへのポインター |
+x08 | DQEFFQE | 最初のFQEへのポインター 空き領域がなければ、このDQE自身を指す |
+x10 | DQEAREA | このDQEが管理する仮想ページのアドレス |
+x14 | DQESIZE | このDQEが管理する仮想ページの長さ |
オフセット | フィールド名 | 意味、内容 |
---|---|---|
+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マクロによってマッピングできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
ASCB +------------+ I I I I +------------+ +----+ ASCBLDA I I +------------+ I I I I I I I I I I +------------+ I +---> LDA +---> FBQE(BELOW 16MB LINE) +---> FBQE +------------+ I +--------------------+ I +--------------------+ + I I I +------+ I I +------------+ I +--------------------+ +--------------------+ I LDAFBQAF +------+ I I I I +------------+ +--------------------+ +--------------------+ I I I 未使用領域長 I I 未使用領域長 I +------------+ +--------------------+ +--------------------+ I LDAEFBAF +------+ I 未使用領域アドレス I I 未使用領域アドレス I +------------+ I +--------------------+ +--------------------+ I I I I I I I I +---> FBQE(ABOVE 16MB LINE) +---> FBQE I I +--------------------+ I +--------------------+ I I I +------+ I I +------------+ +--------------------+ +--------------------+ I I I I +--------------------+ +--------------------+ I 未使用領域長 I I 未使用領域長 I +--------------------+ +--------------------+ I 未使用領域アドレス I I 未使用領域アドレス I +--------------------+ +--------------------+ |
オフセット | フィールド名 | 意味、内容 |
---|---|---|
+x00 | FBQENEXT | 次のFBQEへのポインター |
+x08 | FBQESIZE | このFBQEが管理する未使用領域の長さ |
+x0C | FBQEAREA | このFBQEが管理する未使用領域のアドレス |
ダンプ・リスト上の仮想記憶マップ
プログラムがS878やS80AといったコードでABENDすることはよくあります。一般的には、JCLで指定したリージョンサイズが小さすぎる場合に起きるため、まずはJCL側のリージョン・サイズを修正して再実行する対応が行われます。しかしながら、いくらリージョン・サイズを増やしても再発するような場合は、リージョン・サイズの問題ではなくプログラム側で獲得した領域を解放していない、あるいは獲得時のサイズと解放時のサイズが異なっているといったバグによるものもあります。領域の未解放や誤ったサイズによる解放で仮想記憶域内でフラグメンテーションが起きているような場合は、ダンプ・リスト上に出力される「**VIRTUAL STORAGE MAP**」を参照することでわかる場合があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
**VIRTUAL STORAGE MAP** ABENDした時点のSPQE、DQEおよびFQEを SUBPOOL 000 KEY 08 SHARED BY TCB 009EC828 フォーマットして出力したもの。 ADDRESS 00006000 LENGTH 00001000 FREE AREA 00006000 LENGTH 00000718 SUBPOOL 001 KEY 08 OWNED BY TCB 009D0E88 ADDRESS 0000C000 LENGTH 00001000 FREE AREA 0000C000 LENGTH 00000E20 ADDRESS 00011000 LENGTH 00001000 FREE AREA 00011000 LENGTH 00000E20 ADDRESS 00016000 LENGTH 00001000 <--- DQEが示す割り当て済みページの長さ FREE AREA 00016000 LENGTH 00000E20 <--- FQEが示すこのページ内のフリー領域長 ADDRESS 0001B000 LENGTH 00001000 4096バイトの内、3616バイトが空いていて FREE AREA 0001B000 LENGTH 00000E20 残りの480バイトがGETMAINされたままに ADDRESS 00020000 LENGTH 00001000 なっている。このようなパターンが延々と FREE AREA 00020000 LENGTH 00000E20 続いているようなら、GETMAINとFREEMAINの ADDRESS 00025000 LENGTH 00001000 長さが合っていないことも考えられる。 FREE AREA 00025000 LENGTH 00000E20 ADDRESS 0002A000 LENGTH 00001000 FREE AREA 0002A000 LENGTH 00000E20 ADDRESS 0002F000 LENGTH 00001000 FREE AREA 0002F000 LENGTH 00000E20 ADDRESS 00034000 LENGTH 00001000 FREE AREA 00034000 LENGTH 00000E20 ADDRESS 00039000 LENGTH 00001000 FREE AREA 00039000 LENGTH 00000E20 : : |