Windows版 iTRONサービスコールの作成 (ランデブ・ポート)
(その4)

ランデブを呼び出す

ランデブを呼び出すサービスコールは以下のとおりです。


サービスコール名説明
cal_por

タイムアウトなしでランデブを呼び出します。

pcal_por

ポーリング方式でランデブを呼び出します。

tcal_por

タイムアウト付きでランデブを呼び出します。

※ pcal_por()はVer3.0でのみサポートされます。

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

ランデブを呼び出す (タイムアウトなし)

タイムアウトなしでランデブを呼び出すには以下のサービスコールを使用します。


・Ver3.0の場合


    ER cal_por( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT cmsgsz )
	

引数説明
msg

呼び出しメッセージを格納した領域のポインタ。

p_rmsgsz

応答メッセージのサイズを格納する領域のポインタ。

porid

ランデブポートID番号。

calptn

呼び出し側選択条件のビットパターン。

cmsgsz

呼び出しメッセージのサイズ。

戻り値説明
E_OK

正常終了。

E_ID

範囲外のランデブポートID番号。

E_NOEXS

指定したランデブポートID番号は登録されていない。

E_PAR

パラメータエラー。

E_CTX

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


・Ver4.0の場合


    ER_UINT cal_por( ID porid, RDVPTN calptn, VP msg, UINT cmsgsz )
	

引数説明
porid

ランデブポートID番号。

calptn

呼び出し側選択条件のビットパターン。

msg

呼び出しメッセージを格納した領域のポインタ。

cmsgsz

呼び出しメッセージのサイズ。

戻り値説明
E_ID

範囲外のランデブポートID番号。

E_NOEXS

指定したランデブポートID番号は登録されていない。

E_PAR

パラメータエラー。

E_CTX

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

その他の正数

応答メッセージのサイズ。


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


/****************************************************************************/
/*!
 *  @brief  ランデブ呼び出し (タイムアウトなし).
 *
 *  @param  [in]    msg         呼び出しメッセージのアドレス.
 *  @param  [out]   p_rmsgsz    応答メッセージのサイズを格納する領域のポインタ.
 *  @param  [in]    porid       ランデブポートID番号.
 *  @param  [in]    calptn      呼び出し側選択条件のビットパターン.
 *  @param  [in]    cmsgsz      呼び出しメッセージのサイズ.
 *
 *  @retval エラーコード.
 */
ER      cal_por( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT cmsgsz )
{
    //! タイムアウトなしでランデブを呼び出す.
    return tcal_por( msg, p_rmsgsz, porid, calptn, cmsgsz, TMO_FEVR );
}
	


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


/****************************************************************************/
/*!
 *  @brief  ランデブ呼び出し (タイムアウトなし).
 *
 *  @param  [in]    porid       ランデブポートID番号.
 *  @param  [in]    calptn      呼び出し側選択条件のビットパターン.
 *  @param  [in]    msg         メッセージのアドレス.
 *  @param  [in]    cmsgsz      呼び出しメッセージのサイズ.
 *
 *  @retval 応答メッセージのサイズまたはエラーコード.
 */
ER_UINT cal_por( ID porid, RDVPTN calptn, VP msg, UINT cmsgsz )
{
    //! タイムアウトなしでランデブを呼び出す.
    return tcal_por( porid, calptn, msg, cmsgsz, TMO_FEVR );
}
	

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

ランデブが受け付けられない場合は、ランデブが受け付けられるまでタスクをスリープさせます。

ランデブを呼び出す (ポーリング) Ver3.0のみ

ポーリングでランデブを呼び出すには以下のサービスコールを使用します。



    ER pcal_por( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT cmsgsz )
	

引数説明
msg

呼び出しメッセージを格納した領域のポインタ。

p_rmsgsz

応答メッセージのサイズを格納する領域のポインタ。

porid

ランデブポートID番号。

calptn

呼び出し側選択条件のビットパターン。

cmsgsz

呼び出しメッセージのサイズ。

戻り値説明
E_OK

正常終了。

E_ID

範囲外のランデブポートID番号。

E_NOEXS

指定したランデブポートID番号は登録されていない。

E_PAR

パラメータエラー。

E_CTX

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

E_TMOUT

ランデブが受け付けられない。


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


/****************************************************************************/
/*!
 *  @brief  ランデブ呼び出し (ポーリング).
 *
 *  @param  [in]    msg         呼び出しメッセージのアドレス.
 *  @param  [out]   p_rmsgsz    応答メッセージのサイズを格納する領域のポインタ.
 *  @param  [in]    porid       ランデブポートID番号.
 *  @param  [in]    calptn      呼び出し側選択条件のビットパターン.
 *  @param  [in]    cmsgsz      呼び出しメッセージのサイズ.
 *
 *  @retval エラーコード.
 */
ER      pcal_por( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT cmsgsz )
{
    //! 受付待ちなしでランデブを呼び出す.
    return tcal_por( msg, p_rmsgsz, porid, calptn, cmsgsz, TMO_POL );
}
	

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

