9.3 可変長メモリ・プール
RI600PXでは,処理プログラムから動的なメモリ操作要求が行われた際に利用するメモリ領域として“可変長メモリ・プール”を提供しています。

なお,可変長メモリ・プールに対する動的なメモリ操作は,任意サイズの可変長メモリ・ブロックを単位として行われます。

9.3.1 可変長メモリ・ブロックのサイズ

現在のRI600PXの実装では,実際に獲得されるメモリ・ブロックのサイズは,最大で12種類のバリエーションから選択されます。このバリエーションは,可変長メモリ・プール生成時に指定した最大メモリ・ブロック・サイズを元に,あらかじめ規定された24種類のサイズの中から選択されます。表9−1に,メモリ・ブロックサイズのバリエーションを示します。ただし,この振る舞いは将来変更される可能性があります。

表9−1  メモリ・ブロック・サイズのバリエーション

項番

メモリ・ブロックのサイズ

(16進数)

例1:

最大メモリ・ブロック・サイズ=0x100の場合

例2:

最大メモリ・ブロック・サイズ=0x20000の場合

1

12 (0xC)



×

2

36 (0x24)



×

3

84 (0x54)





4

180 (0xB4)





5

372 (0x174)

×



6

756 (0x2F4)

×



7

1524 (0x5F4)

×



8

3060 (0xBF4)

×



9

6132 (0x17F4)

×



10

12276 (0x2FF4)

×



11

24564 (0x5FF4)

×



12

49140 (0xBFF4)

×



13

98292 (0x17FF4)

×



14

196596 (0x2FFF4)

×



15

393204 (0x5FFF4)

×

×

16

786420 (0xBFFF4)

×

×

17

1572852 (0x17FFF4)

×

×

18

3145716 (0x2FFFF4)

×

×

19

6291444 (0x5FFFF4)

×

×

20

12582900 (0xBFFFF4)

×

×

21

25165812 (0x17FFFF4)

×

×

22

50331636 (0x2FFFFF4)

×

×

23

100663284 (0x5FFFFF4)

×

×

24

201326580 (0xBFFFFF4)

×

×



9.3.2 可変長メモリ・プールの生成

可変長メモリ・プールは,以下のいずれかの方法で生成します。

1 ) システム・コンフィギュレーション・ファイルによる生成
システム・コンフィギュレーション・ファイルで静的API“variable_memorypool[]”を使用して可変長メモリ・プールを生成します。
静的API“variable_memorypool[]”の詳細は,「20.18 可変長メモリ・プール情報(variable_memorypool[])」を参照してください。



2 ) cre_mplまたはacre_mplサービスコールによる生成
cre_mplは,パラメータpk_cmplが指す領域に設定された可変長メモリ・プール生成情報にしたがって,パラメータmplidで指定された可変長メモリ・プールIDの可変長メモリ・プールを生成します。
acre_mplは,パラメータpk_cmplが指す領域に設定された可変長メモリ・プール生成情報にしたがって可変長メモリ・プールを生成し,生成された可変長メモリ・プールIDを返します。
指定する可変長メモリ・プール生成情報は,以下の通りです。




