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 を指定して呼び出します。
ランデブが受け付けられない場合は、ランデブが受け付けられるまでタスクをスリープさせます。
ポーリングでランデブを呼び出すには以下のサービスコールを使用します。
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 |
タイムアウトの設定値。
|
戻り値 | 説明 |
---|---|
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 |
タイムアウトの設定値。
|
戻り値 | 説明 |
---|---|
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番号に該当するランデブポート・オブジェクトを取り出します。
- 非タスクコンテキストからの呼び出しの場合はエラー終了します。
- ランデブ成立待ちをしているタスクがある場合、ランデブ条件ビットパターンをチェックして、ランデブが成立するかどうかを調べます。
- ランデブが成立しない場合、タスクをスリープさせます。(以降ランデブ成立のチェックは、ランデブ受付け側で行います。)
- ランデブが成立した場合、以下の処理を行います。
- 『ランデブ・オブジェクト』を生成します。
- ランデブ受付けタスクにランデブ呼び出しメッセージをコピーします。
- ランデブ受付けタスクを起床します。
- ランデブが終了するまでタスクをスリープさせます。
ランデブが成立した場合、成立したランデブにランデブ番号を付けてランデブ・オブジェクトを生成します。
/****************************************************************************/
/*!
* @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;
}
ランデブが成立すると、ランデブ終了待ちを管理するランデブ・オブジェクトは、ランデブ呼出・受付を管理するランデブポート・オブジェクトとは切り離されますので、別のランデブポート・オブジェクトとは別のオブジェクト・リストで管理するようにします。