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;
    }
}
	



Windowsは米国Microsoft Corporationの登録商標です。