Windows版iTRONサービスコールの作成 (タスク機能)
(その4)
タスクを起動するサービスコールは以下のとおりです。
サービスコール名 | 説明 |
---|---|
sta_tsk | 引数を指定してタスクを起動します。 |
act_tsk | 引数を指定せずにタスクを起動します。 |
iact_tsk | 引数を指定せずにタスクを起動します。(非タスクコンテキストからの呼出し) |
can_act | タスクの起動要求をキャンセルします。 |
※ act_tsk()、iact_tsk() および can_act() はVer4.0のみサポートされます。
引数を指定してタスクを起動するには以下のサービスコールを使用します。
ER sta_tsk( ID tskid, VP_INT stacd )
引数 | 説明 |
---|---|
tskid | タスクID番号。 |
stacd | タスクの起動処理に渡す引数。 |
戻り値 | 説明 |
---|---|
E_OK | 正常終了。 |
E_ID | 範囲外のタスクID番号。 |
E_NOEXS | 指定したタスクID番号のタスクが未登録。 |
・サービスコールのソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief タスクの起動.
*
* @param [in] tskid タスクID番号.
* @param [in] stacd タスク起動コード.
*
* @retval エラーコード.
*/
ER sta_tsk( ID tskid, VP_INT stacd )
{
ER ercd;
wi_CommonLock();
//! タスクを起動する.
ercd = wi_StartTask( tskid, (DWORD)stacd, TRUE );
wi_CommonUnlock();
return ercd;
}
タスクID番号を引数にしてタスクの起動関数を呼び出します。
引数を指定せずにタスクを起動するには以下のサービスコールを使用します。
ER act_tsk( ID tskid )
引数 | 説明 |
---|---|
tskid | タスクID番号。 |
戻り値 | 説明 |
---|---|
E_OK | 正常終了。 |
E_ID | 範囲外のタスクID番号。 |
E_NOEXS | 指定したタスクID番号のタスクが未登録。 |
割り込みハンドラや周期起動ハンドラ等の非タスク処理内からの呼び出しは、act_tsk()ではなく、iact_tsk()を使用します。
ER iact_tsk( ID tskid )
引数および戻り値は act_tsk() と同じです。
※ act_tsk() および iact_tsk() の場合、タスク起動時の引数は cre_tsk() で設定したT_CTSK構造体のexinf(拡張情報)を使用します。
・サービスコールのソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief タスクの起動.
*
* @param [in] tskid タスクID番号.
*
* @retval エラーコード.
*/
ER act_tsk( ID tskid )
{
ER ercd;
wi_CommonLock();
//! タスクを起動する.
ercd = wi_StartTask( tskid, 0, FALSE );
wi_CommonUnlock();
return ercd;
}
タスクID番号を引数にしてタスクの起動関数を呼び出します。
・iact_tsk() サービスコールのソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief タスクの起動 (非タスクコンテキストからの呼出し用).
*
* @param [in] tskid タスクID番号.
*
* @retval エラーコード.
*/
ER iact_tsk( ID tskid )
{
return act_tsk( tskid );
}
act_tsk()を改めて呼び出すだけですので、act_tsk()と同じ動作になります。
タスクの起動関数
タスクを起動する関数のソースコードは以下のとおりです。
/****************************************************************************/
/*!
* @brief タスクの起動.
*
* @param [in] id タスクID番号.
* @param [in] start_code タスク起動コード.
* @param [in] exist_stcd TRUE = タスク起動コードあり.
*
* @retval エラーコード.
*/
ER wi_StartTask( INT id, DWORD start_code, BOOL exist_stcd )
{
WITSKOBJ *p;
//! タスクIDのオブジェクトを取得する.
p = wi_GetTaskObject( id );
if( !p ){
return E_ID;
}
if( p->hThread ){
//! スレッドが終了しているかどうかを調べる.
DWORD code;
if( !GetExitCodeThread( p->hThread, &code ) ){
return E_SYS;
}
//! スレッドが起動中の場合.
if( code == STILL_ACTIVE ){
if( !exist_stcd ){
//! act_tsk(),iact_tsk()からの呼び出しの場合は起動要求回数をカウントアップする.
if( p->ActiveCnt + 1 > TMAX_ACTCNT ){
return E_QOVR;
}
//! 起動要求回数をカウントアップする.
p->ActiveCnt++;
return E_OK;
}else{
//! sta_tsk()からの呼び出しの場合はエラーにする.
return E_OBJ;
}
}
//! 休止中のスレッドのスレッドハンドルをクローズする.
CloseHandle( p->hThread );
p->hThread = NULL;
}
p->SuspendCnt = 0;
p->WakeupCnt = 0;
p->ActiveCnt = 0;
if( exist_stcd ){
//! sta_tsk()からの呼び出しの場合は引数の起動コードを使用する.
p->StartCode = start_code;
}else{
//! act_tsk(),iact_tsk()からの呼び出しの場合はcre_tsk()時の拡張情報を起動コードとする.
p->StartCode = (DWORD)p->ExtInfo;
}
//! タスクの状態を「実行可能状態」にする.
p->TaskState = TTS_RDY;
//! スレッドを休止状態で起動する.
p->hThread = (HANDLE)_beginthreadex( NULL, 0, &UserTask, p, CREATE_SUSPENDED, &(p->ThreadId) );
//! スレッドの優先度を設定する.
SetThreadPriority( p->hThread, ConvertPriority( p->InitPri ) );
//! スレッドの休止状態を解除する.
if( ResumeThread( p->hThread ) == -1 ){
return E_SYS;
}
return E_OK;
}
タスクを起動する関数は以下のような処理を行います。
- 引数で指定されたタスクID番号に該当するタスク・オブジェクトを取り出します。
- スレッド・ハンドルを既に生成している場合は以下の処理を行います。
- スレッドが終了しているどうかを調べます。
- スレッドが動作中の場合、act_tsk() または iact_tsk()からの呼び出しの場合は起動要求回数をカウントアップし処理を終了します。
- sta_tsk()からの呼び出しの場合はエラー終了にします。
- スレッドが休止中であれば、スレッド・ハンドルをクローズします。
- タスク起動時の引数(起動コード)をタスク・オブジェクトにセットします。
- タスクの状態を『実行可能状態』にします。
- _beginthreadex()を呼び出して新しいスレッドを休止状態で生成します。
- SetThreadPriority()を呼び出して新たに生成したスレッドの優先度を設定します。
- ResumeThread()を呼び出してスレッドの休止状態を解除して処理を終了します。
スレッドを生成するのは _beginthreadex() を呼び出します。
uintptr_t _beginthreadex( void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr )
引数 | 説明 |
---|---|
security | SECURITY_ATTRIBUTES構造体のポインタ。 |
stack_size | スタックサイズ。0の場合スタックサイズはWindowsが決めます。 |
start_address | スレッドの起動関数のポインタ。 |
arglist | スレッドに渡される引数リスト。 |
initflag | スレッドの起動状態。(0 = 実行中 / CREATE_SUSPENDED = 休止中) |
thrdaddr | スレッド識別子を格納する領域のポインタ。 |
呼び出しに成功するとスレッド・ハンドルが返ります。
関数が失敗すると、NULL が返ります。
スレッドの優先度を設定するのは SetThreadPriority() を呼び出します。
BOOL SetThreadPriority( HANDLE hThread, int nPriority )
引数 | 説明 |
---|---|
hThread | スレッドのハンドル。 |
nPriority | スレッドの相対優先順位値。 |
呼び出しに成功すると TRUE、関数が失敗すると FALSE が返ります。
スレッドの休止状態を解除するには ResumeThread() を呼び出します。
DWORD ResumeThread( HANDLE hThread )
引数 | 説明 |
---|---|
hThread | スレッドのハンドル。 |
呼び出しに成功すると、関数を呼び出す前のサスペンド受付数が返ります。
関数が失敗すると、-1 が返ります。
・生成されたスレッドの起動関数のソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief ユーザータスクを起動する.
*
* @param [in] arg タスク・オブジェクト構造体のポインタ.
*
* @retval 常に0を返す.
*/
static unsigned __stdcall UserTask( void* arg )
{
WITSKOBJ *p = (WITSKOBJ *)arg;
if( p ){
//! タスクの状態を「実行中」にする.
p->TaskState = TTS_RUN;
//! ユーザータスクを呼び出す.
p->TaskAdr( p->StartCode );
//! タスクの状態を「休止中」にする.
p->TaskState = TTS_DMT;
}
_endthreadex( 0 );
return 0;
}
生成されたスレッドの起動関数は以下のような処理を行います。
- タスクの状態を『実行中』にします。
- cre_tsk() で指定されたユーザータスクのエントリ関数を呼び出します。
- ユーザータスクが終了して処理が返ってきたらタスクの状態を『休止中』にします。
- _endthreadex()を呼び出してスレッドを休止状態にします。
タスクの起動要求をキャンセルするには以下のサービスコールを使用します。
ER can_act( ID tskid )
引数 | 説明 |
---|---|
tskid | タスクID番号。 |
戻り値 | 説明 |
---|---|
E_ID | 範囲外のタスクID番号。 |
E_NOEXS | 指定したタスクID番号のタスクが未登録。 |
その他の正数 | キューイングされていた起動要求回数。 |
・サービスコールのソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief タスク起動要求のキャンセル.
*
* @param [in] tskid タスクID番号.
*
* @retval エラーコード.
*/
ER_UINT can_act( ID tskid )
{
ER_UINT ercd;
wi_CommonLock();
//! タスクの起動要求をキャンセルする.
ercd = (ER_UINT)wi_CancelStartReq( tskid );
wi_CommonUnlock();
return ercd;
}
・タスク起動要求のキャンセル関数のソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief タスク起動要求のキャンセル.
*
* @param [in] id タスクID番号.
*
* @retval キューイングされていた起動要求回数またはエラーコード.
*/
int wi_CancelStartReq( INT id )
{
int cnt;
ER ercd;
WITSKOBJ *p;
//! タスクIDのオブジェクトを取得する.
p = FindTaskObject( id, &ercd );
if( !p ){
return ercd;
}
//! 起動要求回数を取り出す.
cnt = p->ActiveCnt;
//! 起動要求回数をクリアする.
p->ActiveCnt = 0;
return cnt;
}
タスク起動要求のキャンセル関数は以下のような処理を行います。
- 引数で指定されたタスクID番号に該当するタスク・オブジェクトを取り出します。
- 現在の起動要求回数を戻り値としてタスク・オブジェクトから取り出します。
- タスク・オブジェクトの起動要求回数をクリアします。