Windows版 iTRONサービスコールの作成 (固定長メモリプール)
(その5)
固定長メモリプールへメモリブロックを返却するサービスコールは以下のとおりです。
サービスコール名 | 説明 |
---|---|
rel_blf | 固定長メモリプールへメモリブロックを返却します。 |
固定長メモリプールへメモリブロックを返却するには以下のサービスコールを使用します。
ER rel_blf( ID mpfid, VP blk )
引数 | 説明 |
---|---|
mpfid | メモリプールID番号。 |
blk | 返却するメモリブロックのポインタ。 |
戻り値 | 説明 |
---|---|
E_OK | 正常終了。 |
E_ID | 範囲外のメモリプールID番号。 |
E_NOEXS | 指定したメモリプールID番号は登録されていない。 |
E_PAR | 引数 blk が不正な値。 |
・サービスコールのソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief 固定長メモリブロックの返却.
*
* @param [in] mpfid メモリプールID番号.
* @param [in] blf 返却するメモリブロックのアドレス.
*
* @retval エラーコード.
*/
ER rel_blf( ID mpfid, VP blf )
{
ER ercd;
wi_CommonLock();
//! 固定長メモリブロックを返却する.
ercd = wi_ReleaseFixedMemPool( mpfid, blf );
wi_CommonUnlock();
return ercd;
}
指定したメモリプールID番号を引数としてメモリブロックの返却関数を呼び出します。
メモリブロックの返却関数
固定長メモリプールへメモリブロックを返却する関数のソースコードは以下のとおりです。
/****************************************************************************/
/*!
* @brief 固定長メモリブロックの返却.
*
* @param [in] id メモリプールID番号.
* @param [in] buf 返却するメモリブロックのアドレス.
*
* @retval エラーコード.
*/
ER wi_ReleaseFixedMemPool( INT id, VP buf )
{
ER ercd;
WIMPFOBJ *p;
WIHDR *blk,*ptr;
//! メモリプールIDのオブジェクトを取得する.
p = (WIMPFOBJ *)wi_FindObject( id, TMAX_MAXMPF, ObjList, &ercd );
if( !p ){
return ercd;
}
//! 引数が不正な場合はエラーにする.
if( !buf ){
return E_PAR;
}
//! 返却されたアドレスからメモリブロックのヘッダ部のアドレスを計算する.
blk = (WIHDR *)((DWORD)buf - sizeof(WIHDR) );
//! 貸し出し中メモリブロックキューに返却されたメモリブロックがあるかどうかを調べる.
for( ptr = p->UsedQue; ptr && ptr != blk; ptr = ptr->Next ) ;
if( !ptr ){
return E_OBJ;
}
//! 返却されたメモリブロックを解放する.
ReleaseFreeMem( p, blk );
//! メモリブロック獲得待ちのタスクがある場合、メモリブロックを貸し出してタスクを起床する.
MemAllocWaitTask( p );
return E_OK;
}
固定長メモリプールへメモリブロックを返却する関数は以下のような処理を行います。
- 引数で指定された固定長メモリプールID番号に該当する固定長メモリプール・オブジェクトを取り出します。
- 返却されるメモリブロックのポインタがNULLに場合はエラー終了にします。
- 返却されるメモリブロックのポインタからメモリブロックヘッダ部のバイト数を差し引いてメモリブロックの先頭のアドレス計算します。
- 返却されるメモリブロックを「未使用メモリブロックキュー」の最後に追加します。
- 返却されるメモリブロックのポインタを「貸し出し中メモリブロックキュー」から探して削除します。
- メモリブロックの返却待ちをしているタスクがある場合、待ち行列の先頭のタスクを起床させます。
返却されたメモリブロックを未使用メモリブロックにする処理は以下のようになります。
/****************************************************************************/
/*!
* @brief メモリブロックを返却して空きブロックにする.
*
* @param [in] mpf 固定長メモリプール・オブジェクトのポインタ.
* @param [in] blk 返却するメモリブロックのポインタ.
*
* @retval なし.
*/
static void ReleaseFreeMem( WIMPFOBJ *mpf, WIHDR* blk )
{
WIHDR *ptr;
//! 未使用メモリブロックキューに返却されたメモリブロックを追加する.
if( !mpf->FreeQue ){
mpf->FreeQue = blk;
}else{
for( ptr = mpf->FreeQue; ptr->Next; ptr = ptr->Next ) ;
ptr->Next = blk;
}
//! 貸し出し中のメモリブロックキューから返却されたメモリブロックを削除する.
if( mpf->UsedQue == blk ){
mpf->UsedQue = blk->Next;
}else{
ptr = mpf->UsedQue;
while( ptr ){
if( ptr->Next == blk ){
ptr->Next = blk->Next;
break;
}
ptr = ptr->Next;
}
}
//! 返却されたメモリブロックのリンクポインタをクリアする.
blk->Next = NULL;
blk->Id = 0;
}
メモリブロックが解放されるのを待っているタスクがある場合、解放されたメモリブロックを再度取得します。
/****************************************************************************/
/*!
* @brief メモリブロック獲得待ちをしているタスクにメモリを貸し出す.
*
* @param [in] mpf 固定長メモリプール・オブジェクトのポインタ.
*
* @retval なし.
*/
static void MemAllocWaitTask( WIMPFOBJ *mpf )
{
WITSKOBJ *tsk;
tsk = (WITSKOBJ *)mpf->WaitQue;
while( tsk ){
//! 空いているメモリブロックを取得する.
tsk->Param[0] = GetFreeMem( mpf, tsk->Hdr.Id );
if( !tsk->Param[0] ){
break;
}
//! スリープしているタスクを起床させる.
wi_TaskWakeup( tsk->Hdr.Id, TTW_MPF, NULL );
//! 待ち行列から次のタスクを取り出す.
tsk = tsk->QueLink;
}
}