Пример #1
0
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);
}
Пример #2
0
ER
sus_tsk(ID tskid)
{
	TCB		*p_tcb;
	ER		ercd;

	LOG_SUS_TSK_ENTER(tskid);
	CHECK_TSKCTX_UNL();							/*[NGKI1299][NGKI1300]*/
	if (tskid == TSK_SELF) {
		p_tcb = p_runtsk;						/*[NGKI1310]*/
	}
	else {
		CHECK_ID(VALID_TSKID(tskid));			/*[NGKI1302]*/
		p_tcb = get_tcb(tskid);
	}

	lock_cpu();
	if (p_tcb == p_runtsk && !dspflg) {			/*[NGKI1311][NGKI3604]*/
		ercd = E_CTX;
	}
	else if (p_tcb->p_tinib->tskatr == TA_NOEXS) {
		ercd = E_NOEXS;							/*[NGKI1303]*/
	}
	else if (TSTAT_DORMANT(p_tcb->tstat)) {
		ercd = E_OBJ;							/*[NGKI1305]*/
	}
	else if (p_tcb->raster) {
		ercd = E_RASTER;						/*[NGKI3605]*/
	}
	else if (TSTAT_RUNNABLE(p_tcb->tstat)) {
		/*
		 *  実行できる状態から強制待ち状態への遷移[NGKI1307]
		 */
		p_tcb->tstat = TS_SUSPENDED;
		LOG_TSKSTAT(p_tcb);
		make_non_runnable(p_tcb);
		if (p_runtsk != p_schedtsk) {
			dispatch();
		}
		ercd = E_OK;
	}
	else if (TSTAT_SUSPENDED(p_tcb->tstat)) {
		ercd = E_QOVR;							/*[NGKI1306]*/
	}
	else {
		/*
		 *  待ち状態から二重待ち状態への遷移[NGKI1308]
		 */
		p_tcb->tstat |= TS_SUSPENDED;
		LOG_TSKSTAT(p_tcb);
		ercd = E_OK;
	}
	unlock_cpu();

  error_exit:
	LOG_SUS_TSK_LEAVE(ercd);
	return(ercd);
}
Пример #3
0
ER
sus_tsk(ID tskid)
{
	TCB		*p_tcb;
	ER		ercd;

	LOG_SUS_TSK_ENTER(tskid);
	CHECK_TSKCTX_UNL();
	CHECK_TSKID_SELF(tskid);
	p_tcb = get_tcb_self(tskid);

	t_lock_cpu();
	if (p_tcb == p_runtsk && !dspflg) {
		ercd = E_CTX;
	}
	else 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->tstat = TS_SUSPENDED;
		LOG_TSKSTAT(p_tcb);
		if (make_non_runnable(p_tcb)) {
			dispatch();
		}
		ercd = E_OK;
	}
	else if (TSTAT_SUSPENDED(p_tcb->tstat)) {
		ercd = E_QOVR;
	}
	else {
		/*
		 *  待ち状態から二重待ち状態への遷移
		 */
		p_tcb->tstat |= TS_SUSPENDED;
		LOG_TSKSTAT(p_tcb);
		ercd = E_OK;
	}
	t_unlock_cpu();

  error_exit:
	LOG_SUS_TSK_LEAVE(ercd);
	return(ercd);
}
Пример #4
0
SYSCALL ER
sus_tsk(ID tskid)
{
	TCB	*tcb;
	UINT	tstat;
	ER	ercd;

	LOG_SUS_TSK_ENTER(tskid);
	CHECK_TSKCTX_UNL();
	CHECK_TSKID_SELF(tskid);
	tcb = get_tcb_self(tskid);

	t_lock_cpu();
	if (tcb == runtsk && !(enadsp)) {
		ercd = E_CTX;
	}
	else if (TSTAT_DORMANT(tstat = tcb->tstat)) {
		ercd = E_OBJ;
	}
	else if (TSTAT_RUNNABLE(tstat)) {
		/*
		 *  実行できる状態から強制待ち状態への遷移
		 */
		tcb->tstat = TS_SUSPENDED;
		LOG_TSKSTAT(tcb);
		if (make_non_runnable(tcb)) {
			dispatch();
		}
		ercd = E_OK;
	}
	else if (TSTAT_SUSPENDED(tstat)) {
		ercd = E_QOVR;
	}
	else {
		/*
		 *  待ち状態から二重待ち状態への遷移
		 */
		tcb->tstat |= TS_SUSPENDED;
		LOG_TSKSTAT(tcb);
		ercd = E_OK;
	}
	t_unlock_cpu();

    exit:
	LOG_SUS_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);
}
Пример #6
0
SYSCALL ER
chg_pri(ID tskid, PRI tskpri)
{
	TCB	*tcb;
	UINT	newpri;
	UINT	tstat;
	ER	ercd;

	LOG_CHG_PRI_ENTER(tskid, tskpri);
	CHECK_TSKCTX_UNL();
	CHECK_TSKID_SELF(tskid);
	CHECK_TPRI_INI(tskpri);
	tcb = get_tcb_self(tskid);
	newpri = (tskpri == TPRI_INI) ? tcb->tinib->ipriority
					: INT_PRIORITY(tskpri);

	t_lock_cpu();
	if (TSTAT_DORMANT(tstat = tcb->tstat)) {
		ercd = E_OBJ;
	}
	else if (TSTAT_RUNNABLE(tstat)) {
		if (change_priority(tcb, newpri)) {
			dispatch();
		}
		ercd = E_OK;
	}
	else {
		tcb->priority = newpri;
		if ((tstat & TS_WAIT_WOBJCB) != 0) {
			wobj_change_priority(((WINFO_WOBJ *)(tcb->winfo))
							->wobjcb, tcb);
		}
		ercd = E_OK;
	}
	t_unlock_cpu();

    exit:
	LOG_CHG_PRI_LEAVE(ercd);
	return(ercd);
}
Пример #7
0
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);
}
Пример #8
0
/*
 *  タスク毎の整合性検査
 */
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);
}
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);
}
ER
mig_tsk(ID tskid, ID prcid)
{
	TCB		*p_tcb;
	ER		ercd = E_OK;
	PCB		*t_p_pcb;
	PCB		*f_p_pcb;
	bool_t	dspreq = false;
	PCB		*my_p_pcb;
#ifdef TOPPERS_SYSTIM_LOCAL
	EVTTIM	left_time;
#endif /* TOPPERS_SYSTIM_LOCAL */

	LOG_MIG_TSK_ENTER(tskid, prcid);
	CHECK_TSKCTX_UNL();
	CHECK_TSKID_SELF(tskid);
	CHECK_PRCID_INI(prcid);

	t_lock_cpu();
	p_tcb = get_tcb_self(tskid, get_my_p_pcb());
	prcid = (prcid == TPRC_INI)? p_tcb->p_tinib->iaffinity : prcid;
	T_CHECK_MIG(p_tcb->p_tinib->affinity_mask, prcid);

	/* 現在割り付けられているプロセッサと移動先のプロセッサのタスクロックを取得 */
	t_acquire_dual_tsk_lock(p_tcb, prcid, &f_p_pcb, &t_p_pcb);
	my_p_pcb = get_my_p_pcb();
	if (f_p_pcb != my_p_pcb) {
		/*
		 * 自タスクと同じプロセッサに割り付けられているタスクでなけれ
		 * ばエラー. mig_tsk を呼び出したタスクがシステムコール呼出し後,
		 * マイグレートされた場合にも,ここでエラーとなる
		 */
		ercd = E_OBJ;
	}
	else if (TSTAT_RUNNABLE(p_tcb->tstat)){
		/* 実行可能状態 */
		if(p_tcb == my_p_pcb->p_runtsk) {
			/* 自タスクに対して発行 */
			if (!(my_p_pcb->dspflg)) {
				/* ディスパッチ禁止中ならエラー */
				ercd = E_CTX;
			}
			else if (t_p_pcb == my_p_pcb) {
				/* 同一プロセッサを指定 */
				/* 優先順位を同一優先度のタスクの中で最低とする */
				dspreq = set_lowest_precedence(p_tcb, my_p_pcb);
				ercd = E_OK; 
			}
			else {
				/* マイグレーション要求を処理 */
				LOG_TSKMIG(p_tcb, my_p_pcb->prcid, prcid);
				dispatch_and_migrate(prcid);
				/* ここに戻ってくる時にはロックは解放されている */
				ercd = E_OK;
				t_unlock_cpu();
				goto error_exit;
			}
		} 
		else {
			/* 他タスクの場合 */
			if (t_p_pcb == my_p_pcb) {
				/* 同一プロセッサを指定 */
				/* 
				 *  優先順位を同一優先度のタスクの中で最低とする.
				 *  対象のタスクは最高優先順位のタスクでないため,タ
				 *  スク切り替えは発生しない
				 */
				(void)set_lowest_precedence(p_tcb, my_p_pcb);
				ercd = E_OK; 
			}
			else {
				/* 異なるプロセッサを指定 */
				/* レディーキューから外す */
				make_non_runnable(p_tcb);
				/* pcb の書き換え */
				p_tcb->p_pcb = t_p_pcb;
				LOG_TSKMIG(p_tcb, my_p_pcb->prcid, prcid);
				/* 移行先のプロセッサでmake_runnable する*/
				if (make_runnable(p_tcb)) {
					dispatch_request(t_p_pcb);
				}
				ercd = E_OK;
			}
		}
	}
	else if (TSTAT_DORMANT(p_tcb->tstat)) {
		/* 休止状態 */
		LOG_TSKMIG(p_tcb, my_p_pcb->prcid, prcid);
		p_tcb->p_pcb = t_p_pcb;
		ercd = E_OK;
	}
	else {
		/* 待ち状態 */
		if ((p_tcb->tmevtb).callback == NULL) {
			/* 時間待ちでない場合 */
			LOG_TSKMIG(p_tcb, my_p_pcb->prcid, prcid);
			p_tcb->p_pcb = t_p_pcb;
			ercd = E_OK;
		}
		else {
			/*
			 * 時間待ちの場合 グローバルタイマ方式 なら必要なし
			 */
#ifdef TOPPERS_SYSTIM_LOCAL
			/* キューから削除 */
			left_time = tmevtb_dequeue(f_p_pcb->p_tevtcb, &(p_tcb->tmevtb));
			LOG_TSKMIG(p_tcb, my_p_pcb->prcid, prcid);
			/* 移動先のプロセッサのキューに挿入 */
			tmevtb_insert(t_p_pcb->p_tevtcb, &(p_tcb->tmevtb), base_time(t_p_pcb->p_tevtcb) + left_time);
#else  /* TOPPERS_SYSTIM_GLOBAL */
			LOG_TSKMIG(p_tcb, my_p_pcb->prcid, prcid);
#endif /* TOPPERS_SYSTIM_GLOBAL */
			p_tcb->p_pcb = t_p_pcb;
			ercd = E_OK;
		}
	}
	release_dual_tsk_lock(f_p_pcb, t_p_pcb);
	if (dspreq) {
		dispatch();
	}
	t_unlock_cpu();

  error_exit:
	LOG_MIG_TSK_LEAVE(ercd);
	return(ercd);
}