Windows版iTRONサービスコールの作成 (固定長メモリプール)
(その4)

メモリブロックの取得する

固定長メモリプールからメモリブロックの取得するサービスコールは以下のとおりです。


サービスコール名説明
get_blf

固定長メモリプールからメモリブロックを取得します。

pget_blf

ポーリング方式で固定長メモリプールからメモリブロックを取得します。

tget_blf

タイムアウト付きで固定長メモリプールからメモリブロックを取得します。

※ Ver3.0と4.0では関数名は同じですが、引数の順番が逆になりますので注意してください。

固定長メモリプールからメモリブロックを取得する (タイムアウトなし)

タイムアウトなしで固定長メモリプールからメモリブロックを取得するには以下のサービスコールを使用します。


・Ver3.0の場合


    ER get_blf( VP *p_blf, ID mpfid )
	

・Ver4.0の場合


    ER get_blf(ID mpfid, VP *p_blf )
	

引数説明
p_blf

メモリブロックのポインタを格納する領域のポインタ。

mpfid

メモリプールID番号。

戻り値説明
E_OK

正常終了。

E_ID

範囲外のメモリプールID番号。

E_NOEXS

指定したメモリプールID番号は登録されていない。

E_PAR

引数 p_blf が不正な値。

E_CTX

非コンテキスト・タスクからの呼び出し。


・Ver3.0のサービスコールのソースコードは以下のようになります。


/****************************************************************************/
/*!
 *  @brief  固定長メモリブロックの獲得 (タイムアウトなし).
 *
 *  @param  [in]    p_blf   メモリブロックのアドレスを格納する領域のポインタ.
 *  @param  [in]    mpfid   メモリプールID番号.
 *
 *  @retval エラーコード.
 */
ER      get_blf( VP *p_blf, ID mpfid )
{
    //! タイムアウトなしで固定長メモリブロックを獲得する.
    return tget_blf( p_blf, mpfid, TMO_FEVR );
}
	

・Ver4.0のサービスコールのソースコードは以下のようになります。


/****************************************************************************/
/*!
 *  @brief  固定長メモリブロックの獲得 (タイムアウトなし).
 *
 *  @param  [in]    mpfid   メモリプールID番号.
 *  @param  [out]   p_blf   メモリブロックのアドレスを格納する領域のポインタ.
 *
 *  @retval エラーコード.
 */
ER      get_blf(ID mpfid, VP *p_blf )
{
    //! タイムアウトなしで固定長メモリブロックを獲得する.
    return tget_blf( mpfid, p_blf, TMO_FEVR );
}
	

tget_blf()のタイムアウト設定に TMO_FEVR を指定して呼び出します。

未使用のメモリブロックが無い場合は、メモリブロックが解放されるまでタスクをスリープさせます。

固定長メモリプールからメモリブロックを取得する (ポーリング)

ポーリングで固定長メモリプールからメモリブロックを取得するには以下のサービスコールを使用します。


・Ver3.0の場合


    ER pget_blf( VP *p_blf, ID mpfid )
	

・Ver4.0の場合


    ER pget_blf(ID mpfid, VP *p_blf )
	

引数説明
p_blf

メモリブロックのポインタを格納する領域のポインタ。

mpfid

メモリプールID番号。

戻り値説明
E_OK

正常終了。

E_ID

範囲外のメモリプールID番号。

E_NOEXS

指定したメモリプールID番号は登録されていない。

E_PAR

引数 p_blf が不正な値。

E_TMOUT

未使用のメモリブロックが無い。


・Ver3.0のサービスコールのソースコードは以下のようになります。


/****************************************************************************/
/*!
 *  @brief  固定長メモリブロックの獲得 (ポーリング).
 *
 *  @param  [in]    p_blf   メモリブロックのアドレスを格納する領域のポインタ.
 *  @param  [in]    mpfid   メモリプールID番号.
 *
 *  @retval エラーコード.
 */
