Exemple #1
0
/*
 * 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_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 ( (tcb->tskatr & copatr) == 0 ) {
				ercd = E_PAR;
			} else if ( is_ctxtsk(tcb) ) {
				ercd = E_OBJ;
			} else {
				/* No coprocessor */
			}
		}
	}
	END_CRITICAL_NO_DISPATCH;

	return ercd;
}
Exemple #2
0
/*
 * Delete rendezvous port
 */
SYSCALL ER tk_del_por_impl( ID porid )
{
	PORCB	*porcb;
	ER	ercd = E_OK;

	CHECK_PORID(porid);
	CHECK_INTSK();

	porcb = get_porcb(porid);

	BEGIN_CRITICAL_SECTION;
	if ( porcb->porid == 0 ) {
		ercd = E_NOEXS;
	} else {
		/* Release wait state of task (E_DLT) */
		knl_wait_delete(&porcb->call_queue);
		knl_wait_delete(&porcb->accept_queue);

		/* Return to FreeQue */
		QueInsert(&porcb->call_queue, &knl_free_porcb);
		porcb->porid = 0;
	}
	END_CRITICAL_SECTION;

	return ercd;
}
Exemple #3
0
/*
 * 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);
	CHECK_NONSELF(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;
}
Exemple #4
0
/*
 * Unlock mutex
 */
SYSCALL ER _tk_unl_mtx( ID mtxid )
{
	MTXCB	*mtxcb;	
	TCB	*tcb;
	ER	ercd = E_OK;

	CHECK_MTXID(mtxid);
	CHECK_INTSK();

	mtxcb = get_mtxcb(mtxid);

	BEGIN_CRITICAL_SECTION;
	if ( mtxcb->mtxid == 0 ) {
		ercd = E_NOEXS;
		goto error_exit;
	}
	if ( mtxcb->mtxtsk != ctxtsk ) {
		ercd = E_ILUSE;  /* This is not locked by its own task */
		goto error_exit;
	}

	/* Delete the mutex from the list,
	   and adjust its own task priority if necessary. */
	release_mutex(ctxtsk, mtxcb);

	if ( mtx_waited(mtxcb) ) {
		tcb = (TCB*)mtxcb->wait_queue.next;

		/* Release wait */
		wait_release_ok(tcb);

		/* Change mutex get task */
		mtxcb->mtxtsk = tcb;
		mtxcb->mtxlist = tcb->mtxlist;
		tcb->mtxlist = mtxcb;

		if ( (mtxcb->mtxatr & TA_CEILING) == TA_CEILING ) {
			if ( tcb->priority > mtxcb->ceilpri ) {
				/* Raise the priority of the task that
				   got lock to the highest priority limit */
				change_task_priority(tcb, mtxcb->ceilpri);
			}
		}
	} else {
		/* No wait task */
		mtxcb->mtxtsk = NULL;
	}

    error_exit:
	END_CRITICAL_SECTION;

	return ercd;
}
Exemple #5
0
/*
 * Create rendezvous port
 */
SYSCALL ID _tk_cre_por( CONST T_CPOR *pk_cpor )
{
#if CHK_RSATR
	const ATR VALID_PORATR = {
		 TA_TPRI
		|TA_NODISWAI
#if USE_OBJECT_NAME
		|TA_DSNAME
#endif
	};
#endif
	PORCB	*porcb;
	ID	porid;
	ER	ercd;

	CHECK_RSATR(pk_cpor->poratr, VALID_PORATR);
	CHECK_PAR(pk_cpor->maxcmsz >= 0);
	CHECK_PAR(pk_cpor->maxrmsz >= 0);
	CHECK_INTSK();

	BEGIN_CRITICAL_SECTION;
	/* Get control block from FreeQue */
	porcb = (PORCB*)QueRemoveNext(&free_porcb);
	if ( porcb == NULL ) {
		ercd = E_LIMIT;
	} else {
		porid = ID_POR(porcb - porcb_table);

		/* Initialize control block */
		QueInit(&porcb->call_queue);
		porcb->porid = porid;
		porcb->exinf = pk_cpor->exinf;
		porcb->poratr = pk_cpor->poratr;
		QueInit(&porcb->accept_queue);
		porcb->maxcmsz = pk_cpor->maxcmsz;
		porcb->maxrmsz = pk_cpor->maxrmsz;
#if USE_OBJECT_NAME
		if ( (pk_cpor->poratr & TA_DSNAME) != 0 ) {
			strncpy((char*)porcb->name, (char*)pk_cpor->dsname,
				OBJECT_NAME_LENGTH);
		}
#endif
		ercd = porid;
	}
	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;
}
Exemple #7
0
/*
 * 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;
}
Exemple #8
0
/*
 * 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;
}
Exemple #9
0
/*
 * 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;
}