Windows版iTRONサービスコールの作成 (タスク管理)
(その9)
slp_tsk()、tslp_tsk()による待ち状態のタスクを起床するサービスコールは以下のとおりです。
サービスコール名 | 説明 |
---|---|
wup_tsk | 待ち状態のタスクを起床します。 |
iwup_tsk | 待ち状態のタスクを起床します。(非タスクコンテキストからの呼出し) |
can_wup | タスクの起床要求を無効化します。 |
※ iwup_tsk() はVer4.0のみサポートされます。
待ち状態のタスクを起床するには以下のサービスコールを使用します。
ER wup_tsk( ID tskid )
引数 | 説明 |
---|---|
tskid | タスクID番号。 |
戻り値 | 説明 |
---|---|
E_OK | 正常終了。 |
E_ID | 範囲外のタスクID番号。 |
E_NOEXS | 指定したタスクID番号のタスクが未登録。 |
E_OBJ | タスクが休止状態。 |
Ver4.0では割り込みハンドラや周期起動ハンドラ等の非タスク処理内からの呼び出しは、wup_tsk()ではなく、iwup_tsk()を使用します。
ER iwup_tsk( ID semid )
引数および戻り値は wup_tsk() と同じです。
・wup_tsk() サービスコールのソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief タスクの起床.
*
* @param [in] tskid タスクID番号.
*
* @retval エラーコード.
*/
ER wup_tsk( ID tskid )
{
ER ercd;
wi_CommonLock();
//! タスクを起床する.
ercd = wi_WakeupTask( tskid );
wi_CommonUnlock();
return ercd;
}
タスクID番号を引数にしてタスクを起床する関数を呼び出します。
・iwup_tsk() サービスコールのソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief タスクの起床 (非タスクコンテキストからの呼出し用).
*
* @param [in] tskid タスクID番号.
*
* @retval エラーコード.
*/
ER iwup_tsk( ID tskid )
{
return wup_tsk( tskid );
}
wup_tsk()を改めて呼び出すだけですので、wup_tsk()と同じ動作になります。
タスクを起床する関数
タスクを起床する関数のソースコードは以下のとおりです。
/****************************************************************************/
/*!
* @brief タスクの起床.
*
* @param [in] id タスクID番号.
*
* @retval エラーコード.
*/
ER wi_WakeupTask( INT id )
{
ER ercd;
//! 指定されたタスクに対してイベントを発行する.
ercd = wi_TaskWakeup( id, TTW_SLP, NULL );
//! 指定されたタスクがslp_tsk()でイベント待ちをしていない場合は起床要求カウンタを+1する.
if( ercd == E_OACV ){
WITSKOBJ *p = wi_GetTaskObject( id );
if( p ){
p->WakeupCnt++;
}
}
return E_OK;
}
タスクを起床する関数は以下のような処理を行います。
- 引数で指定されたタスクID番号に該当するタスクを起床するため、各オブジェクト共通のタスク起動処理(wi_TaskWakeup)を呼び出します。
- slp_tsk()またはtslp_tsk()でスリープしていないタスクの場合、wi_TaskWakeup()の戻り値がエラーになるので、起床要求カウンタを +1 します。
共通のタスク起動処理のソースコードは以下のとおりです。
/****************************************************************************/
/*!
* @brief イベント待ちしているタスクを起床させる.
*
* @param [in] id タスクID番号.
* @param [in] type イベント種別.
* @param [out] que 待ち行列の先頭のタスク・オブジェクトのポインタのポインタ.
*
* @retval エラーコード.
*/
ER wi_TaskWakeup( INT id, INT type, WIHDR **que )
{
ER ercd;
WITSKOBJ *tsk;
//! タスクIDのオブジェクトを取得する.
tsk = FindTaskObject( id, &ercd );
if( !tsk ){
return ercd;
}
//! イベント・ハンドルを作成していない場合はエラーにする.
if( !tsk->hEvent ){
return E_NOEXS;
}
//! イベント待ちをしていない場合はエラーにする.
if( tsk->EventType == 0 ){
return E_OACV;
}
//! タスクが休止中の場合はエラーにする.
if( tsk->TaskState == TTS_DMT ){
return E_OBJ;
}
//! 他のオブジェクトがイベント待ちをしている場合はエラーにする.
if( tsk->EventType != type ){
return E_OACV;
}
//! イベントを発行する.
if( !SetEvent( tsk->hEvent ) ){
return E_SYS;
}
//! 起床したタスクを待ち行列から削除する.
if( que ){
*que = wi_DelWaitTaskList( id, *que );
}
//! イベント・ハンドルを「未使用」に戻す.
tsk->EventType = 0;
tsk->WaitId = 0;
tsk->QueLink = NULL;
return E_OK;
}
共通のタスク起動処理は以下のような処理を行います。
- 引数で指定されたタスクID番号に該当するタスク・オブジェクトを取り出します。
- タスク・オブジェクトが取得できない場合はエラー終了します。
- 該当タスクがスリープしていない場合はエラー終了します。
- 該当タスクの状態が『休止中』の場合はエラー終了します。
- 呼び出したオブジェクトとタスクとスリープしたオブジェクトが違う場合はエラー終了します。
- イベント待ちでスリープしているタスクにイベントを発行して起床させます。
- 起床させたタスクを待ち行列から削除します。
タスクの起床要求を無効化するには以下のサービスコールを使用します。
※ Ver3.0とVer4.0では引数と戻り値が異なりますので注意してください。
・Ver3.0の場合
ER can_wup( INT *p_wupcnt, ID tskid )
引数 | 説明 |
---|---|
p_wupcnt | キューイングされていた起床要求回数を格納する領域のポインタ。 |
tskid | タスクID番号。 |
戻り値 | 説明 |
---|---|
E_OK | 正常終了。 |
E_ID | 範囲外のタスクID番号。 |
E_PAR | パラメータエラー。 |
E_OBJ | 指定したタスクID番号は登録済み。 |
・Ver4.0の場合
ER can_wup( ID tskid )
引数 | 説明 |
---|---|
tskid | タスクID番号。 |
戻り値 | 説明 |
---|---|
E_ID | 範囲外のタスクID番号。 |
E_PAR | パラメータエラー。 |
E_OBJ | 指定したタスクID番号は登録済み。 |
その他の正数 | キューイングされていた起床要求回数。 |
・Ver3.0のサービスコールのソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief タスクの起床要求を無効化.
*
* @param [in] p_wupcnt キューイングされていた起床要求回数を格納する領域のポインタ.
* @param [in] tskid タスクID番号.
*
* @retval エラーコード.
*/
ER can_wup( INT *p_wupcnt, ID tskid )
{
ER ercd;
wi_CommonLock();
//! タスクへの起床要求をクリアする.
ercd = wi_CancelWakeup( tskid, p_wupcnt );
wi_CommonUnlock();
return ercd;
}
タスクID番号と起床要求回数を格納する領域のポインタを引数にしてタスクの起床要求を無効化する関数を呼び出します。
・Ver4.0のサービスコールのソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief タスクの起床要求を無効化.
*
* @param [in] tskid タスクID番号.
*
* @retval キューイングされていた起床要求回数またはエラーコード.
*/
ER_UINT can_wup( ID tskid )
{
ER ercd;
INT wupcnt;
wi_CommonLock();
//! タスクへの起床要求をクリアする.
ercd = wi_CancelWakeup( tskid, &wupcnt );
if( ercd == E_OK ){
ercd = wupcnt;
}
wi_CommonUnlock();
return ercd;
}
タスクID番号と起床要求回数を格納する領域のポインタを引数にしてタスクの起床要求を無効化する関数を呼び出します。
タスクの起床要求を無効化する関数が正常終了で戻ってきた場合、戻り値をキューイングされていた起床要求回数として終了します。
タスクの起床要求を無効化する関数
タスクの起床要求を無効化する関数のソースコードは以下のとおりです。
/****************************************************************************/
/*!
* @brief タスクの起床要求を無効化.
*
* @param [in] id タスクID番号.
* @param [in] p_wupcnt キューイングされていた起床要求回数を格納する領域のポインタ.
*
* @retval エラーコード.
*/
ER wi_CancelWakeup( INT id, INT *p_wupcnt )
{
ER ercd;
WITSKOBJ *p;
//! タスクIDのオブジェクトを取得する.
p = FindTaskObject( id, &ercd );
if( !p ){
return ercd;
}
if( !p->hThread ){
return E_OBJ;
}
//! 起床要求回数を戻り値に格納する.
if( p_wupcnt ){
*p_wupcnt = p->WakeupCnt;
}
//! タスクの起床要求回数をクリアする.
p->WakeupCnt = 0;
return E_OK;
}
タスクの起床要求を無効化する関数は以下のような処理を行います。
- 引数で指定されたタスクID番号に該当するタスク・オブジェクトを取り出します。
- 引数 p_wupcnt が示す領域にキューイングしていた起床要求回数をセットします。
- タスク・オブジェクト中のタスクの起床要求回数をクリアします。