ER istp_ovr(ID tskid) { TCB *p_tcb; ER ercd; LOG_ISTP_OVR_ENTER(tskid); CHECK_INTCTX_UNL(); CHECK_OBJ(ovrinib.ovrhdr != NULL); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); i_lock_cpu(); if (p_tcb->p_tinib->tskatr == TA_NOEXS) { ercd = E_NOEXS; } else { p_tcb->leftotm = 0U; ercd = E_OK; } i_unlock_cpu(); error_exit: LOG_ISTP_OVR_LEAVE(ercd); return(ercd); }
ER irel_wai(ID tskid) { TCB *p_tcb; ER ercd; LOG_IREL_WAI_ENTER(tskid); CHECK_INTCTX_UNL(); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); i_lock_cpu(); if (p_tcb->p_tinib->tskatr == TA_NOEXS) { ercd = E_NOEXS; } else if (!TSTAT_WAITING(p_tcb->tstat)) { ercd = E_OBJ; } else { if (wait_release(p_tcb)) { reqflg = true; } ercd = E_OK; } i_unlock_cpu(); error_exit: LOG_IREL_WAI_LEAVE(ercd); return(ercd); }
/* * Termination of other task */ SYSCALL ER tk_ter_tsk_impl( ID tskid ) { TCB *tcb; TSTAT state; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_NONSELF(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; state = (TSTAT)tcb->state; if ( !knl_task_alive(state) ) { ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; } else if ( tcb->klocked ) { /* Normally, it does not become this state. * When the state is page-in wait in the virtual memory * system and when trying to terminate any task, * it becomes this state. */ ercd = E_OBJ; } else { knl_ter_tsk(tcb); knl_make_dormant(tcb); } END_CRITICAL_SECTION; return ercd; }
ER ista_ovr(ID tskid, OVRTIM ovrtim) { TCB *p_tcb; ER ercd; LOG_ISTA_OVR_ENTER(tskid, ovrtim); CHECK_INTCTX_UNL(); CHECK_OBJ(ovrinib.ovrhdr != NULL); CHECK_TSKID(tskid); CHECK_PAR(0U < ovrtim && ovrtim <= TMAX_OVRTIM); p_tcb = get_tcb(tskid); i_lock_cpu(); if (p_tcb->p_tinib->tskatr == TA_NOEXS) { ercd = E_NOEXS; } else { p_tcb->leftotm = ovrtim; ercd = E_OK; } i_unlock_cpu(); error_exit: LOG_ISTA_OVR_LEAVE(ercd); return(ercd); }
ER iact_tsk(ID tskid) { ER ercd; uint_t itskpri; LOG_IACT_TSK_ENTER(tskid); CHECK_INTCTX_UNL(); CHECK_TSKID(tskid); itskpri = get_ipri(tskid); i_lock_cpu(); if (test_dormant(itskpri)) { if(make_active(itskpri)) { reqflg = true; } ercd = E_OK; } else { ercd = E_QOVR; } i_unlock_cpu(); error_exit: LOG_IACT_TSK_LEAVE(ercd); return(ercd); }
/* * Set task register */ SYSCALL ER _td_set_reg( ID tskid, T_REGS *regs, T_EIT *eit, T_CREGS *cregs ) { TCB *tcb; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_NONSELF(tskid); #if 0 /* (030206) This is not an error. Please ignore. */ if ( eit != NULL ) { if ( (eit->sr & (SR_BL|SR_I(15))) != 0 ) { return E_PAR; } } #endif tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; } else if ( !MP_CMP_DOMIDPART(tskid, tcb->tskid) ) { ercd = E_NOEXS; } else if ( is_ctxtsk(tcb) ) { ercd = E_OBJ; } else { set_reg(tcb, regs, eit, cregs); } END_CRITICAL_NO_DISPATCH; return ercd; }
/* * Get task register contents */ SYSCALL ER _tk_get_reg( ID tskid, T_REGS *pk_regs, T_EIT *pk_eit, T_CREGS *pk_cregs ) { TCB *tcb; ER ercd = E_OK; CHECK_INTSK(); CHECK_TSKID(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; } else { ercd = mp_check_domain_and_protection(tskid, tcb->tskid, tcb->tskatr); if ( ercd == E_OK ) { if ( is_ctxtsk(tcb) ) { ercd = E_OBJ; } else { get_reg(tcb, pk_regs, pk_eit, pk_cregs); } } } END_CRITICAL_NO_DISPATCH; return ercd; }
ER ter_tsk(ID tskid) { TCB *p_tcb; bool_t dspreq = false; ER ercd; LOG_TER_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); CHECK_NONSELF(p_tcb); t_lock_cpu(); if (p_tcb->p_tinib->tskatr == TA_NOEXS) { ercd = E_NOEXS; } else if (VIOLATE_ACPTN(p_tcb->p_tinib->acvct.acptn2)) { ercd = E_OACV; } else if (TSTAT_DORMANT(p_tcb->tstat)) { ercd = E_OBJ; } else { if (TSTAT_RUNNABLE(p_tcb->tstat)) { /* * p_tcbは自タスクでないため,(シングルプロセッサでは)実 * 行状態でなく,make_non_runnable(p_tcb)でタスクディスパッ * チが必要になることはない. */ (void) make_non_runnable(p_tcb); } else if (TSTAT_WAITING(p_tcb->tstat)) { wait_dequeue_wobj(p_tcb); wait_dequeue_tmevtb(p_tcb); } if (!queue_empty(&(p_tcb->mutex_queue))) { if ((*mtxhook_release_all)(p_tcb)) { dspreq = true; } } make_dormant(p_tcb); if (p_tcb->actque) { p_tcb->actque = false; if (make_active(p_tcb)) { dspreq = true; } } if (dspreq) { dispatch(); } ercd = E_OK; } t_unlock_cpu(); error_exit: LOG_TER_TSK_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 rsm_tsk(ID tskid) { TCB *p_tcb; ER ercd; LOG_RSM_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); t_lock_cpu(); if (p_tcb->p_tinib->tskatr == TA_NOEXS) { ercd = E_NOEXS; } else if (VIOLATE_ACPTN(p_tcb->p_tinib->acvct.acptn2)) { ercd = E_OACV; } else if (!TSTAT_SUSPENDED(p_tcb->tstat)) { ercd = E_OBJ; } else if (!TSTAT_WAITING(p_tcb->tstat)) { /* * 強制待ち状態から実行できる状態への遷移 */ p_tcb->tstat = TS_RUNNABLE; LOG_TSKSTAT(p_tcb); if (make_runnable(p_tcb)) { dispatch(); } ercd = E_OK; } else { /* * 二重待ち状態から待ち状態への遷移 */ p_tcb->tstat &= ~TS_SUSPENDED; LOG_TSKSTAT(p_tcb); ercd = E_OK; } t_unlock_cpu(); error_exit: LOG_RSM_TSK_LEAVE(ercd); return(ercd); }
ER ter_tsk(ID tskid) { TCB *p_tcb; ER ercd; LOG_TER_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); CHECK_NONSELF(p_tcb); t_lock_cpu(); if (TSTAT_DORMANT(p_tcb->tstat)) { ercd = E_OBJ; } else { if (TSTAT_RUNNABLE(p_tcb->tstat)) { /* * p_tcbは自タスクでないため,(シングルプロセッサでは)実 * 行状態でなく,make_non_runnable(p_tcb)でタスクディスパッ * チが必要になることはない. */ (void) make_non_runnable(p_tcb); } else if (TSTAT_WAITING(p_tcb->tstat)) { wait_dequeue_wobj(p_tcb); wait_dequeue_tmevtb(p_tcb); } make_dormant(p_tcb); if (p_tcb->actque) { p_tcb->actque = false; if (make_active(p_tcb)) { dispatch(); } } ercd = E_OK; } t_unlock_cpu(); error_exit: LOG_TER_TSK_LEAVE(ercd); return(ercd); }
ER imact_tsk(ID tskid, ID prcid) { TCB *p_tcb; ER ercd; PCB *t_p_pcb; PCB *f_p_pcb; LOG_IMACT_TSK_ENTER(tskid, prcid); CHECK_INTCTX_UNL(); CHECK_TSKID(tskid); CHECK_PRCID_INI(prcid); p_tcb = get_tcb(tskid); prcid = (prcid == TPRC_INI)? p_tcb->p_tinib->iaffinity : prcid; CHECK_MIG(p_tcb->p_tinib->affinity_mask, prcid); i_lock_cpu(); /* 現在割り付けられているプロセッサと移動先のプロセッサのタスクロックを取得 */ i_acquire_dual_tsk_lock(p_tcb, prcid, &f_p_pcb, &t_p_pcb); if (TSTAT_DORMANT(p_tcb->tstat)) { LOG_TSKMIG(p_tcb, f_p_pcb->prcid, prcid); p_tcb->p_pcb = t_p_pcb; if (make_active(p_tcb)) { if (dispatch_request(t_p_pcb)) { t_p_pcb->reqflg = true; } } ercd = E_OK; } else if (!(p_tcb->actque)) { p_tcb->actque = true; p_tcb->actprc = prcid; ercd = E_OK; } else { ercd = E_QOVR; } release_dual_tsk_lock(f_p_pcb, t_p_pcb); i_unlock_cpu(); error_exit: LOG_IMACT_TSK_LEAVE(ercd); return(ercd); }
/* * Suspend task */ SYSCALL ER _tk_sus_tsk( ID tskid ) { TCB *tcb; TSTAT state; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_NONSELF(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; state = (TSTAT)tcb->state; if ( !task_alive(state) ) { ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; goto error_exit; } if ( tcb == ctxtsk && dispatch_disabled >= DDS_DISABLE ) { ercd = E_CTX; goto error_exit; } if ( tcb->suscnt == INT_MAX ) { ercd = E_QOVR; goto error_exit; } /* Update suspend request count */ ++tcb->suscnt; /* Move to forced wait state */ if ( state == TS_READY ) { make_non_ready(tcb); tcb->state = TS_SUSPEND; } else if ( state == TS_WAIT ) { tcb->state = TS_WAITSUS; } error_exit: END_CRITICAL_SECTION; return ercd; }
ER del_tsk(ID tskid) { TCB *p_tcb; TINIB *p_tinib; ER ercd; LOG_DEL_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); t_lock_cpu(); if (p_tcb->p_tinib->tskatr == TA_NOEXS) { ercd = E_NOEXS; } else if (VIOLATE_ACPTN(p_tcb->p_tinib->acvct.acptn3)) { ercd = E_OACV; } else if (TSKID(p_tcb) > tmax_stskid && TSTAT_DORMANT(p_tcb->tstat)) { p_tinib = (TINIB *)(p_tcb->p_tinib); #ifdef USE_TSKINICTXB term_tskinictxb(&(p_tinib->tskinictxb)); #else /* USE_TSKINICTXB */ if ((p_tinib->tskatr & TA_MEMALLOC) != 0U) { kernel_free(p_tinib->sstk); } #endif /* USE_TSKINICTXB */ p_tinib->tskatr = TA_NOEXS; queue_insert_prev(&free_tcb, &(p_tcb->task_queue)); ercd = E_OK; } else { ercd = E_OBJ; } t_unlock_cpu(); error_exit: LOG_DEL_TSK_LEAVE(ercd); return(ercd); }
/* * Resume task */ SYSCALL ER _tk_rsm_tsk( ID tskid ) { TCB *tcb; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_NONSELF(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; switch ( tcb->state ) { case TS_NONEXIST: ercd = E_NOEXS; break; case TS_DORMANT: case TS_READY: case TS_WAIT: ercd = E_OBJ; break; case TS_SUSPEND: if ( --tcb->suscnt == 0 ) { make_ready(tcb); } break; case TS_WAITSUS: if ( --tcb->suscnt == 0 ) { tcb->state = TS_WAIT; } break; default: ercd = E_SYS; break; } END_CRITICAL_SECTION; return ercd; }
/* * Get task register contents */ SYSCALL ER tk_get_reg_impl( ID tskid, T_REGS *pk_regs, T_EIT *pk_eit, T_CREGS *pk_cregs ) { TCB *tcb; ER ercd = E_OK; CHECK_INTSK(); CHECK_TSKID(tskid); CHECK_NONSELF(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; } else { knl_get_reg(tcb, pk_regs, pk_eit, pk_cregs); } END_CRITICAL_SECTION; return ercd; }
/* * Release wait */ SYSCALL ER _tk_rel_wai( ID tskid ) { TCB *tcb; TSTAT state; ER ercd = E_OK; CHECK_TSKID(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; state = (TSTAT)tcb->state; if ( (state & TS_WAIT) == 0 ) { ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; } else { wait_release_ng(tcb, E_RLWAI); } END_CRITICAL_SECTION; return ercd; }
/* * Get task register */ SYSCALL ER td_get_reg_impl( ID tskid, T_REGS *regs, T_EIT *eit, T_CREGS *cregs ) { TCB *tcb; ER ercd = E_OK; CHECK_TSKID(tskid); tcb = get_tcb(tskid); if ( tcb == knl_ctxtsk ) { return E_OBJ; } BEGIN_DISABLE_INTERRUPT; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; } else { knl_get_reg(tcb, regs, eit, cregs); } END_DISABLE_INTERRUPT; return ercd; }
/* * Delete task */ SYSCALL ER _tk_del_tsk( ID tskid ) { TCB *tcb; TSTAT state; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_NONSELF(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; state = (TSTAT)tcb->state; if ( state != TS_DORMANT ) { ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; } else { _del_tsk(tcb); } END_CRITICAL_SECTION; return ercd; }
SYSCALL ER rsm_tsk(ID tskid) { TCB *tcb; UINT tstat; ER ercd; LOG_RSM_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID(tskid); tcb = get_tcb(tskid); t_lock_cpu(); if (!(TSTAT_SUSPENDED(tstat = tcb->tstat))) { ercd = E_OBJ; } else if (!(TSTAT_WAITING(tstat))) { /* * 強制待ち状態から実行できる状態への遷移 */ if (make_runnable(tcb)) { dispatch(); } ercd = E_OK; } else { /* * 二重待ち状態から待ち状態への遷移 */ tcb->tstat &= ~TS_SUSPENDED; LOG_TSKSTAT(tcb); ercd = E_OK; } t_unlock_cpu(); exit: LOG_RSM_TSK_LEAVE(ercd); return(ercd); }
SYSCALL ER ter_tsk(ID tskid) { TCB *tcb; UINT tstat; ER ercd; LOG_TER_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID(tskid); tcb = get_tcb(tskid); CHECK_NONSELF(tcb); t_lock_cpu(); if (TSTAT_DORMANT(tstat = tcb->tstat)) { ercd = E_OBJ; } else { if (TSTAT_RUNNABLE(tstat)) { make_non_runnable(tcb); } else if (TSTAT_WAITING(tstat)) { wait_cancel(tcb); } make_dormant(tcb); if (tcb->actcnt) { tcb->actcnt = FALSE; if (make_active(tcb)) { dispatch(); } } ercd = E_OK; } t_unlock_cpu(); exit: LOG_TER_TSK_LEAVE(ercd); return(ercd); }
/* * Get task coprocessor register */ SYSCALL ER _tk_get_cpr( ID tskid, INT copno, T_COPREGS *pk_copregs ) { ATR copatr = TA_COP0 << copno; TCB *tcb; ER ercd = E_OK; CHECK_INTSK(); CHECK_TSKID(tskid); CHECK_NONSELF(tskid); CHECK_PAR((copatr & available_cop) != 0); tcb = get_tcb(tskid); BEGIN_CRITICAL_NO_DISPATCH; /* Because the state of the task doesn't change. */ if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; } else { ercd = mp_check_domain_and_protection(tskid, tcb->tskid, tcb->tskatr); if ( ercd == E_OK ) { if ( (tcb->tskatr & copatr) == 0 ) { ercd = E_PAR; } else if ( is_ctxtsk(tcb) ) { ercd = E_OBJ; } else { #if USE_SH3_DSP /* Get DSP register */ memcpy(pk_copregs, tcb->isstack, sizeof(T_COP0REGS)); #endif #if TA_FPU /* Get FPU register */ memcpy(pk_copregs, tcb->isstack, sizeof(T_COP0REGS)); #endif } } } END_CRITICAL_NO_DISPATCH; return ercd; }
SYSCALL ER i_vsnd_tmb(ID tskid,T_MSG *pk_msg) { TCB *tcb; TSTAT state; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_TSKACV(tskid); CHECK_NONSELF(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; if ( !task_alive(state = tcb->state) ) { ercd = (state == TS_NONEXIST) ? E_NOEXS : E_OBJ; } else if ((state & TS_WAIT) && tcb->wspec == &wspec_tmb_tfifo) { *(tcb->winfo.tmb.ppk_msg) = pk_msg; wait_release_ok(tcb); } else { nextmsg(pk_msg) = (T_MSG *) 0; if (tcb->tmq_head) { nextmsg(tcb->tmq_tail) = pk_msg; } else { tcb->tmq_head = pk_msg; } tcb->tmq_tail = pk_msg; } END_CRITICAL_SECTION; return(ercd); }
/* * Start task */ SYSCALL ER tk_sta_tsk_impl( ID tskid, INT stacd ) { TCB *tcb; TSTAT state; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_NONSELF(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; state = (TSTAT)tcb->state; if ( state != TS_DORMANT ) { ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; } else { knl_setup_stacd(tcb, stacd); knl_make_ready(tcb); } END_CRITICAL_SECTION; return ercd; }
/* * タスク状態の参照 */ StatusType GetTaskState(TaskType tskid, TaskStateRefType p_state) { StatusType ercd = E_OK; LOG_GETTST_ENTER(tskid, p_state); CHECK_CALLEVEL(TCL_TASK | TCL_ISR2 | TCL_ERROR | TCL_PREPOST); CHECK_TSKID(tskid); lock_cpu(); *p_state = (tskid == runtsk) ? RUNNING : tcb_tstat[tskid]; exit: unlock_cpu(); LOG_GETTST_LEAVE(ercd, *p_state); return(ercd); error_exit: lock_cpu(); _errorhook_par1.tskid = tskid; _errorhook_par2.p_state = p_state; call_errorhook(ercd, OSServiceId_GetTaskState); goto exit; }
ER iwup_tsk(ID tskid) { TCB *p_tcb; ER ercd; LOG_IWUP_TSK_ENTER(tskid); CHECK_INTCTX_UNL(); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); i_lock_cpu(); if (p_tcb->p_tinib->tskatr == TA_NOEXS) { ercd = E_NOEXS; } else if (TSTAT_DORMANT(p_tcb->tstat)) { ercd = E_OBJ; } else if (TSTAT_WAIT_SLP(p_tcb->tstat)) { if (wait_complete(p_tcb)) { reqflg = true; } ercd = E_OK; } else if (!(p_tcb->wupque)) { p_tcb->wupque = true; ercd = E_OK; } else { ercd = E_QOVR; } i_unlock_cpu(); error_exit: LOG_IWUP_TSK_LEAVE(ercd); return(ercd); }
/* * Get task register */ SYSCALL ER _td_get_reg( ID tskid, T_REGS *regs, T_EIT *eit, T_CREGS *cregs ) { TCB *tcb; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_NONSELF(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; } else if ( !MP_CMP_DOMIDPART(tskid, tcb->tskid) ) { ercd = E_NOEXS; } else if ( is_ctxtsk(tcb) ) { ercd = E_OBJ; } else { get_reg(tcb, regs, eit, cregs); } END_CRITICAL_NO_DISPATCH; return ercd; }
ER iact_tsk(ID tskid) { TCB *p_tcb; ER ercd; PCB *p_pcb; LOG_IACT_TSK_ENTER(tskid); CHECK_INTCTX_UNL(); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); i_lock_cpu(); p_pcb = i_acquire_tsk_lock(p_tcb); if (TSTAT_DORMANT(p_tcb->tstat)) { if (make_active(p_tcb)) { if (dispatch_request(p_pcb)) { p_pcb->reqflg = true; } } ercd = E_OK; } else if (!(p_tcb->actque)) { p_tcb->actque = true; ercd = E_OK; } else { ercd = E_QOVR; } release_tsk_lock(p_pcb); i_unlock_cpu(); error_exit: LOG_IACT_TSK_LEAVE(ercd); return(ercd); }
ER ter_tsk(ID tskid) { TCB *p_tcb; ER ercd = E_OK; bool_t dspreq = false; PCB *f_p_pcb; PCB *t_p_pcb; PCB *my_p_pcb; PCB *p_pcb; LOG_TER_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); t_lock_cpu(); retry: p_pcb = t_acquire_tsk_lock(p_tcb); my_p_pcb = get_my_p_pcb(); /* 自タスクを指定するとエラー */ if ((p_tcb) == my_p_pcb->p_runtsk) { ercd = E_ILUSE; release_tsk_lock(p_pcb); } /* 異なるプロセッサに割り付けられているタスクならエラーとする */ else if (p_pcb != my_p_pcb) { ercd = E_OBJ; release_tsk_lock(p_pcb); } else if (TSTAT_DORMANT(p_tcb->tstat)) { ercd = E_OBJ; release_tsk_lock(p_pcb); } else { if (!(TSTAT_WAITING(p_tcb->tstat) && TSTAT_WAIT_WOBJ(p_tcb->tstat))) { /* オブジェクト待ち以外の状態の場合 */ if ((p_tcb->actprc == TPRC_NONE) || (p_tcb->actprc == p_pcb->prcid)) { /* 再起動時のマイグレーションなし */ if (TSTAT_RUNNABLE(p_tcb->tstat)) { /* * 対象タスクが他プロセッサ上のタスクかつRUNNABLEの場合, * RUN状態の可能性があるため,ディスパッチ要求を出す必要があるが, * 本システムコールは同じプロセッサに割り付けられているタスクのみ * に発行可能であるので,ディスパッチ要求を出す必要はない. */ (void)make_non_runnable(p_tcb); } else if (TSTAT_WAITING(p_tcb->tstat)) { /* オブジェクト待ち以外の待ち状態の場合 */ wait_dequeue_tmevtb(p_tcb); } make_dormant(p_tcb); if (p_tcb->actque) { p_tcb->actque = false; p_tcb->actprc = TPRC_NONE; if (make_active(p_tcb)) { dspreq = dispatch_request(p_pcb); } } release_tsk_lock(p_pcb); if (dspreq) { dispatch(); } } else { /* 起動要求キューイングあり & 他プロセッサにマイグレーションあり */ /* 移動先のプロセッサのPCBを取得 */ t_p_pcb = get_mp_p_pcb(p_tcb->actprc); /* 一旦タスクロックを離す */ release_tsk_lock(p_pcb); /* * 現在割り付けられているプロセッサと移動先のプロセッサのタスク * ロックを取得 */ t_acquire_dual_tsk_lock(p_tcb, p_tcb->actprc, &p_pcb, &t_p_pcb); /* * マイグレーション先のプロセッサが変更された場合はリトライ * 対象タスクと自タスクが所属するプロセッサが異なる場合も * リトライする. */ if ((p_tcb->actprc != t_p_pcb->prcid) || (p_pcb != my_p_pcb)) { release_dual_tsk_lock(p_pcb, t_p_pcb); goto retry; } if (TSTAT_RUNNABLE(p_tcb->tstat)) { /* * 対象タスクが他プロセッサ上のタスクかつRUNNABLEの場合, * RUN状態の可能性があるため,ディスパッチ要求を出す必要があるが, * 本システムコールは同じプロセッサに割り付けられているタスクのみ * に発行可能であるので,ディスパッチ要求を出す必要はない. */ (void)make_non_runnable(p_tcb); } else if (TSTAT_WAITING(p_tcb->tstat)) { /* オブジェクト待ち以外の待ち状態の場合 */ wait_dequeue_tmevtb(p_tcb); } make_dormant(p_tcb); p_tcb->actque = false; p_tcb->actprc = TPRC_NONE; f_p_pcb = p_pcb; p_tcb->p_pcb = t_p_pcb; if (make_active(p_tcb)) { /* * 現在所属するプロセッサと同じプロセッサにマイグレー * ションする場合はここに来ないため,dispatch_request() * 戻り値はチェックしない. */ (void)dispatch_request(t_p_pcb); } release_dual_tsk_lock(f_p_pcb, t_p_pcb); } } else { /* オブジェクト待ち状態の場合 */ if ((p_tcb->actprc == TPRC_NONE) || (p_tcb->actprc == p_pcb->prcid)) { /* 再起動時のマイグレーションなし */ /* * デッドロック回避のため,ロックを取得し直す */ WOBJCB *p_wobjcb = p_tcb->p_wobjcb; release_tsk_lock(p_pcb); /* * あらためて * オブジェクトロック -> タスクロック * の順でロックを取得 */ TEST_G_LABEL("_test_ter_tsk_01"); t_acquire_obj_lock(&GET_OBJLOCK(p_wobjcb)); if ((p_pcb = t_acquire_nested_tsk_lock(p_tcb, &GET_OBJLOCK(p_wobjcb))) == NULL){ goto retry; } /* * オブジェクト待ち状態以外ないし,異なるオブジェクトに対する待ち * になっていないかチェック. */ if ((TSTAT_WAITING(p_tcb->tstat) && !TSTAT_WAIT_WOBJ(p_tcb->tstat)) || p_wobjcb != p_tcb->p_wobjcb) { release_nested_tsk_lock(p_pcb); release_obj_lock(&GET_OBJLOCK(p_wobjcb)); goto retry; } wait_dequeue_wobj(p_tcb); wait_dequeue_tmevtb(p_tcb); release_obj_lock(&GET_OBJLOCK(p_wobjcb)); make_dormant(p_tcb); if (p_tcb->actque) { p_tcb->actque = false; p_tcb->actprc = TPRC_NONE; if (make_active(p_tcb)) { dspreq = dispatch_request(p_pcb); } } release_tsk_lock(p_pcb); if (dspreq) { dispatch(); } } else { /* 起動要求キューイングあり & 他プロセッサへのマイグレーション */ /* 移動先のプロセッサのPCBを取得 */ t_p_pcb = get_mp_p_pcb(p_tcb->actprc); /* * デッドロック回避のため,ロックを取得し直す */ WOBJCB *p_wobjcb = p_tcb->p_wobjcb; release_tsk_lock(p_pcb); /* * あらためて * オブジェクトロック -> タスクロック * の順でロックを取得 */ TEST_G_LABEL("_test_ter_tsk_02"); t_acquire_obj_lock(&GET_OBJLOCK(p_wobjcb)); if (t_acquire_nested_dual_tsk_lock(p_tcb, p_tcb->actprc, &GET_OBJLOCK(p_wobjcb), &p_pcb, &t_p_pcb)) { goto retry; } /* * 異なるオブジェクトに対する待ちないし,オブジェクト待ち状態以外に * になっていない,異なるプロセッサへのマイグレーション,対象タスク * がマイグレートしているならリトライ. */ if ((p_wobjcb != p_tcb->p_wobjcb) || (TSTAT_WAITING(p_tcb->tstat) && !TSTAT_WAIT_WOBJ(p_tcb->tstat)) || (get_mp_p_pcb(p_tcb->actprc) != t_p_pcb) || (p_pcb != my_p_pcb)) { release_dual_tsk_lock(p_pcb, t_p_pcb); release_obj_lock(&GET_OBJLOCK(p_wobjcb)); goto retry; } wait_dequeue_wobj(p_tcb); wait_dequeue_tmevtb(p_tcb); release_obj_lock(&GET_OBJLOCK(p_wobjcb)); make_dormant(p_tcb); p_tcb->actque = false; p_tcb->actprc = TPRC_NONE; f_p_pcb = p_pcb; p_tcb->p_pcb = t_p_pcb; if (make_active(p_tcb)) { /* * 現在所属するプロセッサと同じプロセッサにマイグレー * ションする場合はここに来ないため,dispatch_request() * 戻り値はチェックしない. */ (void)dispatch_request(t_p_pcb); } release_dual_tsk_lock(f_p_pcb, t_p_pcb); } } } t_unlock_cpu(); error_exit: LOG_TER_TSK_LEAVE(ercd); return(ercd); }
ER ter_tsk(ID tskid) { TCB *p_tcb; ER ercd; bool_t dspreq = false; PCB *p_pcb; PCB *my_p_pcb; LOG_TER_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); t_lock_cpu(); p_pcb = t_acquire_tsk_lock(p_tcb); my_p_pcb = get_my_p_pcb(); /* 自タスクを指定するとエラー */ if ((p_tcb) == my_p_pcb->p_runtsk) { ercd = E_ILUSE; } /* 異なるプロセッサに割り付けられているタスクならエラーとする */ else if (p_pcb != my_p_pcb) { ercd = E_OBJ; } else if (TSTAT_DORMANT(p_tcb->tstat)) { ercd = E_OBJ; } else { if (TSTAT_RUNNABLE(p_tcb->tstat)) { /* * 対象タスクが他プロセッサ上のタスクかつRUNNABLEの場合, * RUN状態の可能性があるため,ディスパッチ要求を出す必要があるが, * 本システムコールは同じプロセッサに割り付けられているタスクのみ * に発行可能であるので,ディスパッチ要求を出す必要はない. */ (void)make_non_runnable(p_tcb); } else if (TSTAT_WAITING(p_tcb->tstat)) { wait_dequeue_wobj(p_tcb); wait_dequeue_tmevtb(p_tcb); } make_dormant(p_tcb); if (p_tcb->actque) { p_tcb->actque = false; /* * マイグレーション要求がキューイングしている場合は, * マイグレーション処理を行う. */ if ((p_tcb->actprc != TPRC_NONE) && (p_tcb->actprc != my_p_pcb->prcid)) { p_tcb->p_pcb = get_mp_p_pcb(p_tcb->actprc); } p_tcb->actprc = TPRC_NONE; if (make_active(p_tcb)) { dspreq = dispatch_request(p_tcb->p_pcb); } } ercd = E_OK; } release_tsk_lock(p_pcb); if (dspreq) { dispatch(); } t_unlock_cpu(); error_exit: LOG_TER_TSK_LEAVE(ercd); return(ercd); }