メモリプール管理機能は、ソフトウェアによってメモリプールの管理やメモリブロックの割当てを行うための機能である。
メモリプールには、固定長メモリプールと可変長メモリプールがある。両者は別のオブジェクトであり、操作のためのシステムコールが異なっている。固定長メモリプールから獲得されるメモリブロックはサイズが固定されているのに対して、可変長メモリプールから獲得されるメモリブロックでは、任意のブロックサイズを指定することができる。
固定長メモリプールは、固定されたサイズのメモリブロックを動的に管理するためのオブジェクトである。固定長メモリプール機能には、固定長メモリプールを生成/削除する機能、固定長メモリプールに対してメモリブロックを獲得/返却する機能、固定長メモリプールの状態を参照する機能が含まれる。固定長メモリプールはID番号で識別されるオブジェクトである。固定長メモリプールのID番号を固定長メモリプールIDと呼ぶ。
固定長メモリプールは、固定長メモリプールとして利用するメモリ領域(これを固定長メモリプール領域、または単にメモリプール領域と呼ぶ)と、メモリブロックの獲得を待つタスクの待ち行列を持つ。固定長メモリプールからメモリブロックを獲得するタスクは、メモリプール領域に空きがなくなった場合、次にメモリブロックが返却されるまで固定長メモリブロックの獲得待ち状態となる。固定長メモリブロックの獲得待ち状態になったタスクは、その固定長メモリプールの待ち行列につながれる。
補足事項 | |
---|---|
固定長メモリプールの場合、何種類かのサイズのメモリブロックが必要となる場合には、サイズ毎に複数のメモリプールを用意する必要がある。 |
pk_cmpf
の内容
固定長メモリプールを生成し固定長メモリプールIDを割り当てる。具体的には、mpfcnt
, blfsz
の情報を元に、メモリプールとして利用するメモリ領域を確保する。また、生成したメモリプールに対して管理ブロックを割り付ける。ここで生成されたメモリプールに対して tk_get_mpf システムコールを発行することにより、blfsz
のサイズ(バイト数)をもつメモリブロックを獲得することができる。
exinf
は、対象メモリプールに関する情報を入れておくためにユーザが自由に利用できる。ここで設定した情報は、tk_ref_mpf で取り出すことができる。なお、ユーザの情報を入れるためにもっと大きな領域がほしい場合や、途中で内容を変更したい場合には、自分でそのためのメモリを確保し、そのメモリパケットのアドレスを exinf
に入れる。カーネルでは exinf
の内容について関知しない。
mpfatr
は、下位側がシステム属性を表し、上位側が実装独自属性を表す。mpfatr
のシステム属性の部分では、次のような指定を行う。
mpfatr := (TA_TFIFO || TA_TPRI) | [TA_DSNAME] | [TA_USERBUF] | [TA_NODISWAI] | (TA_RNG0 || TA_RNG1 || TA_RNG2 || TA_RNG3)
TA_TFIFO | メモリ獲得待ちタスクのキューイングはFIFO |
TA_TPRI | メモリ獲得待ちタスクのキューイングは優先度順 |
TA_RNGn | メモリのアクセス制限を保護レベルnとする |
TA_DSNAME | DSオブジェクト名称を指定する |
TA_USERBUF | メモリプール領域としてユーザが指定した領域を利用する |
TA_NODISWAI | tk_dis_wai による待ち禁止を拒否する |
#define TA_TFIFO 0x00000000 /* 待ちタスクをFIFOで管理 */ #define TA_TPRI 0x00000001 /* 待ちタスクを優先度順で管理 */ #define TA_USERBUF 0x00000020 /* ユーザバッファポインタを指定 */ #define TA_DSNAME 0x00000040 /* DSオブジェクト名称を指定 */ #define TA_NODISWAI 0x00000080 /* 待ち禁止拒否 */ #define TA_RNG0 0x00000000 /* 保護レベル0 */ #define TA_RNG1 0x00000100 /* 保護レベル1 */ #define TA_RNG2 0x00000200 /* 保護レベル2 */ #define TA_RNG3 0x00000300 /* 保護レベル3 */
TA_TFIFO, TA_TPRI では、タスクがメモリ獲得のためにメモリプールの待ち行列に並ぶ際の並び方を指定することができる。属性が TA_TFIFO であればタスクの待ち行列はFIFOとなり、属性が TA_TPRI であればタスクの待ち行列はタスクの優先度順となる。
TA_RNGn では、メモリのアクセスを制限する保護レベルを指定する。指定された保護レベルと同じかより高い保護レベルで実行しているタスクからのみアクセス可能である。低いレベルで実行しているタスクがアクセスするとCPUの保護違反の例外が発生する。例えば、TA_RNG1 を指定して作成したメモリプールから獲得したメモリは、TA_RNG0 や TA_RNG1 で動作しているタスクからはアクセス可能だが、TA_RNG2 や TA_RNG3 で動作しているタスクからはアクセスできない。
TA_DSNAME を指定した場合に dsname
が有効となり、DSオブジェクト名称として設定される。DSオブジェクト名称はデバッガがオブジェクトを識別するために使用され、T-Kernel/DSのシステムコール td_ref_dsname と td_set_dsname からのみ操作可能である。詳細は td_ref_dsname 、td_set_dsname を参照のこと。TA_DSNAME を指定しなかった場合は、dsname
が無視され、td_ref_dsname や td_set_dsname が、E_OBJ エラーとなる。
固定長メモリプールの場合、ブロックサイズを変えるためには別のメモリプールを用意しなければならない。すなわち、何種類かのメモリブロックサイズが必要となる場合は、サイズごとに複数のメモリプールを設ける必要がある。
CPUの実行モードがないシステムにおいても、移植性確保のために TA_RNGn 属性を受け付けなければならない。例えば、TA_RNGn の指定はすべて TA_RNG0 相当として処理してもよいが、エラーとはしない。
T-Kernel 2.0にはTA_USERBUFとbufptr
が存在しない。そのため、この機能を使っている場合はT-Kernel 2.0への移植の際に修正が必要となるが、正しくmpfcnt
とblfsz
を設定してあれば、TA_USERBUFとbufptr
を削除するだけで移植ができる。
mpfid
で示される固定長メモリプールを削除する。
このメモリプールからメモリを獲得しているタスクが存在しても、そのチェックや通知は行われない。すべてのメモリブロックが返却されていなくても、このシステムコールは正常終了する。
本システムコールの発行により、対象メモリプールのID番号および管理ブロック用の領域やメモリプール本体の領域は解放される。
対象メモリプールにおいてメモリ獲得を待っているタスクがあった場合にも、本システムコールは正常終了するが、待ち状態にあったタスクにはエラー E_DLT が返される。
E_OK | 正常終了 |
E_ID | 不正ID番号(mpfid が不正あるいは利用できない) |
E_NOEXS | オブジェクトが存在していない(mpfid の固定長メモリプールが存在しない) |
E_PAR | パラメータエラー(tmout ≦(-2)) |
E_DLT | 待ちオブジェクトが削除された(待ちの間に対象メモリプールが削除) |
E_RLWAI | 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け) |
E_DISWAI | 待ち禁止による待ち解除 |
E_TMOUT | ポーリング失敗またはタイムアウト |
E_CTX | コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行) |
mpfid
で示される固定長メモリプールからメモリブロックを獲得する。獲得したメモリブロックの先頭アドレスが blf
に返される。獲得されるメモリブロックのサイズは、固定長メモリプール生成時に blfsz
パラメータで指定された値となる。
獲得したメモリのゼロクリアは行われず、獲得されたメモリブロックの内容は不定となる。
指定したメモリプールからメモリブロックが獲得できなければ、tk_get_mpf 発行タスクがそのメモリプールのメモリ獲得待ち行列につながれ、メモリを獲得できるようになるまで待つ。
tmout
により待ち時間の最大値(タイムアウト値)を指定することができる。tmout
の基準時間(時間の単位)はシステム時刻の基準時間(=1ミリ秒)と同じである。タイムアウト指定が行われた場合、待ち解除の条件が満足されない(空きメモリができない)まま tmout
の時間が経過すると、タイムアウトエラー E_TMOUT となってシステムコールが終了する。
tmout
として TMO_POL=0を指定した場合は、タイムアウト値として0を指定したことを示し、メモリが獲得できなかった場合も待ちに入ることなく E_TMOUT を返す。
tmout
として TMO_FEVR=(-1)を指定した場合は、タイムアウト値として無限大の時間を指定したことを示し、タイムアウトせずにメモリが獲得できるまで待ち続ける。
メモリブロック獲得待ちを行う場合の待ち行列の順序は、メモリプールの属性によって、FIFOまたはタスク優先度順のいずれかとなる。
E_OK | 正常終了 |
E_ID | 不正ID番号(mpfid が不正あるいは利用できない) |
E_NOEXS | オブジェクトが存在していない(mpfid の固定長メモリプールが存在しない) |
E_PAR | パラメータエラー(tmout_u ≦(-2)) |
E_DLT | 待ちオブジェクトが削除された(待ちの間に対象メモリプールが削除) |
E_RLWAI | 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け) |
E_DISWAI | 待ち禁止による待ち解除 |
E_TMOUT | ポーリング失敗またはタイムアウト |
E_CTX | コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行) |
tk_get_mpf のパラメータである tmout
を64ビットマイクロ秒単位の tmout_u
としたシステムコールである。
パラメータが tmout_u
となった点を除き、本システムコールの仕様は tk_get_mpf と同じである。詳細は tk_get_mpf の説明を参照のこと。
blf
で示されるメモリブロックを、mpfid
で示される固定長メモリプールへ返却する。
tk_rel_mpf の実行により、mpfid
のメモリプールでメモリを待っていた別のタスクがメモリを獲得し、そのタスクの待ち状態が解除される場合がある。
メモリブロックの返却を行う固定長メモリプールは、メモリブロックの獲得を行った固定長メモリプールと同じものでなければならない。メモリブロックの返却を行うメモリプールが、メモリブロックの獲得を行ったメモリプールと異なっていることが検出された場合には、E_PAR のエラーとなる。ただし、エラーを検出するか否かは実装依存である。
pk_rmpf
の内容
mpfid
で示された対象固定長メモリプールの各種の状態を参照し、リターンパラメータとして現在の空きブロック数(frbcnt
)、待ちタスクのID(wtsk
)、拡張情報(exinf
) を返す。
wtsk
は、この固定長メモリプールで待っているタスクのIDを示す。この固定長メモリプールで複数のタスクが待っている場合には、待ち行列の先頭のタスクのIDを返す。待ちタスクが無い場合は wtsk
=0となる。
tk_ref_mpf で、対象固定長メモリプールが存在しない場合には、エラー E_NOEXS となる。
どんな場合でも、frbcnt
=0とwtsk
=0の少なくとも一方は成り立つ。
tk_ref_mpl の frsz
ではメモリの空き領域の合計サイズがバイト数で返るのに対して、tk_ref_mpf の frbcnt
では空きブロックの数が返る。
可変長メモリプールは、任意のサイズのメモリブロックを動的に管理するためのオブジェクトである。可変長メモリプール機能には、可変長メモリプールを生成/削除する機能、可変長メモリプールに対してメモリブロックを獲得/返却する機能、可変長メモリプールの状態を参照する機能が含まれる。可変長メモリプールはID番号で識別されるオブジェクトである。可変長メモリプールのID番号を可変長メモリプールIDと呼ぶ。
可変長メモリプールは、可変長メモリプールとして利用するメモリ領域(これを可変長メモリプール領域、または単にメモリプール領域と呼ぶ)と、メモリブロックの獲得を待つタスクの待ち行列を持つ。可変長メモリプールからメモリブロックを獲得するタスクは、メモリプール領域の空き領域が足りなくなった場合、十分なサイズのメモリブロックが返却されるまで可変長メモリブロックの獲得待ち状態となる。可変長メモリブロックの獲得待ち状態になったタスクは、その可変長メモリプールの待ち行列につながれる。
補足事項 | |
---|---|
可変長メモリプールでメモリブロックの獲得を待っているタスクは、待ち行列につながれている順序でメモリブロックを獲得する。例えば、ある可変長メモリプールに対して400バイトのメモリブロックを獲得しようとしているタスクAと、100バイトのメモリブロックを獲得しようとしているタスクBが、この順で待ち行列につながれている時に、別のタスクからのメモリブロックの返却により200バイトの連続空きメモリ領域ができたとする。このような場合でも、タスクAがメモリブロックを獲得するまで、タスクBはメモリブロックを獲得できない。 |
pk_cmpl
の内容
可変長メモリプールを生成し可変長メモリプールIDを割り当てる。具体的には、mplsz
の情報を元に、メモリプールとして利用するメモリ領域を確保する。また、生成したメモリプールに対して管理ブロックを割り付ける。
exinf
は、対象メモリプールに関する情報を入れておくためにユーザが自由に利用できる。ここで設定した情報は、tk_ref_mpl で取り出すことができる。なお、ユーザの情報を入れるためにもっと大きな領域がほしい場合や、途中で内容を変更したい場合には、自分でそのためのメモリを確保し、そのメモリパケットのアドレスを exinf
に入れる。カーネルでは exinf
の内容について関知しない。
mplatr
は、下位側がシステム属性を表し、上位側が実装独自属性を表す。mplatr
のシステム属性の部分では、次のような指定を行う。
mplatr := (TA_TFIFO || TA_TPRI) | [TA_DSNAME] | [TA_USERBUF] | [TA_NODISWAI] | (TA_RNG0 || TA_RNG1 || TA_RNG2 || TA_RNG3)
TA_TFIFO | メモリ獲得待ちタスクのキューイングはFIFO |
TA_TPRI | メモリ獲得待ちタスクのキューイングは優先度順 |
TA_RNGn | メモリのアクセス制限を保護レベルnとする |
TA_DSNAME | DSオブジェクト名称を指定する |
TA_USERBUF | メモリプール領域としてユーザが指定した領域を利用する |
TA_NODISWAI | tk_dis_wai による待ち禁止を拒否する |
#define TA_TFIFO 0x00000000 /* 待ちタスクをFIFOで管理 */ #define TA_TPRI 0x00000001 /* 待ちタスクを優先度順で管理 */ #define TA_USERBUF 0x00000020 /* ユーザバッファポインタを指定 */ #define TA_DSNAME 0x00000040 /* DSオブジェクト名称を指定 */ #define TA_NODISWAI 0x00000080 /* 待ち禁止拒否 */ #define TA_RNG0 0x00000000 /* 保護レベル0 */ #define TA_RNG1 0x00000100 /* 保護レベル1 */ #define TA_RNG2 0x00000200 /* 保護レベル2 */ #define TA_RNG3 0x00000300 /* 保護レベル3 */
TA_TFIFO, TA_TPRI では、タスクがメモリ獲得のためにメモリプールの待ち行列に並ぶ際の並び方を指定することができる。属性が TA_TFIFO であればタスクの待ち行列はFIFOとなり、属性が TA_TPRI であればタスクの待ち行列はタスクの優先度順となる。
タスクがメモリ獲得待ちの行列を作った場合は、待ち行列先頭のタスクに優先してメモリを割り当てる。待ち行列の2番目以降により少ないメモリサイズを要求しているタスクがあった場合も、そのタスクが先にメモリを獲得することはない。例えば、ある可変長メモリプールに対して 要求メモリサイズ=400のタスクAと要求メモリサイズ=100のタスクBがこの順で待っており、別のタスクの tk_rel_mpl により メモリサイズ=200の連続空きメモリ領域ができたとする。このとき、行列の先頭ではないが要求サイズの少ないタスクBが先にメモリを獲得することはない。
TA_RNGn では、メモリのアクセスを制限する保護レベルを指定する。指定された保護レベルと同じかより高い保護レベルで実行しているタスクからのみアクセス可能である。低いレベルで実行しているタスクがアクセスするとCPUの保護違反の例外が発生する。例えば、TA_RNG1 を指定して作成したメモリプールから獲得したメモリは、TA_RNG0 や TA_RNG1 で動作しているタスクからはアクセス可能だが、TA_RNG2 や TA_RNG3 で動作しているタスクからはアクセスできない。
TA_DSNAME を指定した場合に dsname
が有効となり、DSオブジェクト名称として設定される。DSオブジェクト名称はデバッガがオブジェクトを識別するために使用され、T-Kernel/DSのシステムコール td_ref_dsname と td_set_dsname からのみ操作可能である。詳細は td_ref_dsname 、td_set_dsname を参照のこと。TA_DSNAME を指定しなかった場合は、dsname
が無視され、td_ref_dsname や td_set_dsname が、E_OBJ エラーとなる。
メモリ獲得待ち行列の先頭のタスクの待ちが強制解除されたり、タスク優先度が変更されるなどで待ち行列の順序が変化した場合は、新たに待ち行列の先頭になったタスクに対してメモリ割当てが試みられる。メモリを割り当てることができれば、そのタスクの待ちは解除される。したがって、tk_rel_mpl によるメモリの解放がなくても、状況によってはメモリの獲得が行われ、待ちが解除される場合がある。
CPUの実行モードがないシステムにおいても、移植性確保のために TA_RNGn 属性を受け付けなければならない。例えば、TA_RNGn の指定はすべて TA_RNG0 相当として処理してもよいが、エラーとはしない。
複数個の可変長メモリプールを設ける機能は、エラー処理時や緊急時などにメモリを確保するためのメモリプールを分離しておくために利用できる。
T-Kernel 2.0にはTA_USERBUFとbufptr
が存在しない。そのため、この機能を使っている場合はT-Kernel 2.0への移植の際に修正が必要となるが、正しくmplsz
を設定してあれば、TA_USERBUFとbufptr
を削除するだけで移植ができる。
mplid
で示される可変長メモリプールを削除する。
このメモリプールからメモリを獲得しているタスクが存在しても、そのチェックや通知は行われない。すべてのメモリブロックが返却されていなくても、このシステムコールは正常終了する。
本システムコールの発行により、対象メモリプールのID番号および管理ブロック用の領域やメモリプール本体の領域は解放される。
対象メモリプールにおいてメモリ獲得を待っているタスクがあった場合にも、本システムコールは正常終了するが、待ち状態にあったタスクにはエラー E_DLT が返される。
E_OK | 正常終了 |
E_ID | 不正ID番号(mplid が不正あるいは利用できない) |
E_NOEXS | オブジェクトが存在していない(mplid の可変長メモリプールが存在しない) |
E_PAR | パラメータエラー(tmout ≦(-2)) |
E_DLT | 待ちオブジェクトが削除された(待ちの間に対象メモリプールが削除) |
E_RLWAI | 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け) |
E_DISWAI | 待ち禁止による待ち解除 |
E_TMOUT | ポーリング失敗またはタイムアウト |
E_CTX | コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行) |
mplid
で示される可変長メモリプールから、blksz
で指定されるサイズ(バイト数)のメモリブロックを獲得する。獲得したメモリブロックの先頭アドレスが blk
に返される。
獲得したメモリのゼロクリアは行われず、獲得されたメモリブロックの内容は不定となる。
メモリが獲得できなければ、本システムコールを発行したタスクは待ち状態に入る。
tmout
により待ち時間の最大値(タイムアウト値)を指定することができる。tmout
の基準時間(時間の単位)はシステム時刻の基準時間(=1ミリ秒)と同じである。タイムアウト指定が行われた場合、待ち解除の条件が満足されない(空きメモリができない)まま tmout
の時間が経過すると、タイムアウトエラー E_TMOUT となってシステムコールが終了する。
tmout
として TMO_POL=0を指定した場合は、タイムアウト値として0を指定したことを示し、メモリが獲得できなかった場合も待ちに入ることなく E_TMOUT を返す。
tmout
として TMO_FEVR=(-1)を指定した場合は、タイムアウト値として無限大の時間を指定したことを示し、タイムアウトせずにメモリが獲得できるまで待ち続ける。
メモリブロック獲得待ちを行う場合の待ち行列の順序は、メモリプールの属性によって、FIFOまたはタスク優先度順のいずれかとなる。
E_OK | 正常終了 |
E_ID | 不正ID番号(mplid が不正あるいは利用できない) |
E_NOEXS | オブジェクトが存在していない(mplid の可変長メモリプールが存在しない) |
E_PAR | パラメータエラー(tmout_u ≦(-2)) |
E_DLT | 待ちオブジェクトが削除された(待ちの間に対象メモリプールが削除) |
E_RLWAI | 待ち状態強制解除(待ちの間に tk_rel_wai を受け付け) |
E_DISWAI | 待ち禁止による待ち解除 |
E_TMOUT | ポーリング失敗またはタイムアウト |
E_CTX | コンテキストエラー(タスク独立部またはディスパッチ禁止状態で実行) |
tk_get_mpl のパラメータである tmout
を64ビットマイクロ秒単位の tmout_u
としたシステムコールである。
パラメータが tmout_u
となった点を除き、本システムコールの仕様は tk_get_mpl と同じである。詳細は tk_get_mpl の説明を参照のこと。
blk
で示されるメモリブロックを、mplid
で示される可変長メモリプールへ返却する。
tk_rel_mpl の実行により、mplid
のメモリプールでメモリを待っていた別のタスクがメモリを獲得し、そのタスクの待ち状態が解除される場合がある。
メモリブロックの返却を行う可変長メモリプールは、メモリブロックの獲得を行った可変長メモリプールと同じものでなければならない。メモリブロックの返却を行うメモリプールが、メモリブロックの獲得を行ったメモリプールと異なっていることが検出された場合には、E_PAR のエラーとなる。ただし、エラーを検出するか否かは実装依存である。
複数のタスクが待っている可変長メモリプールに対してメモリを返却する場合は、要求メモリ数との関係により、複数のタスクが同時に待ち解除となることがある。この場合の待ち解除後のタスクの優先順位は、同じ優先度を持つタスクの間では待ち行列に並んでいたときと同じ順序となる。
pk_rmpl
の内容
mplid
で示された対象可変長メモリプールの各種の状態を参照し、リターンパラメータとして現在の空き領域の合計サイズ(frsz
)、すぐに獲得可能な最大の空き領域のサイズ(maxsz
)、待ちタスクのID(wtsk
)、拡張情報(exinf
) を返す。
wtsk
は、この可変長メモリプールで待っているタスクのIDを示す。この可変長メモリプールで複数のタスクが待っている場合には、待ち行列の先頭のタスクのIDを返す。待ちタスクが無い場合は wtsk
=0となる。
tk_ref_mpl で、対象可変長メモリプールが存在しない場合には、エラー E_NOEXS となる。