ER      pget_blf( VP *p_blf, ID mpfid )
{
    //! 獲得待ちなしで固定長メモリブロックを獲得する.
    return tget_blf( p_blf, mpfid, TMO_POL );
}
	

・Ver4.0のサービスコールのソースコードは以下のようになります。


/****************************************************************************/
/*!
 *  @brief  固定長メモリブロックの獲得 (ポーリング).
 *
 *  @param  [in]    mpfid   メモリプールID番号.
 *  @param  [out]   p_blf   メモリブロックのアドレスを格納する領域のポインタ.
 *
 *  @retval エラーコード.
 */
ER      pget_blf(ID mpfid, VP *p_blf )
{
    //! 獲得待ちなしで固定長メモリブロックを獲得する.
    return tget_blf( mpfid, p_blf, TMO_POL );
}
	

tget_blf()のタイムアウト設定に TMO_POL を指定して呼び出します。

未使用のメモリブロックが無い場合は、タスクをスリープさせずに戻り値をE_TMOUTとしてすぐにサービスコールから戻ります。

固定長メモリプールからメモリブロックを取得する (タイムアウト付き)

タイムアウト付きで固定長メモリプールからメモリブロックを取得するには以下のサービスコールを使用します。


・Ver3.0の場合


    ER tget_blf( VP *p_blf, ID mpfid, TMO tmout )
	

・Ver4.0の場合


    ER tget_blf(ID mpfid, VP *p_blf, TMO tmout )
	

引数説明
p_blf

メモリブロックのポインタを格納する領域のポインタ。

mpfid

メモリプールID番号。

tmout

タイムアウトの設定値。

 - TMO_FEVRの場合、永久にメモリブロックが解放されるのを待ちます。
 - TMO_POLの場合、メモリブロックが取得できなくてもタスクをスリープしません。
 - その他の正数はタイムアウト値となります

戻り値説明
E_OK

正常終了。

E_ID

範囲外のメモリプールID番号。

E_NOEXS

指定したメモリプールID番号は登録されていない。

E_PAR

引数 p_blf が不正な値。

E_TMOUT

メモリブロックが取得できずにタイムアウト。

E_CTX

非コンテキスト・タスクからの呼び出し。


・Ver3.0のサービスコールのソースコードは以下のようになります。


/****************************************************************************/
/*!
 *  @brief  固定長メモリブロックの獲得 (タイムアウトあり).
 *
 *  @param  [in]    p_blf   メモリブロックのアドレスを格納する領域のポインタ.
 *  @param  [in]    mpfid   メモリプールID番号.
 *  @param  [in]    tmout   タイムアウト設定.
 *
 *  @retval エラーコード.
 */
ER      tget_blf( VP *p_blf, ID mpfid, TMO tmout )
{
    ER ercd;

    wi_CommonLock();

    //! 固定長メモリブロックを獲得する.
    ercd = wi_GetFixedMemPool( mpfid, p_blf, tmout );

    wi_CommonUnlock();
    return ercd;
}
	

・Ver4.0のサービスコールのソースコードは以下のようになります。


/****************************************************************************/
/*!
 *  @brief  固定長メモリブロックの獲得 (タイムアウトあり).
 *
 *  @param  [in]    mpfid   メモリプールID番号.
 *  @param  [out]   p_blf   メモリブロックのアドレスを格納する領域のポインタ.
 *  @param  [in]    tmout   タイムアウト設定.
 *
 *  @retval エラーコード.
 */
ER      tget_blf(ID mpfid, VP *p_blf, TMO tmout )
{
    ER ercd;

    wi_CommonLock();

    //! 固定長メモリブロックを獲得する.
    ercd = wi_GetFixedMemPool( mpfid, p_blf, tmout );

    wi_CommonUnlock();
    return ercd;
}
	

固定長メモリープールから未使用のメモリブロックを取得する関数を呼び出します。

メモリブロックが取得できない場合は、メモリブロックが解放されるか、タイムアウトで設定した時間が経過するまでタスクをスリープさせます。