ランデブが受け付けられない場合は、タスクをスリープさせずに戻り値をE_TMOUTとしてすぐにサービスコールから戻ります。

ランデブを呼び出す (タイムアウト付き)

タイムアウト付きでランデブを呼び出すには以下のサービスコールを使用します。


・Ver3.0の場合


    ER cal_por( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT cmsgsz )
	

引数説明
msg

呼び出しメッセージを格納した領域のポインタ。

p_rmsgsz

応答メッセージのサイズを格納する領域のポインタ。

porid

ランデブポートID番号。

calptn

呼び出し側選択条件のビットパターン。

cmsgsz

呼び出しメッセージのサイズ。

tmout

タイムアウトの設定値。

  • TMO_FEVRの場合、永久にランデブが受け付けられるのを待ちます。
  • TMO_POLの場合、ランデブが受け付けられなくてもタスクをスリープしません。
  • その他の正数はタイムアウト値となります。

戻り値説明
E_OK

正常終了。

E_ID

範囲外のランデブポートID番号。

E_NOEXS

指定したランデブポートID番号は登録されていない。

E_PAR

パラメータエラー。

E_CTX

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

E_TMOUT

ランデブが受け付けられない。


・Ver4.0の場合


    ER_UINT cal_por( ID porid, RDVPTN calptn, VP msg, UINT cmsgsz )
	

引数説明
porid

ランデブポートID番号。

calptn

呼び出し側選択条件のビットパターン。

msg

呼び出しメッセージを格納した領域のポインタ。

cmsgsz

呼び出しメッセージのサイズ。

tmout

タイムアウトの設定値。

  • TMO_FEVRの場合、永久にランデブが受け付けられるのを待ちます。
  • TMO_POLの場合、ランデブが受け付けられなくてもタスクをスリープしません。
  • その他の正数はタイムアウト値となります。

戻り値説明
E_ID

範囲外のランデブポートID番号。

E_NOEXS

指定したランデブポートID番号は登録されていない。

E_PAR

パラメータエラー。

E_CTX

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

E_TMOUT

ランデブが受け付けられない。

その他の正数

応答メッセージのサイズ。


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


/****************************************************************************/
/*!
 *  @brief  ランデブ呼び出し (タイムアウトあり).
 *
 *  @param  [in]    msg         呼び出しメッセージのアドレス.
 *  @param  [out]   p_rmsgsz    応答メッセージのサイズを格納する領域のポインタ.
 *  @param  [in]    porid       ランデブポートID番号.
 *  @param  [in]    calptn      呼び出し側選択条件のビットパターン.
 *  @param  [in]    cmsgsz      呼び出しメッセージのサイズ.
 *  @param  [in]    tmout       タイムアウト設定.
 *
 *  @retval エラーコード.
 */
ER      tcal_por( VP msg, INT *p_rmsgsz, ID porid, UINT calptn, INT cmsgsz, TMO tmout )
{
    ER ercd;

    wi_CommonLock();

    //! ランデブを呼び出す.
    ercd = wi_CallRendPort( porid, calptn, msg, cmsgsz, p_rmsgsz, tmout );

    wi_CommonUnlock();
    return ercd;
}
	


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


/****************************************************************************/
/*!
 *  @brief  ランデブ呼び出し (タイムアウトあり).
 *
 *  @param  [in]    porid       ランデブポートID番号.
 *  @param  [in]    calptn      呼び出し側選択条件のビットパターン.
 *  @param  [in]    msg         メッセージのアドレス.
 *  @param  [in]    cmsgsz      呼び出しメッセージのサイズ.
 *  @param  [in]    tmout       タイムアウト設定.
 *
 *  @retval 応答メッセージのサイズまたはエラーコード.
 */
ER_UINT tcal_por( ID porid, RDVPTN calptn, VP msg, UINT cmsgsz, TMO tmout )
{
    ER  ercd;
    INT size;

    wi_CommonLock();

    //! ランデブを呼び出す.
    ercd = wi_CallRendPort( porid, calptn, msg, cmsgsz, &size, tmout );
    if( ercd == E_OK ){
        ercd  = size;
    }
    wi_CommonUnlock();
    return ercd;
}
	

指定したランデブポートID番号のランデブを呼び出します。

ランデブが受け付けられない場合は、ランデブが受け付けられるか、または、タイムアウトで設定した時間が経過するまでタスクをスリープさせます。

ランデブの呼び出し関数

ランデブの呼び出し関数のソースコードは以下のとおりです。



/****************************************************************************/
/*!
 *  @brief  ランデブ呼び出し.
 *
 *  @param  [in]    id          ランデブポートID番号.
 *  @param  [in]    ptn         呼び出し側選択条件のビットパターン.
 *  @param  [in]    msg         メッセージのアドレス.
 *  @param  [in]    csize       呼び出しメッセージのサイズ.
 *  @param  [out]   rsize       応答メッセージのサイズを格納する領域のポインタ.
 *  @param  [in]    tmout       タイムアウト設定.
 *
 *  @retval エラーコード.
 */
