01.2ストレージ・プールの作成(CPOOL)

By 神居 - Posted: 2008/12/05 Last updated: 2009/12/14 - Leave a Comment
印刷用ページの表示 印刷用ページの表示

リエントラントプログラムでは書き込みを行うレジスター保管域や作業域はプログラムの外に確保するため、GETMAIN/FREEMAINマクロを利用します。しかし頻繁に呼び出されるモジュールでは呼び出しの度にこれらの領域の獲得と解放を繰り返すのはパフォーマンスの点で劣ります。そこでこのような場合は作業に使用する領域をまとめて確保し、必要の都度そこから切り出して使う方法が行われます。まとめて確保した領域をプール(POOL)、切り出す領域をセル(CELL)と呼びます。セルは固定長と可変長の両方の構造がありますが、可変長セルはストレージの利用効率は上がりますが実現方法はむずかしいです。ここでは固定長のセルを使ったストレージ・プールの利用を解説します。


CPOOLマクロでストレージ・プールを作る

CPOOL BUILDマクロはセル・プールの作成を行い、CPOOL DELETEマクロはセル・プールの削除を行います。このサンプルでは1KBの固定長セル64個分のプールを16MB未満のリージョンに作成します。作成されたプールの識別子がGR0に返ります。この識別子(セル・プールID)は以降のGET,FREE,DELETEの各サービスで使用します。
64個以上のセルが要求された場合は8個単位でプールが拡張されます。(拡張されたプールが未使用となっても解放はなされません、より細かなセルとプールの制御が必要ならCSRPxxxルーチン(呼び出し可能セル・プール・サービス)も利用できます。)


CPOOLマクロでセルを切り出す

セル・プールはサブルーチンを呼び出す親プログラムがあらかじめ作成しておくものとします。サンプルでは親プログラムはサブルーチンを呼び出す時、GR0にセル・プールIDを、GR1にパラメーター・リストを設定しています。
呼び出されたサブルーチンはプログラムの先頭でCPOOL GETマクロを使ってプールからセルを切り出します。切り出されたセルの長さは親プログラムがプール作成時に定義します。レジスター保管域の目的なら72バイトあればいいのですが、リエントラントプログラムでは作業域も必要になりますからそれらの長さも考慮して適当な大きさのセルを定義する方がいいでしょう。サンプルではレジスター保管域の後ろにプログラム作業域をDSECTでマッピングしています。GETMAINの代わりにCPOOL GETを使うと考えればいいでしょう。
呼び出し元プログラムへ復帰する際に切り出したセルを返却します。セル・プールIDは入口点で保管したGR0を復元して指定しています。返却するセルのアドレスはGR2に設定しています。セル返却前に呼び出し元のレジスター保管域アドレスをGR13にロードしておきます。こちらもFREEMAINの代わりにCPOOL FREEを使うと考えればいいでしょう。

プールを各サブルーチンで作成する方法も考えられますが、プールIDをどこに保管するか?と言う問題がありますので、サンプルのように親プログラムでプールを作成する方が簡単です。なおサンプルのような使い方では影響ありませんが、GETはGR2?4が、FREEはGR2?3が破壊されます。REGS=SAVEパラメーターを指定すれば内容は保証されますが、GR13がレジスター保管域をポイントしていなければなりません。したがってサンプルのようにリエントラントプログラム用レジスター保管域のためのセルのGET/FREEであればREGS=SAVEパラメーターは利用できません。

CPOOLはz/OSでのみ利用できます。MSPには同等機能としてBLDCPOOL,GETCELL,FREECEEL,DELCPOOLの各マクロがありますが、プールの作成と削除はキー0・スーパーバイザーモードのプログラムでしか利用できず一般プログラムでの利用を想定していません。VOS3では同等機能が公開されていません。
マルチタスク構造のプログラムで各タスクが同じサブルーチンを頻繁に呼び出すならば、GETMAIN/FREEMAINよりCPOOLでセルを切り出す方がオーバーヘッドが少なくなります。

Posted in 中級編 • • Top Of Page