/* * 自タスクの終了 */ StatusType TerminateTask(void) { StatusType ercd = E_OK; LOG_TERTSK_ENTER(); CHECK_CALLEVEL(TCL_TASK); CHECK_RESOURCE(tcb_lastres[runtsk] == RESID_NULL); lock_cpu(); /* * 内部リソースの解放は優先度を下げるだけなので,ここでは * 何もしなくてよい. */ tcb_tstat[runtsk] = TS_DORMANT; search_schedtsk(); if (tcb_actcnt[runtsk] > 0) { tcb_actcnt[runtsk] -= 1; (void)make_active(runtsk); } exit_and_dispatch(); /* ここには戻ってこない */ error_exit: lock_cpu(); call_errorhook(ercd, OSServiceId_TerminateTask); unlock_cpu(); LOG_TERTSK_LEAVE(ercd); return(ercd); }
/* * 自タスクの終了とタスクの起動 */ StatusType ChainTask(TaskType tskid) { /* * ここでの ercd の初期化は本来は不要であるが,コンパイラの警 * 告メッセージを避けるために初期化している. */ StatusType ercd = E_OK; LOG_CHNTSK_ENTER(tskid); CHECK_CALLEVEL(TCL_TASK); CHECK_RESOURCE(tcb_lastres[runtsk] == RESID_NULL); CHECK_TSKID(tskid); lock_cpu(); if (tskid == runtsk) { // tcb_tstat[runtsk] = TS_DORMANT; search_schedtsk(); (void)make_active(runtsk); } else { /* * エラー時に副作用が残らないように,エラーチェックは * タスク終了処理の前に行う必要がある. */ if ((tcb_tstat[tskid] != TS_DORMANT) && (tcb_actcnt[tskid] >= tinib_maxact[tskid])) { ercd = E_OS_LIMIT; goto d_error_exit; } tcb_tstat[runtsk] = TS_DORMANT; search_schedtsk(); if (tcb_actcnt[runtsk] > 0) { tcb_actcnt[runtsk] -= 1; (void)make_active(runtsk); } if (tcb_tstat[tskid] == TS_DORMANT) { (void)make_active(tskid); } else { tcb_actcnt[tskid] += 1; } } exit_and_dispatch(); /* ここには戻ってこない */ error_exit: lock_cpu(); d_error_exit: _errorhook_par1.tskid = tskid; call_errorhook(ercd, OSServiceId_ChainTask); unlock_cpu(); LOG_CHNTSK_LEAVE(ercd); return(ercd); }
ER ext_tsk(void) { ER ercd; LOG_EXT_TSK_ENTER(); CHECK_TSKCTX(); if (t_sense_lock()) { /* * CPUロック状態でext_tskが呼ばれた場合は,CPUロックを解除し * てからタスクを終了する.実装上は,サービスコール内でのCPU * ロックを省略すればよいだけ. */ } else { t_lock_cpu(); } if (disdsp) { /* * ディスパッチ禁止状態でext_tskが呼ばれた場合は,ディスパッ * チ許可状態にしてからタスクを終了する. */ disdsp = false; } if (!ipmflg) { /* * 割込み優先度マスク(IPM)がTIPM_ENAALL以外の状態でext_tsk * が呼ばれた場合は,IPMをTIPM_ENAALLにしてからタスクを終了す * る. */ t_set_ipm(TIPM_ENAALL); ipmflg = true; } dspflg = true; (void) make_non_runnable(p_runtsk); if (!queue_empty(&(p_runtsk->mutex_queue))) { (void) (*mtxhook_release_all)(p_runtsk); } #ifdef TOPPERS_SUPPORT_OVRHDR ovrtimer_stop(); #endif /* TOPPERS_SUPPORT_OVRHDR */ make_dormant(p_runtsk); if (p_runtsk->actque) { p_runtsk->actque = false; (void) make_active(p_runtsk); } exit_and_dispatch(); ercd = E_SYS; error_exit: LOG_EXT_TSK_LEAVE(ercd); return(ercd); }
ER ext_tsk(void) { ER ercd; LOG_EXT_TSK_ENTER(); CHECK_TSKCTX(); if (t_sense_lock()) { /* * CPUロック状態でext_tskが呼ばれた場合は,CPUロックを解除し * てからタスクを終了する.実装上は,サービスコール内でのCPU * ロックを省略すればよいだけ. */ } else { t_lock_cpu(); } if (disdsp) { /* * ディスパッチ禁止状態でext_tskが呼ばれた場合は,ディスパッ * チ許可状態にしてからタスクを終了する. */ disdsp = false; } if (t_get_ipm() != TIPM_ENAALL) { /* * 割込み優先度マスク(IPM)がTIPM_ENAALL以外の状態でext_tsk * が呼ばれた場合は,IPMをTIPM_ENAALLにしてからタスクを終了す * る. */ t_set_ipm(TIPM_ENAALL); } dspflg = true; (void) make_non_runnable(p_runtsk); make_dormant(p_runtsk); if (p_runtsk->actque) { p_runtsk->actque = false; (void) make_active(p_runtsk); } exit_and_dispatch(); return(E_SYS); error_exit: LOG_EXT_TSK_LEAVE(ercd); return(ercd); }
ER ext_tsk(void) { ER ercd; PCB *t_p_pcb; PCB *my_p_pcb; TCB *p_runtsk; bool_t locked; LOG_EXT_TSK_ENTER(); CHECK_TSKCTX(); /* * CPUロック状態でext_tskが呼ばれた場合は,ロック取得時に割込みを許可 * しない. * ロック取得時に割込みを許可しないのは, 過度状態の場合にロックを取得 * できなかった場合に割込みを許可すると,割込みが入りサスペンド状態と * なってしまうためである. */ locked = t_sense_lock(); retry: if (locked) { my_p_pcb = acquire_tsk_lock_without_preemption_self(); } else { t_lock_cpu(); my_p_pcb = t_acquire_tsk_lock_self_without_runnable_check(); } p_runtsk = my_p_pcb->p_runtsk; /* 再起動時のマイグレーションなし */ if ((p_runtsk->actprc == TPRC_NONE) || (p_runtsk->actprc == my_p_pcb->prcid)) { /* * ディスパッチ禁止状態でext_tskが呼ばれた場合に対応して,ディスパッ * チ許可状態にしてからタスクを終了する. */ my_p_pcb->disdsp = false; /* * 割込み優先度マスク(IPM)がTIPM_ENAALL以外の状態でext_tskが呼ばれ * た場合に対応して,IPMをTIPM_ENAALLにしてからタスクを終了する. */ t_set_ipm(TIPM_ENAALL); my_p_pcb->ipmflg = true; my_p_pcb->dspflg = true; /* * スピンロックを取得している場合は,スピンロックを解除する */ force_unlock_spin(my_p_pcb); (void) make_non_runnable(p_runtsk); make_dormant(p_runtsk); if (p_runtsk->actque) { p_runtsk->actque = false; p_runtsk->actprc = TPRC_NONE; (void) make_active(p_runtsk); } release_tsk_lock(my_p_pcb); exit_and_dispatch(); ercd = E_SYS; } else { /* 移動先のプロセッサのPCBを取得 */ t_p_pcb = get_mp_p_pcb(p_runtsk->actprc); /* 一旦タスクロックを離す */ release_tsk_lock(my_p_pcb); /* * 現在割り付けられているプロセッサと移動先のプロセッサのタスク * ロックを取得 */ if (locked) { acquire_dual_tsk_lock_without_preemption(p_runtsk, p_runtsk->actprc, &my_p_pcb, &t_p_pcb); } else { t_acquire_dual_tsk_lock(p_runtsk, p_runtsk->actprc, &my_p_pcb, &t_p_pcb); } /* * マイグレーション先のプロセッサが変更された場合はリトライ */ if (p_runtsk->actprc != t_p_pcb->prcid) { release_dual_tsk_lock(p_runtsk->p_pcb, t_p_pcb); goto retry; } /* * ここで各カーネル状態を変更するのは,ディスパッチ禁止状態と割込 * み優先度マスク全解除状態でない状態による過度状態の場合に,各カ * ーネル状態を変更してから,ロック取得関数で割込みを許可して割込 * みが入ると,割込みからのリターン時にディスパッチャが呼ばれてし * まい,休止状態となるためである. */ my_p_pcb->disdsp = false; t_set_ipm(TIPM_ENAALL); my_p_pcb->ipmflg = true; my_p_pcb->dspflg = true; force_unlock_spin(my_p_pcb); /* 現在コンテキストを捨ててマイグレーション */ exit_and_migrate(p_runtsk->actprc); ercd = E_SYS; } error_exit: LOG_EXT_TSK_LEAVE(ercd); return(ercd); }
ER ext_tsk(void) { ER ercd; PCB *my_p_pcb; TCB *p_runtsk; LOG_EXT_TSK_ENTER(); CHECK_TSKCTX(); /* * CPUロック状態でext_tskが呼ばれた場合は,ロック取得時に割込みを許可 * しない. * ロック取得時に割込みを許可しないのは, 過度状態の場合にロックを取得 * できなかった場合に割込みを許可すると,割込みが入りサスペンド状態と * なってしまうためである. * ディスパッチ禁止や割込み優先度マスク全解除状態でない場合の過度状態の * 場合は,割込みが入っても割込みの出口でディスパッチャに行かずに戻って * くるため問題ない. */ if (t_sense_lock()) { my_p_pcb = acquire_tsk_lock_without_preemption_self(); } else { t_lock_cpu(); my_p_pcb = t_acquire_tsk_lock_self_without_runnable_check(); } p_runtsk = my_p_pcb->p_runtsk; if (my_p_pcb->disdsp) { /* * ディスパッチ禁止状態でext_tskが呼ばれた場合に対応して,ディスパッ * チ許可状態にしてからタスクを終了する. */ my_p_pcb->disdsp = false; } if (!my_p_pcb->ipmflg) { /* * 割込み優先度マスク(IPM)がTIPM_ENAALL以外の状態でext_tskが呼ばれ * た場合に対応して,IPMをTIPM_ENAALLにしてからタスクを終了する. */ t_set_ipm(TIPM_ENAALL); my_p_pcb->ipmflg = true; } my_p_pcb->dspflg = true; /* * スピンロックを取得している場合は,スピンロックを解除する */ force_unlock_spin(my_p_pcb); /* 再起動時のマイグレーションなし */ if ((p_runtsk->actprc == TPRC_NONE) || (p_runtsk->actprc == my_p_pcb->prcid)) { (void) make_non_runnable(p_runtsk); make_dormant(p_runtsk); if (p_runtsk->actque) { p_runtsk->actque = false; p_runtsk->actprc = TPRC_NONE; (void) make_active(p_runtsk); } release_tsk_lock(my_p_pcb); exit_and_dispatch(); ercd = E_SYS; } else { /* 現在コンテキストを捨ててマイグレーション */ exit_and_migrate(p_runtsk->actprc); ercd = E_SYS; } error_exit: LOG_EXT_TSK_LEAVE(ercd); return(ercd); }