ER      wi_CallRendPort( INT id, UINT ptn, VP msg, INT csize, INT *rsize, TMO tmout )
{
    ER          ercd;
    WIPOROBJ    *p;
    WITSKOBJ    *acp_tsk,*cal_tsk;

    //! ランデブポートIDのオブジェクトを取得する.
    p = (WIPOROBJ *)wi_FindObject( id, TMAX_MAXPOR, PortList, &ercd );
    if( !p ){
        return ercd;
    }
    //! 引数が不正な場合はエラーにする.
    if( !rsize || p->MaxCalMsg < csize ){
        return E_PAR;
    }
    //! 自タスクのタスクコンテキストを取り出す.
    cal_tsk = wi_GetTaskObject( TSK_SELF );
    if( !cal_tsk ){
        return E_CTX;
    }
    cal_tsk->Param[0] = (VP)ptn;
    cal_tsk->Param[1] = (VP)msg;
    cal_tsk->Param[2] = (VP)csize;

    //! ランデブ受付待ちをしているタスクに対してランデブが成立するかどうかを調べる.
    acp_tsk = SatisfyRendezvous( (WITSKOBJ *)(p->AcpWaitQue), ptn );

    if( !acp_tsk ){
        //! ランデブが成立するまでタスクをスリープさせる.
        ercd = wi_TaskWait( id, TTW_CAL, tmout, p->Attribute, &(p->CalWaitQue) );
        if( ercd == E_OK ){
            *rsize = (INT)cal_tsk->Param[2];
        }
    }else{
        //! 成立したランデブを登録する.
        ercd = CreateRdv( cal_tsk->Hdr.Id, p->MaxRepMsg );
        if( ercd != E_OK ){
            return ercd;
        }
        //! 成立したランデブ番号を受付タスクに通知する.
        acp_tsk->Param[3] = (VP)RdvSeqNo;

        //! ランデブ受付タスクにランデブ呼び出しメッセージをコピーする.
        if( acp_tsk->Param[1] && msg && csize > 0 ){
            memcpy( acp_tsk->Param[1], msg, csize );
            acp_tsk->Param[2] = (VP)csize;
        }else{
            acp_tsk->Param[2] = 0;
        }
        wi_TaskWakeup( acp_tsk->Hdr.Id, TTW_ACP, &(p->AcpWaitQue) );

        //! ランデブが終了するまでタスクをスリープさせる.
        ercd = wi_TaskWait( RdvSeqNo, TTW_RDV, tmout, 0, NULL );
        if( ercd == E_OK ){
            *rsize = (INT)cal_tsk->Param[2];
        }
    }
    return ercd;
}
	

ランデブの呼び出し関数は以下のような処理を行います。

  • 引数で指定されたランデブポートID番号に該当するランデブポート・オブジェクトを取り出します。
  • 非タスクコンテキストからの呼び出しの場合はエラー終了します。
  • ランデブ成立待ちをしているタスクがある場合、ランデブ条件ビットパターンをチェックして、ランデブが成立するかどうかを調べます。
  • ランデブが成立しない場合、タスクをスリープさせます。(以降ランデブ成立のチェックは、ランデブ受付け側で行います。)
  • ランデブが成立した場合、以下の処理を行います。
    1. 『ランデブ・オブジェクト』を生成します。
    2. ランデブ受付けタスクにランデブ呼び出しメッセージをコピーします。
    3. ランデブ受付けタスクを起床します。
  • ランデブが終了するまでタスクをスリープさせます。

ランデブが成立した場合、成立したランデブにランデブ番号を付けてランデブ・オブジェクトを生成します。


/****************************************************************************/
/*!
 *  @brief  ランデブの生成.
 *
 *  @param  [in]    tskid   ランデブ終了待ちのタスクのID番号.
 *  @param  [in]    rsize   返答メッセージの最大サイズ.
 *
 *  @retval エラーコード.
 */
static ER   CreateRdv( INT tskid, INT rsize )
{
    WIRDVOBJ *rdv;

    //! ランデブ番号をインクリメントする.
    if( RdvSeqNo >= TMAX_MAXRDV ){
        RdvSeqNo  = 1;
    }else{
        RdvSeqNo++;
    }
    //! ランデブ・オブジェクト構造体を確保する.
    rdv = (WIRDVOBJ *)malloc( sizeof(WIRDVOBJ) );
    if( !rdv ){
        return E_NOMEM;
    }
    memset( rdv, 0, sizeof(WIRDVOBJ) );
    rdv->Hdr.Id    = RdvSeqNo;
    rdv->TaskId    = tskid;
    rdv->MaxRepMsg = rsize;

    //! リストに成立したランデブを追加する.
    wi_AddObject( (WIHDR *)rdv, &RdvList );
    return E_OK;
}
	

ランデブが成立すると、ランデブ終了待ちを管理するランデブ・オブジェクトは、ランデブ呼出・受付を管理するランデブポート・オブジェクトとは切り離されますので、別のランデブポート・オブジェクトとは別のオブジェクト・リストで管理するようにします。



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