/* |------------------+--------------------------------------------------------------| */ StatusType GetEvent ( TaskType xTaskID , EventMaskRefType pxEvent ) { StatusType ercd = E_OK; TCB* tcb=get_tcb(xTaskID); ID flgid=(ID)(tcb->exinf); FLGCB *flgcb; if((xTaskID >= cfgOSEK_TASK_NUM+MIN_TSKID) || (xTaskID < MIN_TSKID)) { ercd = E_OS_ID; goto Error_Exit; } if(flgid == (ID)NULL) { ercd = E_OS_ACCESS; goto Error_Exit; } flgcb = get_flgcb(flgid); *pxEvent = flgcb->flgptn; Error_Exit: 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; }
/* * Delete task */ SYSCALL ER tk_del_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 ( state != TS_DORMANT ) { ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; } else { knl_del_tsk(tcb); } END_CRITICAL_SECTION; return ercd; }
/* * Set task register contents */ SYSCALL ER tk_set_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_set_reg(tcb, pk_regs, pk_eit, pk_cregs); } 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; }
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(); p_tcb->leftotm = ovrtim; ercd = E_OK; i_unlock_cpu(); error_exit: LOG_ISTA_OVR_LEAVE(ercd); 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); }
ER del_tsk(ID tskid) { TCB *p_tcb; TINIB *p_tinib; ER ercd; LOG_DEL_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); /*[NGKI1101][NGKI1102]*/ CHECK_ID(VALID_TSKID(tskid)); /*[NGKI1103]*/ p_tcb = get_tcb(tskid); lock_cpu(); if (p_tcb->p_tinib->tskatr == TA_NOEXS) { ercd = E_NOEXS; /*[NGKI1104]*/ } else if (tskid <= tmax_stskid || !TSTAT_DORMANT(p_tcb->tstat)) { ercd = E_OBJ; /*[NGKI1106][NGKI1107]*/ } else { 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) { /*[NGKI1109]*/ kernel_free(p_tinib->stk); } #endif /* USE_TSKINICTXB */ p_tinib->tskatr = TA_NOEXS; /*[NGKI1108]*/ queue_insert_prev(&free_tcb, &(p_tcb->task_queue)); ercd = E_OK; } unlock_cpu(); error_exit: LOG_DEL_TSK_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 (!TSTAT_SUSPENDED(p_tcb->tstat)) { ercd = E_OBJ; } else if (!TSTAT_WAITING(p_tcb->tstat)) { /* * 強制待ち状態から実行できる状態への遷移 */ 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); }
/* * Start task */ SYSCALL ER _tk_sta_tsk( 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 { setup_stacd(tcb, stacd); make_ready(tcb); } END_CRITICAL_SECTION; return ercd; }
ER rel_wai(ID tskid) { TCB *p_tcb; ER ercd; LOG_REL_WAI_ENTER(tskid); CHECK_UNL(); CHECK_ID(VALID_TSKID(tskid)); p_tcb = get_tcb(tskid); CHECK_NOSPT((p_tcb->p_tinib->tskatr & TA_RSTR) == 0U); /*[NGKI1291]*/ lock_cpu(); if (!TSTAT_WAITING(p_tcb->tstat)) { ercd = E_OBJ; } else { wait_dequeue_wobj(p_tcb); wait_dequeue_tmevtb(p_tcb); p_tcb->p_winfo->wercd = E_RLWAI; make_non_wait(p_tcb); if (p_runtsk != p_schedtsk) { if (!sense_context()) { dispatch(); } else { request_dispatch(); } } ercd = E_OK; } unlock_cpu(); error_exit: LOG_REL_WAI_LEAVE(ercd); return(ercd); }
/* * Reply rendezvous */ SYSCALL ER tk_rpl_rdv_impl( RNO rdvno, VP msg, INT rmsgsz ) { TCB *caltcb; ER ercd = E_OK; CHECK_RDVNO(rdvno); CHECK_PAR(rmsgsz >= 0); CHECK_INTSK(); caltcb = get_tcb(knl_get_tskid_rdvno(rdvno)); BEGIN_CRITICAL_SECTION; if ( (caltcb->state & TS_WAIT) == 0 || caltcb->wspec != &knl_wspec_rdv || rdvno != caltcb->winfo.rdv.rdvno ) { ercd = E_OBJ; goto error_exit; } #if CHK_PAR if ( rmsgsz > caltcb->winfo.rdv.maxrmsz ) { ercd = E_PAR; goto error_exit; } #endif /* Send message */ if ( rmsgsz > 0 ) { memcpy(caltcb->winfo.rdv.msg, msg, (UINT)rmsgsz); } *caltcb->winfo.rdv.p_rmsgsz = rmsgsz; knl_wait_release_ok(caltcb); error_exit: END_CRITICAL_SECTION; return ercd; }
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); }
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); }
/* * 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; }
/* * Forward Rendezvous to Other Port */ SYSCALL ER tk_fwd_por_impl( ID porid, UINT calptn, RNO rdvno, VP msg, INT cmsgsz ) { PORCB *porcb; TCB *caltcb, *tcb; QUEUE *queue; RNO new_rdvno; ER ercd = E_OK; CHECK_PORID(porid); CHECK_PAR(calptn != 0); CHECK_RDVNO(rdvno); CHECK_PAR(cmsgsz >= 0); CHECK_INTSK(); porcb = get_porcb(porid); caltcb = get_tcb(knl_get_tskid_rdvno(rdvno)); BEGIN_CRITICAL_SECTION; if ( porcb->porid == 0 ) { ercd = E_NOEXS; goto error_exit; } #if CHK_PAR if ( cmsgsz > porcb->maxcmsz ) { ercd = E_PAR; goto error_exit; } #endif if ( (caltcb->state & TS_WAIT) == 0 || caltcb->wspec != &knl_wspec_rdv || rdvno != caltcb->winfo.rdv.rdvno ) { ercd = E_OBJ; goto error_exit; } if ( porcb->maxrmsz > caltcb->winfo.rdv.maxrmsz ) { ercd = E_OBJ; goto error_exit; } #if CHK_PAR if ( cmsgsz > caltcb->winfo.rdv.maxrmsz ) { ercd = E_PAR; goto error_exit; } #endif /* Search accept wait task */ queue = porcb->accept_queue.next; while ( queue != &porcb->accept_queue ) { tcb = (TCB*)queue; queue = queue->next; if ( (calptn & tcb->winfo.acp.acpptn) == 0 ) { continue; } /* Send message */ new_rdvno = knl_gen_rdvno(caltcb); if ( cmsgsz > 0 ) { memcpy(tcb->winfo.acp.msg, msg, (UINT)cmsgsz); } *tcb->winfo.acp.p_rdvno = new_rdvno; *tcb->winfo.acp.p_cmsgsz = cmsgsz; knl_wait_release_ok(tcb); /* Change rendezvous end wait of the other task */ caltcb->winfo.rdv.rdvno = new_rdvno; caltcb->winfo.rdv.msg = caltcb->winfo.cal.msg; caltcb->winfo.rdv.maxrmsz = porcb->maxrmsz; caltcb->winfo.rdv.p_rmsgsz = caltcb->winfo.cal.p_rmsgsz; goto error_exit; } /* Change the other task to rendezvous call wait */ caltcb->wspec = ( (porcb->poratr & TA_TPRI) != 0 )? &knl_wspec_cal_tpri: &knl_wspec_cal_tfifo; caltcb->wid = porid; caltcb->winfo.cal.calptn = calptn; caltcb->winfo.cal.msg = caltcb->winfo.rdv.msg; caltcb->winfo.cal.cmsgsz = cmsgsz; caltcb->winfo.cal.p_rmsgsz = caltcb->winfo.rdv.p_rmsgsz; knl_timer_insert(&caltcb->wtmeb, TMO_FEVR, (CBACK)knl_wait_release_tmout, caltcb); if ( (porcb->poratr & TA_TPRI) != 0 ) { knl_queue_insert_tpri(caltcb, &porcb->call_queue); } else { QueInsert(&caltcb->tskque, &porcb->call_queue); } if ( cmsgsz > 0 ) { memcpy(caltcb->winfo.cal.msg, msg, (UINT)cmsgsz); } error_exit: END_CRITICAL_SECTION; return ercd; }
/* * タスク毎の検査 */ static ER bit_mutex_task(ID tskid) { TCB *p_tcb; MTXCB *p_mtxcb; QUEUE *p_queue, *p_next; uint_t pri; if (!(TMIN_TSKID <= (tskid) && (tskid) <= tmax_tskid)) { return(E_ID); } p_tcb = get_tcb(tskid); pri = p_tcb->bpriority; /* * タスクがロックしているミューテックスのキューの検査 */ p_queue = p_tcb->mutex_queue.p_next; if (p_queue->p_prev != &(p_tcb->mutex_queue)) { return(E_SYS_LINENO); } while (p_queue != &(p_tcb->mutex_queue)) { p_mtxcb = MTXCB_QUEUE(p_queue); if (!VALID_MTXCB(p_mtxcb)) { return(E_SYS_LINENO); } /* * ミューテックスをロックしているタスクのチェック */ if (p_mtxcb->p_loctsk != p_tcb) { return(E_SYS_LINENO); } /* * 現在優先度の計算 */ if (MTXPROTO(p_mtxcb)) { if (p_mtxcb->p_mtxinib->ceilpri < pri) { pri = p_mtxcb->p_mtxinib->ceilpri; } } /* * キューの次の要素に進む */ p_next = p_queue->p_next; if (p_next->p_prev != p_queue) { return(E_SYS_LINENO); } p_queue = p_next; } /* * 現在優先度の検査 */ if (p_tcb->priority != pri) { return(E_SYS_LINENO); } /* * タスクが待っているミューテックスに関する検査 */ if (TSTAT_WAIT_MTX(p_tcb->tstat)) { p_mtxcb = ((WINFO_MTX *)(p_tcb->p_winfo))->p_mtxcb; if (!VALID_MTXCB(p_mtxcb)) { return(E_SYS_LINENO); } if (!in_queue(&(p_mtxcb->wait_queue), &(p_tcb->task_queue))) { return(E_SYS_LINENO); } } return(E_OK); }
ER ref_tsk(ID tskid, T_RTSK *pk_rtsk) { TCB *p_tcb; uint_t tstat; ER ercd; LOG_REF_TSK_ENTER(tskid, pk_rtsk); CHECK_TSKCTX_UNL(); if (tskid == TSK_SELF) { p_tcb = p_runtsk; } else { CHECK_ID(VALID_TSKID(tskid)); p_tcb = get_tcb(tskid); } lock_cpu(); tstat = p_tcb->tstat; if (TSTAT_DORMANT(tstat)) { /* * 対象タスクが休止状態の場合 */ pk_rtsk->tskstat = TTS_DMT; } else { /* * タスク状態の取出し */ if (TSTAT_SUSPENDED(tstat)) { if (TSTAT_WAITING(tstat)) { pk_rtsk->tskstat = TTS_WAS; } else { pk_rtsk->tskstat = TTS_SUS; } } else if (TSTAT_WAITING(tstat)) { pk_rtsk->tskstat = TTS_WAI; } else if (p_tcb == p_runtsk) { pk_rtsk->tskstat = TTS_RUN; } else { pk_rtsk->tskstat = TTS_RDY; } /* * 現在優先度とベース優先度の取出し */ pk_rtsk->tskpri = EXT_TSKPRI(p_tcb->priority); pk_rtsk->tskbpri = EXT_TSKPRI(p_tcb->bpriority); if (TSTAT_WAITING(tstat)) { /* * 待ち要因と待ち対象のオブジェクトのIDの取出し */ switch (tstat) { case TS_WAITING_SLP: pk_rtsk->tskwait = TTW_SLP; break; case TS_WAITING_DLY: pk_rtsk->tskwait = TTW_DLY; break; case TS_WAITING_SEM: pk_rtsk->tskwait = TTW_SEM; pk_rtsk->wobjid = SEMID(((WINFO_SEM *)(p_tcb->p_winfo)) ->p_semcb); break; case TS_WAITING_FLG: pk_rtsk->tskwait = TTW_FLG; pk_rtsk->wobjid = FLGID(((WINFO_FLG *)(p_tcb->p_winfo)) ->p_flgcb); break; case TS_WAITING_SDTQ: pk_rtsk->tskwait = TTW_SDTQ; pk_rtsk->wobjid = DTQID(((WINFO_SDTQ *)(p_tcb->p_winfo)) ->p_dtqcb); break; case TS_WAITING_RDTQ: pk_rtsk->tskwait = TTW_RDTQ; pk_rtsk->wobjid = DTQID(((WINFO_RDTQ *)(p_tcb->p_winfo)) ->p_dtqcb); break; case TS_WAITING_SPDQ: pk_rtsk->tskwait = TTW_SPDQ; pk_rtsk->wobjid = PDQID(((WINFO_SPDQ *)(p_tcb->p_winfo)) ->p_pdqcb); break; case TS_WAITING_RPDQ: pk_rtsk->tskwait = TTW_RPDQ; pk_rtsk->wobjid = PDQID(((WINFO_RPDQ *)(p_tcb->p_winfo)) ->p_pdqcb); break; case TS_WAITING_MTX: pk_rtsk->tskwait = TTW_MTX; pk_rtsk->wobjid = MTXID(((WINFO_MTX *)(p_tcb->p_winfo)) ->p_mtxcb); break; case TS_WAITING_MPF: pk_rtsk->tskwait = TTW_MPF; pk_rtsk->wobjid = MPFID(((WINFO_MPF *)(p_tcb->p_winfo)) ->p_mpfcb); break; } /* * タイムアウトするまでの時間の取出し */ if (p_tcb->p_winfo->p_tmevtb != NULL) { pk_rtsk->lefttmo = (TMO) tmevt_lefttim(p_tcb->p_winfo->p_tmevtb); } else { pk_rtsk->lefttmo = TMO_FEVR; } } /* * 起床要求キューイング数の取出し */ pk_rtsk->wupcnt = p_tcb->wupque ? 1U : 0U; /* * タスク終了要求状態の取出し */ pk_rtsk->raster = p_tcb->raster; /* * タスク終了禁止状態の取出し */ pk_rtsk->dister = !(p_tcb->enater); } /* * 起動要求キューイング数の取出し */ pk_rtsk->actcnt = p_tcb->actque ? 1U : 0U; ercd = E_OK; unlock_cpu(); error_exit: LOG_REF_TSK_LEAVE(ercd, pk_rtsk); return(ercd); }
unsigned long kapi_process_id() { struct thread_control_block *tcb = get_tcb(); return tcb->proc_id; }
/* * タスク毎の整合性検査 */ static ER bit_task(ID tskid) { TCB *p_tcb; const TINIB *p_tinib; uint_t tstat, tstat_wait, pri; TMEVTB *p_tmevtb; SEMCB *p_semcb; FLGCB *p_flgcb; DTQCB *p_dtqcb; PDQCB *p_pdqcb; MTXCB *p_mtxcb; MPFCB *p_mpfcb; if (!(TMIN_TSKID <= (tskid) && (tskid) <= tmax_tskid)) { return(E_ID); } p_tcb = get_tcb(tskid); p_tinib = p_tcb->p_tinib; tstat = p_tcb->tstat; tstat_wait = (tstat & TS_WAIT_MASK); pri = p_tcb->priority; /* * 初期化ブロックへのポインタの検査 */ if (p_tinib != &(tinib_table[INDEX_TSK(tskid)])) { return(E_SYS_LINENO); } /* * tstatの検査 */ switch (tstat & (TS_RUNNABLE | TS_WAITING | TS_SUSPENDED)) { case TS_DORMANT: if (tstat != TS_DORMANT) { return(E_SYS_LINENO); } break; case TS_RUNNABLE: if (tstat != TS_RUNNABLE) { return(E_SYS_LINENO); } break; case TS_WAITING: case (TS_WAITING | TS_SUSPENDED): if (!(TS_WAIT_DLY <= tstat_wait && tstat_wait <= TS_WAIT_MTX) || tstat_wait == TS_WAIT_MBX) { return(E_SYS_LINENO); } if ((tstat & ~(TS_WAIT_MASK | TS_RUNNABLE | TS_WAITING | TS_SUSPENDED)) != 0U) { return(E_SYS_LINENO); } break; case TS_SUSPENDED: if (tstat != TS_SUSPENDED) { return(E_SYS_LINENO); } break; default: return(E_SYS_LINENO); } /* * actqueの検査 */ if (TSTAT_DORMANT(tstat) && p_tcb->actque) { return(E_SYS_LINENO); } /* * タスク優先度の検査 */ if (pri >= TNUM_TPRI) { return(E_SYS_LINENO); } /* * texptnの検査 */ if (p_tcb->p_tinib->texrtn == NULL && p_tcb->texptn != 0U) { return(E_SYS_LINENO); } /* * 休止状態におけるチェック */ if (TSTAT_DORMANT(tstat)) { if (!(pri == p_tinib->ipriority) && (p_tcb->wupque == false) && (p_tcb->enatex == false) && (p_tcb->texptn == 0U)) { return(E_SYS_LINENO); } } /* * 実行できる状態におけるチェック */ if (TSTAT_RUNNABLE(tstat)) { if (!in_queue(&ready_queue[pri], &(p_tcb->task_queue))) { return(E_SYS_LINENO); } } /* * 待ち状態におけるチェック */ if (TSTAT_WAITING(tstat)) { if (!on_stack(p_tcb->p_winfo, p_tinib)) { return(E_SYS_LINENO); } p_tmevtb = p_tcb->p_winfo->p_tmevtb; if (p_tmevtb != NULL) { if (!on_stack(p_tmevtb, p_tinib)) { return(E_SYS_LINENO); } /* * (*p_tmevtb)の検査(未完成) */ } switch (tstat & TS_WAIT_MASK) { case TS_WAIT_SLP: if (p_tcb->wupque == true) { return(E_SYS_LINENO); } break; case TS_WAIT_DLY: if (p_tmevtb == NULL) { return(E_SYS_LINENO); } break; case TS_WAIT_SEM: p_semcb = ((WINFO_SEM *)(p_tcb->p_winfo))->p_semcb; if (!VALID_SEMCB(p_semcb)) { return(E_SYS_LINENO); } if (!in_queue(&(p_semcb->wait_queue), &(p_tcb->task_queue))) { return(E_SYS_LINENO); } break; case TS_WAIT_FLG: p_flgcb = ((WINFO_FLG *)(p_tcb->p_winfo))->p_flgcb; if (!VALID_FLGCB(p_flgcb)) { return(E_SYS_LINENO); } if (!in_queue(&(p_flgcb->wait_queue), &(p_tcb->task_queue))) { return(E_SYS_LINENO); } break; case TS_WAIT_SDTQ: p_dtqcb = ((WINFO_DTQ *)(p_tcb->p_winfo))->p_dtqcb; if (!VALID_DTQCB(p_dtqcb)) { return(E_SYS_LINENO); } if (!in_queue(&(p_dtqcb->swait_queue), &(p_tcb->task_queue))) { return(E_SYS_LINENO); } break; case TS_WAIT_RDTQ: p_dtqcb = ((WINFO_DTQ *)(p_tcb->p_winfo))->p_dtqcb; if (!VALID_DTQCB(p_dtqcb)) { return(E_SYS_LINENO); } if (!in_queue(&(p_dtqcb->rwait_queue), &(p_tcb->task_queue))) { return(E_SYS_LINENO); } break; case TS_WAIT_SPDQ: p_pdqcb = ((WINFO_PDQ *)(p_tcb->p_winfo))->p_pdqcb; if (!VALID_PDQCB(p_pdqcb)) { return(E_SYS_LINENO); } if (!in_queue(&(p_pdqcb->swait_queue), &(p_tcb->task_queue))) { return(E_SYS_LINENO); } break; case TS_WAIT_RPDQ: p_pdqcb = ((WINFO_PDQ *)(p_tcb->p_winfo))->p_pdqcb; if (!VALID_PDQCB(p_pdqcb)) { return(E_SYS_LINENO); } if (!in_queue(&(p_pdqcb->rwait_queue), &(p_tcb->task_queue))) { return(E_SYS_LINENO); } break; case TS_WAIT_MTX: p_mtxcb = ((WINFO_MTX *)(p_tcb->p_winfo))->p_mtxcb; if (!VALID_MTXCB(p_mtxcb)) { return(E_SYS_LINENO); } if (!in_queue(&(p_mtxcb->wait_queue), &(p_tcb->task_queue))) { return(E_SYS_LINENO); } break; case TS_WAIT_MPF: p_mpfcb = ((WINFO_MPF *)(p_tcb->p_winfo))->p_mpfcb; if (!VALID_MPFCB(p_mpfcb)) { return(E_SYS_LINENO); } if (!in_queue(&(p_mpfcb->wait_queue), &(p_tcb->task_queue))) { return(E_SYS_LINENO); } break; } } /* * tskctxbの検査 */ if (!TSTAT_DORMANT(tstat) && p_tcb != p_runtsk) { /* * ターゲット依存の検査 */ #if 0 if (bit_tskctxb(&(p_tcb->tskctxb))) { return(E_SYS_LINENO); } #endif } return(E_OK); }
/* * タスク毎の検査 */ static ER bit_mutex_task(ID tskid) { TCB *p_tcb; uint_t pri; MTXCB *p_mtxcb; const MTXINIB *p_mtxinib; if (!VALID_TSKID(tskid)) { return(E_ID); } p_tcb = get_tcb(tskid); pri = p_tcb->bpriority; /* * タスクがロックしているミューテックスのキューの検査 */ p_mtxcb = p_tcb->p_lastmtx; while (p_mtxcb != NULL) { if (!VALID_MTXCB(p_mtxcb)) { return(E_SYS_LINENO); } p_mtxinib = p_mtxcb->p_mtxinib; /* * ミューテックスをロックしているタスクのチェック */ if (p_mtxcb->p_loctsk != p_tcb) { return(E_SYS_LINENO); } /* * 現在優先度の計算 */ if (MTXPROTO(p_mtxinib)) { if (p_mtxinib->ceilpri < pri) { pri = p_mtxinib->ceilpri; } } /* * キューの次の要素に進む */ p_mtxcb = p_mtxcb->p_prevmtx; } /* * 現在優先度の検査 */ if (p_tcb->priority != pri) { return(E_SYS_LINENO); } /* * タスクが待っているミューテックスに関する検査 */ if (TSTAT_WAIT_MTX(p_tcb->tstat)) { p_mtxcb = ((WINFO_MTX *)(p_tcb->p_winfo))->p_mtxcb; if (!VALID_MTXCB(p_mtxcb)) { return(E_SYS_LINENO); } if (!in_queue(&(p_mtxcb->wait_queue), &(p_tcb->task_queue))) { return(E_SYS_LINENO); } } return(E_OK); }
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); }
void *ktls_access(unsigned long tls_offset) { struct thread_control_block *tcb = get_tcb(); return tcb->tls + tls_offset; }