- 可変長メモリ・プール属性(mplatr
「タスク待ちキューはFIFO順(TA_TFIFO)」のみを指定できます。


- 可変長メモリ・プール領域のサイズ(バイト数)(mplsz),可変長メモリ・プール領域の先頭アドレス(mpl
可変長メモリ・プールの先頭アドレスは,4バイト境界でなければなりません。
可変長メモリ・プール領域は,メモリ・ブロックにアクセスするタスクがアクセス可能なメモリオブジェクト内としてください。



- 最大メモリ・ブロック・サイズ(バイト数)(maxblksz
可変長メモリ・プールから獲得するメモリ・ブロックの最大サイズを指定します。「9.3.1 可変長メモリ・ブロックのサイズ」も参照してください。


これらのサービス・コールは,信頼されたドメインに所属するタスクだけが呼び出せます。

以下に,代表としてacre_mplの記述例を示します。

 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 
 #define MPLSZ     1024                  /*可変長メモリ・プール領域のサイズ(バイト数)*/
 #define MAXBLKSZ  128                   /*最大メモリ・ブロック・サイズ(バイト数)*/
 
 #pragma section B BU_SH                 /*可変長メモリ・プール領域のセクション*/
 static UW mpl_area[ MPLSZ/sizeof(UW)];  /* 可変長メモリ・プール領域*/
 #pragma section
 
 #pragma task Task1                      /*備考参照*/
 void Task1 ( VP_INT exinf );            /*備考参照*/
 void Task1 ( VP_INT exinf )
 {
         ID      mplid;                  /*変数の宣言*/
         T_CMPL  pk_cmpl = {             /*変数の宣言,初期化*/
                      TA_TFIFO,      /*可変長メモリ・プール属性(mplatr)*/
                      MPLSZ,         /*可変長メモリ・プール領域のサイズ(バイト数)(mplsz*/
                      (VP)mpl_area,  /*可変長メモリ・プール領域の先頭アドレス(mpl)*/
                      MAXBLKSZ       /*最大メモリ・ブロック・サイズ(バイト数)(maxblksz)*/
        };
         ............
         mplid = acre_mpl ( &pk_cmpl );   /*可変長メモリ・プールの生成*/
         ............
 }


備考 システム・コンフィギュレーション・ファイルで生成したタスクについては,これらのステートメントはcfg600pxがkernel_id.hに出力するため,記述不要です。

9.3.3 可変長メモリ・プールの削除

- del_mpl
パラメータmplidで指定された可変長メモリ・プールを削除します。
対象可変長メモリ・プールでget_mplまたはtget_mplによって待っているタスクがある場合は,そのタスク待ち状態を解除し,get_mplまたはtget_mplの戻り値としてE_DLTを返します。
本サービス・コールは,信頼されたドメインに所属するタスクだけが呼び出せます。
以下に,本サービス・コールの記述例を示します。




 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 #pragma task Task1                      /*備考参照*/
 void Task1 ( VP_INT exinf );            /*備考参照*/
 void Task1 ( VP_INT exinf )
 {
         ID      mplid = 8;              /*変数の宣言,初期化*/
 
         ............
         ............
 
         del_mpl( mplid );               /*可変長メモリ・プールの削除*/
 }


備考 システム・コンフィギュレーション・ファイルで生成したタスクについては,これらのステートメントはcfg600pxがkernel_id.hに出力するため,記述不要です。

9.3.4 可変長メモリ・ブロックの獲得

可変長メモリ・ブロックの獲得は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。

RI600PXでは,可変長メモリ・ブロックを獲得する際,メモリ・クリア処理を行っていません。したがって,獲得された可変長メモリ・ブロックの内容は不定となります。

- get_mpl(待つ)

- pget_mplipget_mpl(ポーリング)

- tget_mpl(タイムアウト付きで待つ)

- get_mpl(待つ)
パラメータmplidで指定された可変長メモリ・プールからパラメータblkszで指定されたサイズの可変長メモリ・ブロックを獲得し,その先頭アドレスをパラメータp_blkで指定された領域に格納します。
ただし,本サービス・コールを発行した際,対象可変長メモリ・プールから可変長メモリ・ブロックを獲得することができなかった(要求サイズ分の連続する空き領域が存在しなかった)場合には,可変長メモリ・ブロックの獲得は行わず,自タスクを対象可変長メモリ・プールの待ちキューにキューイングしたのち,RUNNING状態からWAITING状態(可変長メモリ・ブロック獲得待ち状態)へと遷移させます。
なお,可変長メモリ・ブロック獲得待ち状態の解除は,以下の場合に行われます。




 
可変長メモリ・ブロック獲得待ち状態の解除操作

戻り値

rel_mplの発行により,対象可変長メモリ・プールに要求サイズを満足する可変長メモリ・ブロックが返却された。

E_OK

送信待ちキュー先頭のタスクが,以下のいずれかによって待ち状態を強制的に解除された。

- rel_waiの発行により,待ち状態を強制的に解除された。

- irel_waiの発行により,待ち状態を強制的に解除された。

- ter_tskの発行により,待ち状態を強制的に解除された。

- tget_mplのパラメータtmoutで指定された待ち時間が経過した。

E_OK

rel_waiの発行により,待ち状態を強制的に解除された。

E_RLWAI

irel_waiの発行により,待ち状態を強制的に解除された。

E_RLWAI

vrst_mplの発行により,対象可変長メモリ・プールがリセットされた。

EV_RST

del_mplの発行により,待ち状態を強制的に解除された。

E_DLT



以下に,本サービス・コールの記述例を示します。

 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 #pragma task Task1                      /*備考5参照*/
 void Task1 ( VP_INT exinf );            /*備考5参照*/
 void Task1 ( VP_INT exinf )
 {
         ER      ercd;                   /*変数の宣言*/
         ID      mplid = 1;              /*変数の宣言,初期化*/
         UINT    blksz = 256;            /*変数の宣言,初期化*/
         VP      p_blk;                  /*変数の宣言*/
 
         ............
         ............
 
                                         /*可変長メモリ・ブロックの獲得*/
         ercd = get_mpl ( mplid, blksz, &p_blk );
 
         if ( ercd == E_OK ) {
                 ............            /*正常終了処理*/
                 ............
                                         /*可変長メモリ・ブロックの返却*/
                 rel_mpl ( mplid, p_blk );
         } else if ( ercd == E_RLWAI ) {
                 ............            /*強制終了処理*/
                 ............
         }
 
         ............
         ............
 }


備考1 実際に獲得されるメモリ・ブロックのサイズについては,「9.3.1 可変長メモリ・ブロックのサイズ」を参照してください。

備考2 自タスクを対象可変長メモリ・プールの待ちキューにキューイングする際のキューイング方式は,FIFO順に行われます。

備考3 獲得したメモリ・ブロックの内容は不定です。

備考4 獲得するメモリ・ブロックのアライメント数は,可変長メモリ・プールの生成方法によって異なります。

- システム・コンフィギュレーション・ファイルで静的に生成した場合
獲得するメモリ・ブロックのアライメント数は1です。アライメント数を4とするには,可変長メモリ・プール情報(variable_memorypool[])メモリ・プール領域に付与するセクション名(mpl_section)に個別のセクション名を指定し,リンク時にそのセクションを4バイト境界アドレスに配置してください。


- cre_mplまたはacre_mplサービスコールで動的に生成した場合
獲得するメモリ・ブロックのアライメント数は4です。


備考5 システム・コンフィギュレーション・ファイルで生成したタスクについては,これらのステートメントはcfg600pxがkernel_id.hに出力するため,記述不要です。

- pget_mplipget_mpl(ポーリング)
パラメータmplidで指定された可変長メモリ・プールからパラメータblkszで指定されたサイズの可変長メモリ・ブロックを獲得し,その先頭アドレスをパラメータp_blkで指定された領域に格納します。
ただし,本サービス・コールを発行した際,対象可変長メモリ・プールから可変長メモリ・ブロックを獲得することができなかった(要求サイズ分の連続する空き領域が存在しなかった)場合には,可変長メモリ・ブロックの獲得は行わず,戻り値としてE_TMOUTを返します。
以下に,本サービス・コールの記述例を示します。




 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 #pragma task Task1                      /*備考4参照*/
 void Task1 ( VP_INT exinf );            /*備考4参照*/
 void Task1 ( VP_INT exinf )
 {
         ER      ercd;                   /*変数の宣言*/
         ID      mplid = 1;              /*変数の宣言,初期化*/
         UINT    blksz = 256;            /*変数の宣言,初期化*/
         VP      p_blk;                  /*変数の宣言*/
 
         ............
         ............
 
                                         /*可変長メモリ・ブロックの獲得*/
         ercd = pget_mpl ( mplid, blksz, &p_blk );
 
         if ( ercd == E_OK ) {
                 ............            /*ポーリング成功処理*/
                 ............
 
                                         /*可変長メモリ・ブロックの返却*/
                 rel_mpl ( mplid, p_blk );
         } else if ( ercd == E_TMOUT ) {
                 ............            /*ポーリング失敗処理*/
                 ............
         }
 
         ............
         ............
 }


備考1 実際に獲得されるメモリ・ブロックのサイズについては,「9.3.1 可変長メモリ・ブロックのサイズ」を参照してください。

備考2 獲得したメモリ・ブロックの内容は不定です。

備考3 獲得するメモリ・ブロックのアライメント数は,可変長メモリ・プールの生成方法によって異なります。

- システム・コンフィギュレーション・ファイルで静的に生成した場合
獲得するメモリ・ブロックのアライメント数は1です。アライメント数を4とするには,可変長メモリ・プール情報(variable_memorypool[])メモリ・プール領域に付与するセクション名(mpl_section)に個別のセクション名を指定し,リンク時にそのセクションを4バイト境界アドレスに配置してください。


- cre_mplまたはacre_mplサービスコールで動的に生成した場合
獲得するメモリ・ブロックのアライメント数は4です。


備考4 システム・コンフィギュレーション・ファイルで生成したタスクについては,これらのステートメントはcfg600pxがkernel_id.hに出力するため,記述不要です。

- tget_mpl(タイムアウト付きで待つ)
パラメータmplidで指定された可変長メモリ・プールからパラメータblkszで指定されたサイズの可変長メモリ・ブロックを獲得し,その先頭アドレスをパラメータp_blkで指定された領域に格納します。
ただし,本サービス・コールを発行した際,対象可変長メモリ・プールから可変長メモリ・ブロックを獲得することができなかった(要求サイズ分の連続する空き領域が存在しなかった)場合には,可変長メモリ・ブロックの獲得は行わず,自タスクを対象可変長メモリ・プールの待ちキューにキューイングしたのち,RUNNING状態からタイムアウト付きのWAITING状態(可変長メモリ・ブロック獲得待ち状態)へと遷移させます。
なお,可変長メモリ・ブロック獲得待ち状態の解除は,以下の場合に行われます。




 
可変長メモリ・ブロック獲得待ち状態の解除操作

戻り値

rel_mplの発行により,対象可変長メモリ・プールに要求サイズを満足する可変長メモリ・ブロックが返却された。

E_OK

送信待ちキュー先頭のタスクが,以下のいずれかによって待ち状態を強制的に解除された。

- rel_waiの発行により,待ち状態を強制的に解除された。

- irel_waiの発行により,待ち状態を強制的に解除された。

- ter_tskの発行により,待ち状態を強制的に解除された。

- tget_mplのパラメータtmoutで指定された待ち時間が経過した。

E_OK

rel_waiの発行により,待ち状態を強制的に解除された。

E_RLWAI

irel_waiの発行により,待ち状態を強制的に解除された。

E_RLWAI

vrst_mplの発行により,対象可変長メモリ・プールがリセットされた。

EV_RST

パラメータtmoutで指定された待ち時間が経過した。

E_TMOUT

del_mplの発行により,待ち状態を強制的に解除された。

E_DLT



以下に,本サービス・コールの記述例を示します。

 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 #pragma task Task1                      /*備考6参照*/
 void Task1 ( VP_INT exinf );            /*備考6参照*/
 void Task1 ( VP_INT exinf )
 {
         ER      ercd;                   /*変数の宣言*/
         ID      mplid = 1;              /*変数の宣言,初期化*/
         UINT    blksz = 256;            /*変数の宣言,初期化*/
         VP      p_blk;                  /*変数の宣言*/
         TMO     tmout = 3600;           /*変数の宣言,初期化*/
 
         ............
         ............
 
                                         /*可変長メモリ・ブロックの獲得*/
         ercd = tget_mpl ( mplid, blksz, &p_blk, tmout );
 
         if ( ercd == E_OK ) {
                 ............            /*正常終了処理*/
                 ............
 
                                         /*可変長メモリ・ブロックの返却*/
                 rel_mpl ( mplid, p_blk );
         } else if ( ercd == E_RLWAI ) {
                 ............            /*強制終了処理*/
                 ............
         } else if ( ercd == E_TMOUT ) {
                 ............            /*タイムアウト処理*/
                 ............
         }
 
         ............
         ............
 }


備考1 実際に獲得されるメモリ・ブロックのサイズについては,「9.3.1 可変長メモリ・ブロックのサイズ」を参照してください。

備考2 自タスクを対象可変長メモリ・プールの待ちキューにキューイングする際のキューイング方式は,FIFO順に行われます。

備考3 獲得したメモリ・ブロックの内容は不定です。

備考4 獲得するメモリ・ブロックのアライメント数は,可変長メモリ・プールの生成方法によって異なります。

- システム・コンフィギュレーション・ファイルで静的に生成した場合
獲得するメモリ・ブロックのアライメント数は1です。アライメント数を4とするには,可変長メモリ・プール情報(variable_memorypool[])メモリ・プール領域に付与するセクション名(mpl_section)に個別のセクション名を指定し,リンク時にそのセクションを4バイト境界アドレスに配置してください。


- cre_mplまたはacre_mplサービスコールで動的に生成した場合
獲得するメモリ・ブロックのアライメント数は4です。


備考5 待ち時間tmoutTMO_FEVRが指定された際には“get_mplと同等の処理”を,TMO_POLが指定された際には“pget_mplと同等の処理”を実行します。

備考6 システム・コンフィギュレーション・ファイルで生成したタスクについては,これらのステートメントはcfg600pxがkernel_id.hに出力するため,記述不要です。

9.3.5 可変長メモリ・ブロックの返却

可変長メモリ・ブロックの返却は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。

- rel_mpl
パラメータmplidで指定された可変長メモリ・プールにパラメータblkで指定された可変長メモリ・ブロックを返却します。
可変長メモリ・ブロックを返却したあと,対象可変長メモリ・プールの待ちキューにキューイングされているタスクをキューの先頭から調べていき,待ちタスクが要求するサイズのメモリを割り当てられる場合はメモリを割り当てます。この動作を待ちキューにタスクがなくなるか,メモリが割り当てられなくなるまで繰り返します。これにより,メモリを獲得できたタスクは,待ちキューから外れ,WAITING状態(可変長メモリ・ブロック獲得待ち状態)からREADY状態へ,またはWAITING-SUSPENDED状態からSUSPENDED状態へと遷移します。
以下に,本サービス・コールの記述例を示します。



 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 #pragma task Task1                      /*備考2参照*/
 void Task1 ( VP_INT exinf );            /*備考2参照*/
 void Task1 ( VP_INT exinf )
 {
         ER      ercd;                   /*変数の宣言*/
         ID      mplid = 1;              /*変数の宣言,初期化*/
         UINT    blksz = 256;            /*変数の宣言,初期化*/
         VP      blk;                    /*変数の宣言*/
 
         ............
         ............
 
                                         /*可変長メモリ・ブロックの獲得*/
         ercd = get_mpl ( mplid, blksz, &blk );
 
         if ( ercd == E_OK ) {
                 ............            /*正常終了処理*/
                 ............
 
                 rel_mpl ( mplid, blk ); /*可変長メモリ・ブロックの返却*/
         } else if ( ercd == E_RLWAI ) {
                 ............            /*強制終了処理*/
                 ............
         }
 
         ............
         ............
 }


備考1 RI600PXでは,blkに関して簡易的なエラー検出しか行っていません。blkには,必ず正しい値を指定してください。blkがエラー検出されない不正な値の場合,以後の動作は保証されません。

備考2 システム・コンフィギュレーション・ファイルで生成したタスクについては,これらのステートメントはcfg600pxがkernel_id.hに出力するため,記述不要です。

9.3.6 可変長メモリ・プール詳細情報の参照

可変長メモリ・プール詳細情報の参照は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。

- ref_mpliref_mpl
パラメータmplidで指定された可変長メモリ・プールの可変長メモリ・プール詳細情報(待ちタスクの有無,空き可変長メモリ・ブロックの合計サイズなど)をパラメータpk_rmplで指定された領域に格納します。
以下に,本サービス・コールの記述例を示します。


 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600pxが出力するヘッダ・ファイルの定義*/
 #pragma task Task1                      /*備考2参照*/
 void Task1 ( VP_INT exinf );            /*備考2参照*/
 void Task1 ( VP_INT exinf )
 {
         ID      mplid = 1;              /*変数の宣言,初期化*/
         T_RMPL  pk_rmpl;                /*データ構造体の宣言*/
         ID      wtskid;                 /*変数の宣言*/
         SIZE    fmplsz;                 /*変数の宣言*/
         UINT    fblksz;                 /*変数の宣言*/
 
         ............
         ............
 
         ref_mpl ( mplid, &pk_rmpl );    /*可変定長メモリ・プール詳細情報の参照*/
 
         wtskid = pk_rmpl.wtskid;        /*待ちタスクの有無の獲得*/
         fmplsz = pk_rmpl.fmplsz;        /*空き領域の合計サイズの獲得*/
         fblksz = pk_rmpl.fblksz;        /*獲得可能なメモリ・ブロックの最大サイズの獲得*/
 
         ............
         ............
 }


備考1 可変長メモリ・プール詳細情報T_RMPLについての詳細は,「【 可変長メモリ・プール詳細情報T_RMPLの構造 】」を参照してください。

備考2 システム・コンフィギュレーション・ファイルで生成したタスクについては,これらのステートメントはcfg600pxがkernel_id.hに出力するため,記述不要です。