void wait_dequeue_wobj(TCB *p_tcb) { if (TSTAT_WAIT_WOBJ(p_tcb->tstat)) { queue_delete(&(p_tcb->task_queue)); if (TSTAT_WAIT_SMBF(p_tcb->tstat)) { (*mbfhook_dequeue_wobj)(p_tcb); } } }
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 chg_pri(ID tskid, PRI tskpri) { TCB *p_tcb; uint_t newpri; ER ercd; bool_t dspreq = false; PCB *p_pcb; LOG_CHG_PRI_ENTER(tskid, tskpri); CHECK_TSKCTX_UNL(); CHECK_TSKID_SELF(tskid); CHECK_TPRI_INI(tskpri); t_lock_cpu(); p_tcb = get_tcb_self(tskid, get_my_p_pcb()); newpri = (tskpri == TPRI_INI) ? p_tcb->p_tinib->ipriority : INT_PRIORITY(tskpri); p_pcb = t_acquire_tsk_lock(p_tcb); if (TSTAT_DORMANT(p_tcb->tstat)) { ercd = E_OBJ; } else { #if TTYPE_KLOCK == G_KLOCK if (change_priority(p_tcb, newpri)) { dspreq = dispatch_request(p_pcb); } #else /* TTYPE_KLOCK != G_KLOCK */ if (!(TSTAT_WAITING(p_tcb->tstat) && TSTAT_WAIT_WOBJ(p_tcb->tstat))) { /* オブジェクト待ち以外の状態の場合 */ if (change_priority(p_tcb, newpri)) { dspreq = dispatch_request(p_pcb); } } else { /* * オブジェクト待ちの場合 * デッドロック回避のため,ロックを取得し直す */ WOBJCB *p_wobjcb = p_tcb->p_wobjcb; p_tcb->pend_chgpri = true; p_tcb->pend_newpri = newpri; release_tsk_lock(p_pcb); /* * あらためて * オブジェクトロック -> タスクロック * の順でロックを取得 */ TEST_G_LABEL("_test_chg_pri"); retry: 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 (!(p_tcb->pend_chgpri)) { /* 既に他の箇所で優先度変更処理がなされた */ release_nested_tsk_lock(p_pcb); release_obj_lock(&GET_OBJLOCK(p_wobjcb)); t_unlock_cpu(); ercd = E_OK; goto error_exit; } p_tcb->priority = p_tcb->pend_newpri; p_tcb->pend_chgpri = false; change_priority(p_tcb, newpri); release_obj_lock(&GET_OBJLOCK(p_wobjcb)); } #endif /* TTYPE_KLOCK != G_KLOCK */ ercd = E_OK; } release_tsk_lock(p_pcb); if (dspreq) { dispatch(); } t_unlock_cpu(); error_exit: LOG_CHG_PRI_LEAVE(ercd); return(ercd); }