/*
 *  タスク毎の検査
 */
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);
}
/*
 *  ミューテックス毎の検査
 */
static ER
bit_mutex_mutex(ID mtxid)
{
	MTXCB			*p_mtxcb, *p_acquired_mtx;
	const MTXINIB	*p_mtxinib;
	TCB				*p_tcb;
	QUEUE			*p_queue, *p_next;
	uint_t			pri;

	if (!VALID_MTXID(mtxid)) {
		return(E_ID);
	}
	p_mtxcb = get_mtxcb(mtxid);
	p_mtxinib = p_mtxcb->p_mtxinib;

	/*
	 *  初期化ブロックへのポインタの検査
	 */
	if (p_mtxinib != &(mtxinib_table[INDEX_MTX(mtxid)])) {
		return(E_SYS_LINENO);
	}

	/*
	 *  ミューテックス待ちキューの検査
	 */
	p_queue = p_mtxcb->wait_queue.p_next;
	if (p_queue->p_prev != &(p_mtxcb->wait_queue)) {
		return(E_SYS_LINENO);
	}
	pri = TMIN_TPRI;
	while (p_queue != &(p_mtxcb->wait_queue)) {
		p_tcb = (TCB *) p_queue;
		if (!VALID_TCB(p_tcb)) {
			return(E_SYS_LINENO);
		}

		/*
		 *  キューがタスク優先度順になっているかの検査
		 */
		if (MTXPROTO(p_mtxinib) != TA_NULL) {
			if (p_tcb->priority < pri) {
				return(E_SYS_LINENO);
			}
		}
		pri = p_tcb->priority;

		/*
		 *  タスク状態の検査
		 *
		 *  ミューテックス待ち状態のタスクの検査は,タスク毎の検査で行っ
		 *  ているため,ここでは行わない.
		 */
		if (!TSTAT_WAIT_MTX(p_tcb->tstat)) {
			return(E_SYS_LINENO);
		}

		/*
		 *  優先度上限の検査
		 */
		if (MTX_CEILING(p_mtxinib)) {
			if (p_tcb->bpriority < p_mtxinib->ceilpri) {
				return(E_SYS_LINENO);
			}
		}

		/*
		 *  キューの次の要素に進む
		 */
		p_next = p_queue->p_next;
		if (p_next->p_prev != p_queue) {
			return(E_SYS_LINENO);
		}
		p_queue = p_next;
	}

	/*
	 *  ミューテックスをロックしているタスクの検査
	 */
	p_tcb = p_mtxcb->p_loctsk;
	if (p_tcb == NULL) {
		/*
		 *  ミューテックスがロックされていない時
		 */
		if (!queue_empty(&(p_mtxcb->wait_queue))) {
			return(E_SYS_LINENO);
		}
	}
	else {
		/*
		 *  ミューテックスがロックされている時
		 *
		 *  ミューテックスをロックしているタスクの検査は,タスク毎の検
		 *  査で行っているため,ここでは行わない.
		 */
		if (!VALID_TCB(p_tcb)) {
			return(E_SYS_LINENO);
		}
		p_acquired_mtx = p_tcb->p_lastmtx;
		while (p_mtxcb != NULL) {
			if (p_mtxcb == p_acquired_mtx) {
				break;
			}
			p_acquired_mtx = p_acquired_mtx->p_prevmtx;
		}
		if (p_mtxcb == NULL) {
			return(E_SYS_LINENO);
		}

		/*
		 *  優先度上限の検査
		 */
		if (MTX_CEILING(p_mtxinib)) {
			if (p_tcb->bpriority < p_mtxinib->ceilpri) {
				return(E_SYS_LINENO);
			}
		}
	}
	return(E_OK);
}
/*
 *  タスク毎の検査
 */
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);
}