POOL(9)

名称
pool_create, pool_destroy, pool_get, pool_put, pool_prime - リソースプールマネージャ

書式
#include <sys/pool.h> struct pool * pool_create(size_t size, u_int align, u_int align_offset, int nitems, char *wchan, u_int pagesz, void *(*palloc)(unsigned long sz, int flags, int tag), void (*prelease)(void *v, unsigned long sz, int tag), int mtag) void * pool_get(struct pool *pp, int flags) void pool_put(struct pool *pp, void *item) int pool_prime(struct pool *pp, int nitems, caddr_t storage) pool_sethiwat(struct pool *pp, int n) pool_setlowat(struct pool *pp, int n) POOL_STORAGE_SIZE(size, nitems)

解説
これらのユーティリティルーチン群は、固定サイズのメモリ塊のプールを 管理する機能を提供します。リソースプールはそのリソースプールのオーナが 独占使用できるように、ある量のメモリを確保しておきます。システム全体レベルの メモリ割当機構 (malloc(9)) で利用できるメモリ資源とは無関係に、アプリケーションの動作継続に必要な 最低限のメモリ確保を保証するのに使うことができます。 プールリソースとして管理される通常のプールアイテム数を越えた数の プールアイテムを割り当てたい場合、オプションとして pool_create() に引数として渡した palloc() 関数を呼び出す事によって一時的なメモリ取得が可能です。 この一時的なメモリは後で自動的にシステムに返却されます。

  プールの生成
pool_create() 関数は、リソースプールを初期化し、それへのハンドルを返します。引数は下記:

size
    プールが管理するメモリアイテムのサイズを指定します。

align
    pool_get() が返すメモリアドレスの整列値を指定します。この引数は必ず 2 の冪乗に します。0 を指定すると、整列値はデフォルトとしてアーキテクチャで自然な 整列値となります。

align_offset
    align パラメータの適用されたアイテム内でのオフセットです。

nitems
    そのプールの生成時に割り当てるメモリアイテムの数を指定します。 この数字には 0 を指定でき、その場合、後から pool_prime() でプールに永続アイテムを追加することができます。

wchan
    pool_get() がアイテムのプールへの返却を待たなくてはならない場合に tsleep(9) に渡される ‘待機チャネル’ です。

pagesz
    プールへ追加のメモリを割り当てる場合に使う単位です。2 の冪乗でなければ なりません。

palloc
    プールが使い果たされた時に、メモリを追加するために呼び出されます。これは pagesz で整列したメモリを返します。 sz 引数は pagesz の倍数となります。

prelease
    ページを解放し、システムへ返却する場合に呼び出されます。 palloc() と prelease() が NULL の場合は、プールマネジャは kernel_map ( UVM(9) 参照) を使用して uvm_km_kmemalloc(9) と uvm_km_free(9) でメモリ割当と解放を行います。

mtag
    メモリページの割当と解放時に、 palloc() や prelease() に渡されるメモリタグです。

storage
    呼び出した側で用意するオプションのストレージです。 malloc(9) を使用する代わりに、プールハンドルとプールアイテムの両方に使用します。

プールリソースを作成するのに充分なメモリがない場合、 pool_create() は NULL を返します。 storage 引数を使用する場合、使用者は nitems で指定した数のプールアイテムと、プール管理に必要な余分 (つまりは、プールハンドル) を収容きるだけのストレージを用意する必要があります。

  プールからのアイテムの割り当て
pool_get() プールから 1 アイテムを割り当て、それへのポインタを返します。

pp  プールリソースのインスタンスを識別するハンドルです。

flags
    PR_URGENT または PR_WAITOK のいずれかで、プールリソースを使い切った場合の振舞いを定義します。 リソースのない状態で PR_WAITOK が指定されている場合、アイテムがプールに返却されるのを待ちます。 そうでない場合、 pool_get() は NULL を返します。 PR_URGENT が指定されて、リソースがなく、さらに palloc() が新しいページを割り当てることができなかった場合、システムは panic (XXX) します。

  プールへのアイテムの返却
pool_put() item で指されるプールアイテムを、プールハンドル pp で識別されるリソースプールへ返します。 プール内の利用可能なアイテム数が pool_sethiwat() で設定されている最大プールサイズを越え、特にプールアイテムの要求が なければ、超過したアイテムは prelease() によってシステムへ返却されます。

pp  プールリソースインスタンスを識別するハンドルです。

item
    以前に pool_get() で取得したプールアイテムへのポインタです。

  プールの準備
pool_prime() はプールへアイテムを追加します。アイテムの格納領域は malloc(9) を使って直接割り当てられるか、 呼び出した関数であらかじめ割り当てて pool_prime() に与えられます。

pool_prime()

pp  プールリソースインスタンスを識別するハンドルです。

nitems
    プールへ追加するアイテムの数です。そのプールアイテムの格納領域は storage 引数で渡すことができます。このパラメータが NULL の場合、アイテムは malloc(9) で割り当てられます。 この関数は、要求された数のアイテムを割り当てられなかった場合、 ENOMEM を返します。そうでなければ、0 を返します。

  プールリソースの指標値設定
プールは、アイテムの要求数が増えるに従って、そのリソースの使用量を 増やそうとします。 逆に言うと、 使っていないメモリをシステムに返す、プールで使っていない アイテムがたまって超える上限値は、設定可能であるべきです。 プールが手元に保持するアイテム数の最小と最大の制限値は、それぞれ最高、 最低 指標値 といいます。 関数 pool_sethiwat() と pool_setlowat() はそれぞれ、プールの最高指標値と最低指標値を設定します。 pool_sethiwat()

pp  プールリソースインスタンスを識別するハンドルです。

n   プールに保持できるアイテムの最大値です。アイテムが返却されて、 プール内の総ページ数がこの関数で設定された最大値を越えた場合、 間違いなく使用されていないページが ( prelease() を呼び出すことによって) すぐに解放されます。 この関数を使用してアイテムの最大値を指定していない場合、そのページは、 システムがメモリ不足となって VM システムが不要ページを取り返そうと するまで、プールに関連付けられたままとなります。

pool_setlowat()

pp  プールリソースインスタンスを識別するハンドルです。

n   プールに保持されるアイテムの最小値です。そのプールのページ数は、 この関数で指定された最低数のアイテムを割り当てるのに必要な値よりも 減少することはありません。 pool_prime() と違い、この関数は追加で必要なメモリを割り当てることは ありません。

  潜在的な落し穴
プールリソースルーチンで、ストレージの供給方法を取り混ぜて使用すると 動作がおかしくなりますので注意して下さい。

プールリソースのコードでは、内部状態の一貫性のためプール毎にロックを 使用しています。プールを割り込みコンテキストで呼び出す場合、再入の 可能性のある割り込みは全てブロックしなくてはなりません。

  診断
コンパイル時に POOL_DIAGNOSTIC オプションを定義することにより、プールの使用ログを取ることができます。

参照コード
プールマネージャはファイル sys/kern/subr_pool.c で実装されています。

関連項目
malloc(9), free(9), uvm(9)

歴史
NetBSD のプールマネージャは NetBSD 1.4 で登場しました。