GETMAINとFREEMAIN(仮想記憶域の獲得と解放)
MVS,MSP,VOS3:OSの互換性:API,インターネルの違い – GETMAINとFREEMAIN
仮想記憶域を獲得、返却するためのAPIマクロである、GETMAINとFREEMAINは基本的にMVS、MSPおよびVOS3間で互換がある。24ビット・アドレスしかサポートされていなかったMVS/SPの頃までは、マクロの構文もSVCインターフェースも全く同じであった。
しかしながら、31ビット・アドレスがサポートされた以降は関連するパラメーターとインターフェースに若干の違いが見られる。また、64ビット・アドレスに関してはz/OSでしかサポートされないため、使用する記憶域量に無理がなければ31ビット域で代用するしかない。
基本的な構文
GETMAIN RC|RU,LV=要求長, R,LV=要求長, VRC|VRU,LV=(最大長,最小長), EC|EU,LV=要求長,A=獲得領域アドレス返答域, VC|VU,LA=要求長リスト,A=獲得領域アドレス返答リスト, LC|LU,LA=要求長リスト,A=獲得領域アドレス返答リスト, SP=サブプール番号, LOC=記憶域の位置, BNDRY=DBLWD|PAGE, [BRANCH=YES|(YES,GLOBAL),] [KEY=記憶保護キー] FREEMAIN RC|RU|R,LV=要求長,A=解放領域アドレス, EC|EU|E,LV=要求長,A=解放領域アドレス格納域, VC|VU|V,A=解放領域アドレスおよび長さ格納域, LC|LU|L,LA=要求長リスト,A=解放領域アドレス格納リスト, SP=サブプール番号, [BRANCH=YES|(YES,GLOBAL),] [KEY=記憶保護キー]
マクロ命令の構文はいずれのOS共に基本的なものについては互換である。ただし、MVS(z/OS)にはESA第4版以降に追加されたいくつかの固有のパラメーターがあり、それらはMSPとVOS3に対しては非互換である。また、MVSにはARモードやクロスメモリー・モードのプログラムでも発行できるGETMAIN/FREEMAINと同等機能のSTORAGEマクロも用意されている。
ストレージの獲得位置の指定
GETMAINではストレージを、16MB境界より下に割り当てるのか、それとも16MB境界より上に割り当てるのか、をLOCパラメーターで指定できる。
獲得位置 | MVS(z/OS) | MSP | VOS3 |
16MB境界より下 (実記憶も24bit域) | LOC=BELOW | LOC=BELOW マニュアルには記載なし | LOC=BELOW |
16MB境界より下 (実記憶はどこでもよい) | LOC=(BELOW,ANY) | LOC=(BELOW,ANY) | LOC=(BELOW,ANY) |
16MB境界より上 (仮想記憶も実記憶もどこでもよい) | LOC=ANY LOC=(ANY,ANY) | LOC=ANY LOC=(ANY,ANY) マニュアルには記載なし | LOC=ANY LOC=(ANY,ANY) |
RMODE=24なら16MB境界より下 (実記憶も24bit域) RMODE=ANYなら16MB境界より上 (実記憶はどこでもよい) | LOC=RES | LOC=RES マニュアルには記載なし | LOC=RES |
RMODE=24なら16MB境界より下 (実記憶はどこでもよい) RMODE=ANYなら16MB境界より上 (実記憶はどこでもよい) | LOC=(RES,ANY) | LOC=(RES,ANY) | LOC=(RES,ANY) |
仮想記憶は希望するアドレス で指定され、実記憶はどこでもよい | LOC=EXPLICIT LOC=(EXPLICIT,ANY) | なし | なし |
仮想記憶は希望するアドレス で指定されるが、実記憶は24bit域 | LOC=(EXPLICIT,BELOW) | なし | なし |
LOCパラメーターを指定しない場合は、いずれのOSもLOC=RESとなる。
(MSPのマニュアルには省略値はLOC=(RES,ANY)と解説されていたが実際はLOC=RES、そうでなければ24ビットOS時代に作られたプログラムに対して非互換となってしまう)
基本的に非互換なのはLOC=EXPLICITの指定である。これは獲得したい領域のアドレス(あくまでも希望アドレス)を要求側が指定するもので、MVSに固有の機能である。具体的なアドレスはINADDRパラメーターで指定する。
MSP固有のインターフェース
現在のMSPの前にMSP/E20というバージョンがあった。これはMVS/SPとの互換OSだが、MVS/SPが仮想記憶が2GBに拡張されたMVS/XAになった時、同じように31ビット・アドレッシングをサポートするためにAEオプションというのが追加され、MVS/XA互換のMSPとしてMSP/E20-AEとなった。しかし同じ31ビットアドレス・サポートといってもMVS/XAとまったくの互換をとったわけでなく、内部仕様もAPIも独自のもので一部実装されていた。
GETMAINマクロでは獲得領域を16MB境界の上下いずれに割り振るかはLOCパラメーターではなくAE=YES|NOという独自のパラメーターを追加し、実行されるSVCもMVS/XAと同じSVC120ではなくSVC85という独自のインターフェースになっていた。
GETMAIN RU,LV=1024,LOC=ANY <--- mvs>しかし、現在のMSP(MSP/EX)にエンハンスされた時に、GETMAINマクロはMVS互換のパラメーターがサポートされ、SVCもMVSと同じSVC120でサポートされるようになった。
2GB以上の実記憶における配置位置
z/OSでは、LOC=(xxx,64)が本当の意味で実記憶をどこに配置してもよい、ということになる。LOC=(ANY,ANY)は、正確には実記憶は2GBより下に配置されることを意味し、64bit域には配置されない。仮想記憶は2GB未満の領域だが実記憶は2GBを超えた領域でもよいのであれば、LOC=(31,64)と指定する。現在のLOCパラメーターではBELOWは24、ANYは31に値が変わっている。互換のためBELOWもANYも指定できるが、ANYは64ビット域を含まず誤解されるため、LOCパラメーターの表記には24,31,64の使用が推奨されている。RESとEXPLICITの表記については変わりはない。
MSPでは、LOCパラメーターの指定に変更はなく、MVSと異なりLOC=ANY(LOC=(ANY,ANY))の場合、実記憶は2GBを超える領域が割り当てられるようになっている。実記憶を2GBより下に割り当てる場合は、LOCパラメーターとは別にREAL=BELOW2Gパラメーターを追加指定する。ただし、実際に2GB未満の領域に実記憶が割り当てられるのはGETMAIN時ではなく、獲得された仮想記憶域がPGFIXマクロなどによってページ固定された時点となる。
獲得したストレージの初期値
MVSでは、GETMAINで獲得した仮想記憶域は条件次第でゼロ・クリアーされる。マニュアルには、「ページング可能な私用域のサブプールから8192バイト以上あるいはBNDRY=PAGEが指定されていれば4096バイト以上」の領域をGETMAINした場合は、システムが領域をゼロに設定する、と明記されている。
しかし、MSPにおいては同じではない。経験的には新しい仮想ページが割り当てられた場合(4KB単位の大きさでGETMAINするとか)はゼロになっていた、と記憶しているが、必要ならMVCL命令で初期化していたからGETMAINの仕様にこだわったことはない。ずいぶん前のことであるが、富士通のソフトウェア工場の人から「MSPのGETMAINルーチンでは明示的にゼロ・クリアーされる保証はしていない、海外のMVS用ソフトウェアの中にはGETMAINした領域がゼロ・クリアーを期待していて、MSP用に移植した際に上手く動かず問い合わせを受けたこともあった」という話を聞いたことがある。どうしてそんな期待をするのかと思っていたけど、MVSはマニュアルで明確にしている。MSPもVOS3もMVSのように明確にゼロ・クリアーの条件を公表していないので、MVSと同じように考えない方がよい。ゼロ・クリアーを前提にしたいなら、GETMAIN直後に自分でゼロ・クリアーすることを奨める。
GETMAINマクロにおけるz/OSに固有のパラメーター
INADDR= | 獲得したい領域の先頭アドレス。あくまでも希望アドレス。 希望したアドレスが既に使用中であったり使用できない領域であった場合、GETMAINは 失敗する。 |
OWNER= HOME|PRIMARY|SECONDARY|SYSTEM | 共通域をGETMAINする際のオーナー情報。 (共通域トラッキングの機能で使われる) |
CHECKZERO=YES|NO | 獲得した領域がゼロ・クリアーされたかどうかを復帰コードで通知する。 YESの場合、ゼロ・クリアーされるとRC=x14となる。 |
CONTBDY= | 獲得する領域の包含境界の指定。包含境界は2のべき数で指定する。 10なら2の10乗で1024となり、空き領域が1K単位のブロックで区切られたとして、 要求された長さを満たすブロックが選択され、その中に収まるように開始アドレスが 割り当てられる。 例えば、要求長が1000バイトの場合、CONTBDY=10とすると空き領域が1K単位で 区切られ、空き領域が1000バイト以上ある1Kブロックが探されてそこに割り当てられる。 CONTBDY=20とすると空き領域が2K単位で区切られ、空き領域が1000バイト以上ある 2Kブロックが探されてそこに割り当てられる。 アドレス10000番地から空き領域がある場合、 GETMAIN LV=1000,CONTBDY=10を発行すると10000番地が割り当てられる。 続けてGETMAIN LV=1000,CONTBDY=10を発行すると次は10400番地が割り当てられる。 10000番地からの最初の1Kブロックは24バイトしか空きがないため次の1Kブロックである 10400番地から割り当てられるのである。 2回目のGETMAINでCONTBDY=11とすると、10000番地からの最初の2Kブロックの後方に 1048バイトの空きがあるため1000バイトを割り当てられる。そのため2回目のGETMAINで は103E8番地が割り当てられる。 |
STARTBDY= | 獲得する領域の開始境界の指定。開始境界は2のべき数で指定する。 8なら2の8乗で256となり、先頭アドレスは256の倍数となる。 先頭アドレスを2KB境界にしたければ11を指定する。(2の11乗で2048) |
従来GETMAINでのバウンダリー調整はBNDRY=PAGEによるページ単位(4KB)バウンダリーしかできなかった。短い領域をページ・バウンダリーで大量に獲得すると、不連続な空き領域が増えてストレージ効率が悪くなる。また、MVS(MSP,VOS3)では、GETMAINする領域はページの後方から前方に向かって空き領域を割り当てる(BNDRY=DBLWDの時)という特徴がある。このため1Kや2Kといった長さでは意図してきりのいいアドレスから割り当てることが難しかった。CONTBDYやSTARTBDYの機能によって、プログラムによるバウンダリー調整が容易になり、その結果の不連続空き領域の発生も抑えられる効果がある。