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の場合、永久にメモリブロックが解放されるのを待ちます。 |
戻り値 | 説明 |
---|---|
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));
}