Windows版iTRONサービスコールの作成 (タスク管理)
(その8)
タスクをスリープさせるサービスコールは以下のとおりです。
サービスコール名 | 説明 |
---|---|
slp_tsk | タイムアウトなしでタスクをスリープさせます。 |
tslp_tsk | タイムアウト付きでタスクをスリープさせます。 |
※ Ver3.0、Ver4.0共に同じサービスコールの形式です。
タイムアウトなしでスリープさせるには以下のサービスコールを使用します。
ER slp_tsk( void )
戻り値 | 説明 |
---|---|
E_OK | 正常終了。 |
E_CTX | 非コンテキスト・タスクからの呼び出し。 |
・サービスコールのソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief 起床待ち (タイムアウトなし).
*
* @param なし.
*
* @retval エラーコード.
*/
ER slp_tsk( void )
{
//! タイムアウトなしでタスクを起床待ちにする.
return tslp_tsk( TMO_FEVR );
}
tslp_tsk()のタイムアウト設定に TMO_FEVR を指定して呼び出します。
wup_tsk()またはiwup_tsk()から起床されるまでタスクをスリープさせます。
タイムアウト付きでスリープさせるには以下のサービスコールを使用します。
ER tslp_tsk( TMO tmout )
引数 | 説明 |
---|---|
tmout |
タイムアウトの設定値。
|
戻り値 | 説明 |
---|---|
E_OK | 正常終了。 |
E_TMOUT | wup_tsk()から起床されずにタイムアウト。 |
E_CTX | 非コンテキスト・タスクからの呼び出し。 |
・サービスコールのソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief 起床待ち (タイムアウトあり).
*
* @param [in] tmout タイムアウト設定.
*
* @retval エラーコード.
*/
ER tslp_tsk( TMO tmout )
{
ER ercd;
wi_CommonLock();
//! タスクを起床待ちにする.
ercd = wi_SleepTask( tmout );
wi_CommonUnlock();
return ercd;
}
サービスコールを呼び出したタスクをスリープさせます。
wup_tsk()またはiwup_tsk()から起床されるか、タイムアウトで設定した時間が経過するまでタスクをスリープさせます。
タスクをスリープさせる関数
タスクをスリープさせる関数のソースコードは以下のとおりです。
/****************************************************************************/
/*!
* @brief 起床待ち.
*
* @param [in] tmout タイムアウト設定.
*
* @retval エラーコード.
*/
ER wi_SleepTask( TMO tmout )
{
ER ercd;
WITSKOBJ *p;
//! 自タスクのタスク・オブジェクトを取得する.
p = FindTaskObject( TSK_SELF, &ercd );
if( !p ){
return E_OBJ;
}
if( !p->hThread ){
return E_OBJ;
}
//! 起床要求カウンタが貯まっている場合はイベント待ちをしないで正常終了にする.
if( p->WakeupCnt > 0 ){
p->WakeupCnt--;
return E_OK;
}
//! イベント待ちをする.
return wi_TaskWait( p->Hdr.Id, TTW_SLP, tmout, 0, NULL );
}
タスクをスリープさせる関数は以下のような処理を行います。
- 自タスクのタスク・オブジェクトをリストから取得します。
- 既にwup_tsk()またはiwup_tsk()が呼び出されて起床要求カウンタが貯まっている場合はイベント待ちをしないで正常終了にします。
- 起床要求カウンタが 0 の場合は、wup_tsk()またはiwup_tsk()が呼び出されるまで、オブジェクト共通のタスク・スリープ処理()を呼び出してタスクをスリープさせます。
共通のタスク起動処理のソースコードは以下のとおりです。
/****************************************************************************/
/*!
* @brief 自タスクをイベント待ちにする.
*
* @param [in] wid 待ちオブジェクトのID.
* @param [in] type イベント種別.
* @param [in] tmout タイムアウト設定.
* @param [in] pri オブジェクトの属性.
* @param [out] que 待ち行列の先頭のタスク・オブジェクトのポインタのポインタ.
*
* @retval エラーコード.
*/
ER wi_TaskWait( INT wid, INT type, TMO tmout, ATR pri, WIHDR **que )
{
DWORD ret_code;
ER ercd;
WITSKOBJ *tsk;
//! ポーリングの場合はタイムアウトで終了する.
if( tmout == TMO_POL ){
return E_TMOUT;
}
//! 自タスクのタスク・オブジェクトを取得する.
tsk = FindTaskObject( TSK_SELF, &ercd );
if( !tsk ){
return E_CTX;
}
//! イベント・ハンドルを作成していない場合はエラーにする.
if( !tsk->hEvent ){
return E_NOEXS;
}
//! 他のオブジェクトがイベント待ちをしている場合は処理を終了にする.
if( tsk->EventType != 0 ){
return E_OACV;
}
//! イベント・ハンドルを「使用中」にする.
tsk->EventType = type;
tsk->WaitId = wid;
tsk->QueLink = NULL;
tsk->TaskState = TTS_WAI;
//! タスクを待ち行列に追加する.
if( que ){
*que = wi_AddWaitTaskList( TSK_SELF, pri, *que );
}
//! ミューテックスを一旦解除する.
wi_CommonUnlock();
//! イベントの発生を待つ.
ret_code = WaitForSingleObject( tsk->hEvent, wi_CvtTimeOutValue( tmout ) );
//! 再度ミューテックスを掛ける.
wi_CommonLock();
//! タスクを待ち行列から削除する.
if( que ){
*que = wi_DelWaitTaskList( TSK_SELF, *que );
}
//! イベント・ハンドルを「未使用」に戻す.
tsk->EventType = 0;
tsk->WaitId = 0;
tsk->QueLink = NULL;
tsk->TaskState = TTS_RUN;
switch( ret_code ){
case WAIT_OBJECT_0:
if( tsk->DelRes ){
ercd = E_DLT;
}else
if( tsk->RelRes ){
ercd = E_RLWAI;
}else{
ercd = E_OK;
}
break;
case WAIT_TIMEOUT:
ercd = E_TMOUT;
break;
default:
ercd = E_SYS;
break;
}
tsk->DelRes = FALSE;
tsk->RelRes = FALSE;
return ercd;
}
共通のタスク・スリープ処理は以下のような処理を行います。
- タスクをスリープさせるオブジェクトがポーリング方式で呼ばれていた場合はタイムアウトでエラー終了します。
- 自タスクのタスク・オブジェクトをリストから取得します。
- 既に他のオブジェクトでタスクがスリープされている場合はエラー終了します。(多分、ないですけど。)
- スリープするオブジェクト種別とオブジェクトIDをタスク・オブジェクトにセットします。
- 呼び出し元から待ち行列が指定されている場合、待ち行列にスリープするタスク・オブジェクトを追加します。
- 呼び出し元でロックしてあるはずのミューテックスを一旦解除します。
- イベント待ちでタスクをスリープさせます。
- 一旦解除したミューテックスを再びロックします。
- 呼び出し元から待ち行列が指定されている場合、待ち行列からスリープしたタスク・オブジェクトを削除します。
- スリープしたタスク・オブジェクトからオブジェクト種別とオブジェクトIDをクリアします。
- タスクがイベントを受けて起床した場合、戻り値を以下のようにします。
- タスクが削除されるときに起床した場合、戻り値は『E_DLT(タスクの削除)』にします。
- rel_wai() または irel_wai() によっていタスクが起床した場合、戻り値は『E_RLWAI(タスクの待ち状態の強制解除)』にします。
- その他の場合、戻り値は『E_OK(正常終了)』にします。
- タスクがタイムアウトで起床した場合、戻り値は『E_TMOUT(タイムアウト)』にします。
- その他の要因で起床した場合、戻り値は『E_SYS(システムエラー)』にします。