未使用のメモリブロックを取得する関数

固定長メモリープールから未使用のメモリブロックを取得する関数のソースコードは以下のとおりです。



/****************************************************************************/
/*!
 *  @brief  固定長メモリブロックの獲得.
 *
 *  @param  [in]    id      メモリプールID番号.
 *  @param  [out]   buf     メモリブロックのアドレスを格納する領域のポインタ.
 *  @param  [in]    tmout   タイムアウト設定.
 *
 *  @retval エラーコード.
 */
ER      wi_GetFixedMemPool( INT id, VP buf, TMO tmout )
{
    ER          ercd;
    WIMPFOBJ    *p;
    WITSKOBJ    *tsk;
    BYTE        *blk;

    //! メモリプールIDのオブジェクトを取得する.
    p = (WIMPFOBJ *)wi_FindObject( id, TMAX_MAXMPF, ObjList, &ercd );
    if( !p ){
        return ercd;
    }
    //! 引数が不正な場合はエラーにする.
    if( !buf ){
        return E_PAR;
    }
    //! タスク以外からの呼び出しの場合はエラーにする.
    tsk = wi_GetTaskObject( TSK_SELF );
    if( !tsk ){
        return E_CTX;
    }
    //! 未使用のメモリブロックを取得する.
    blk = GetFreeMem( p, tsk->Hdr.Id );

    //! 未使用のメモリブロックがない場合、メモリブロックが返却されるまでタスクをスリープさせる.
    if( !blk ){
        ercd = wi_TaskWait( id, TTW_MPF, tmout, p->Attribute, &(p->WaitQue) );
        if( ercd != E_OK ){
            return ercd;
        }
        blk = tsk->Param[0];
    }
    //! 貸し出すメモリブロックからリンクヘッダを削除する.
    *((DWORD *)buf) = (DWORD)blk;
    return E_OK;
}
	

未使用のメモリブロックを取得する関数は以下のような処理を行います。

  • 引数で指定された固定長メモリプールID番号に該当する固定長メモリプール・オブジェクトを取り出します。
  • 非タスクコンテキストから呼び出された場合はエラー終了します。
  • 未使用のメモリブロックがない場合、メモリブロックが解放されるか、タイムアウトになるまでタスクをスリープさせます。
  • 未使用のメモリブロックを「未使用メモリブロックキュー」の先頭から取り出します。
  • 取り出したメモリブロックのポインタを「貸し出し中メモリブロックキュー」の最後に追加します。

確保してあるメモリブロックから未使用のメモリブロックを取得する処理は以下のようになります。


/****************************************************************************/
/*!
 *  @brief  空いているメモリブロックを取得する.
 *
 *  @param  [in]    mpf     固定長メモリプール・オブジェクトのポインタ.
 *  @param  [in]    tskid   メモリを取得するタスクのID.
 *
 *  @retval 取得したメモリブロックのポインタ.
 */
static BYTE *GetFreeMem( WIMPFOBJ *mpf, INT tskid )
{
    WIHDR *blk,*ptr;

    if( !mpf->FreeQue ){
        return NULL;
    }
    //! 貸し出すメモリブロックを未使用メモリブロックキューの先頭から取り出す.
    blk = mpf->FreeQue;

    //! 未使用メモリブロックキューの先頭から貸し出したメモリブロックを削除する.
    mpf->FreeQue = mpf->FreeQue->Next;

    //! 貸し出し中メモリブロックキューに貸し出したメモリブロックを追加する.
    if( !mpf->UsedQue ){
        mpf->UsedQue = blk;
    }else{
        for( ptr = mpf->UsedQue; ptr->Next; ptr = ptr->Next ) ;
        ptr->Next = blk;
    }
    blk->Next = NULL;
    blk->Id   = tskid;

    //! 貸し出すメモリブロックからリンクヘッダを削除する.
    return (BYTE *)((DWORD)blk + sizeof(WIHDR));
}
	



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