Example #1
0
/*
 * Wakeup task
 */
SYSCALL ER _tk_wup_tsk( 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 ( !task_alive(state) ) {
		ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ;

	} else if ( (state & TS_WAIT) != 0 && tcb->wspec == &wspec_slp ) {
		wait_release_ok(tcb);

	} else if ( tcb->wupcnt == INT_MAX ) {
		ercd = E_QOVR;
	} else {
		++tcb->wupcnt;
	}
	END_CRITICAL_SECTION;

	return ercd;
}
Example #2
0
File: mutex.c Project: yuki74w/TRON
/*
 * Free mutex when task is terminated
 *	Free all mutexes which the task holds.
 *	Do not need to handle mutex list and priority of terminated task.
 *	
 */
EXPORT void signal_all_mutex( TCB *tcb )
{
	MTXCB	*mtxcb, *next_mtxcb;
	TCB	*next_tcb;

	next_mtxcb = tcb->mtxlist;
	while ( (mtxcb = next_mtxcb) != NULL ) {
		next_mtxcb = mtxcb->mtxlist;

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

			/* Wake wait task */
			wait_release_ok(next_tcb);

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

			if ( (mtxcb->mtxatr & TA_CEILING) == TA_CEILING ) {
				if ( next_tcb->priority > mtxcb->ceilpri ) {
					/* Raise the priority for the task
					   that got lock to the highest
					   priority limit */
					change_task_priority(next_tcb,
							mtxcb->ceilpri);
				}
			}
		} else {
			/* No wait task */
			mtxcb->mtxtsk = NULL;
		}
	}
}
Example #3
0
SYSCALL INT _tk_rcv_mbf_u( ID mbfid, void *msg, TMO_U tmout )
{
	MBFCB	*mbfcb;
	TCB	*tcb;
	INT	rcvsz;
	ER	ercd = E_OK;

	CHECK_MBFID(mbfid);
	CHECK_TMOUT(tmout);
	CHECK_DISPATCH();

	mbfcb = get_mbfcb(mbfid);

	BEGIN_CRITICAL_SECTION;
	if (mbfcb->mbfid == 0) {
		ercd = E_NOEXS;
		goto error_exit;
	}

	/* Check receive wait disable */
	if ( is_diswai((GCB*)mbfcb, ctxtsk, TTW_RMBF) ) {
		ercd = E_DISWAI;
		goto error_exit;
	}

	if ( !mbf_empty(mbfcb) ) {
		/* Read from message buffer */
		rcvsz = mbf_to_msg(mbfcb, msg);

		/* Accept message from sending task(s) */
		mbf_wakeup(mbfcb);

	} else if ( !isQueEmpty(&mbfcb->send_queue) ) {
		/* Receive directly from send wait task */
		tcb = (TCB*)mbfcb->send_queue.next;
		rcvsz = tcb->winfo.smbf.msgsz;
		memcpy(msg, tcb->winfo.smbf.msg, (UINT)rcvsz);
		wait_release_ok(tcb);
		mbf_wakeup(mbfcb);
	} else {
		ercd = E_TMOUT;
		if ( tmout != TMO_POL ) {
			/* Ready for receive wait */
			ctxtsk->wspec = &wspec_rmbf;
			ctxtsk->wid = mbfid;
			ctxtsk->wercd = &ercd;
			ctxtsk->winfo.rmbf.msg = msg;
			ctxtsk->winfo.rmbf.p_msgsz = &rcvsz;
			make_wait(tmout, mbfcb->mbfatr);
			QueInsert(&ctxtsk->tskque, &mbfcb->recv_queue);
		}
	}

    error_exit:
	END_CRITICAL_SECTION;

	return ( ercd < E_OK )? ercd: rcvsz;
}
Example #4
0
File: mutex.c Project: yuki74w/TRON
/*
 * 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;
}
Example #5
0
/*
 * Send to mailbox
 */
SYSCALL ER _tk_snd_mbx( ID mbxid, T_MSG *pk_msg )
{
	MBXCB	*mbxcb;
	TCB	*tcb;
	ER	ercd = E_OK;

	CHECK_MBXID(mbxid);

	mbxcb = get_mbxcb(mbxid);

	BEGIN_CRITICAL_SECTION;
	if (mbxcb->mbxid == 0) {
		ercd = E_NOEXS;
		goto error_exit;
	}

	if ( (mbxcb->mbxatr & TA_MPRI) != 0 ) {
		if ( ((T_MSG_PRI*)pk_msg)->msgpri <= 0 ) {
			ercd = E_PAR;
			goto error_exit;
		}
	}

	if ( !isQueEmpty(&mbxcb->wait_queue) ) {
		/* Directly send to receive wait task */
		tcb = (TCB*)(mbxcb->wait_queue.next);
		*tcb->winfo.mbx.ppk_msg = pk_msg;
		wait_release_ok(tcb);

	} else {
		/* Connect message to queue */
		if ( (mbxcb->mbxatr & TA_MPRI) != 0 ) {
			/* Connect message to queue following priority */
			queue_insert_mpri((T_MSG_PRI*)pk_msg, &mbxcb->mq_head);
		} else {
			/* Connect to end of queue */
			nextmsg(pk_msg) = NULL;
			if ( headmsg(mbxcb) == NULL ) {
				headmsg(mbxcb) = pk_msg;
			} else {
				nextmsg(mbxcb->mq_tail) = pk_msg;
			}
			mbxcb->mq_tail = pk_msg;
		}
	}

    error_exit:
	END_CRITICAL_SECTION;

	return ercd;
}
Example #6
0
/*
 * Accept message and release wait task,
 * as long as there are free message area.
 */
LOCAL void mbf_wakeup( MBFCB *mbfcb )
{
	TCB	*top;
	INT	msgsz;

	while ( !isQueEmpty(&mbfcb->send_queue) ) {
		top = (TCB*)mbfcb->send_queue.next;
		msgsz = top->winfo.smbf.msgsz;
		if ( !mbf_free(mbfcb, msgsz) ) {
			break;
		}

		/* Store a message from waiting task and release it */
		msg_to_mbf(mbfcb, top->winfo.smbf.msg, msgsz);
		wait_release_ok(top);
	}
}
Example #7
0
/*
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
 Funtion	:_bk_wup_tsk
 Input		:struct task *task
 		 < task to wake up >
 Output		:void
 Return		:ER
 		 < result >
 Description	:wake up a task for btron
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
*/
EXPORT ER _bk_wup_tsk(struct task *task)
{
	ER	ercd = E_OK;
	TSTAT	state;
	
	state = (TSTAT)task->state;
	if ( !task_alive(state) ) {
		ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ;

	} else if ( (state & TS_WAIT) != 0 && task->wspec == &wspec_slp ) {
		wait_release_ok(task);

	} else if ( task->wupcnt == INT_MAX ) {
		ercd = E_QOVR;
	} else {
		++task->wupcnt;
	}
	
	return(ercd);
}
Example #8
0
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);
	}
Example #9
0
/*
 * Allocate memory and release wait task,
 * as long as there are enough free memory.
 */
LOCAL void mpl_wakeup( MPLCB *mplcb )
{
	TCB	*top;
	void	*blk;
	INT	blksz;

	while ( !isQueEmpty(&mplcb->wait_queue) ) {
		top = (TCB*)mplcb->wait_queue.next;
		blksz = top->winfo.mpl.blksz;

		/* Check free space */
		if ( blksz > MaxFreeSize(mplcb) ) {
			break;
		}

		/* Get memory block */
		blk = get_blk(mplcb, blksz);
		*top->winfo.mpl.p_blk = blk;

		/* Release wait task */
		wait_release_ok(top);
	}
}
Example #10
0
/*
 * Reply rendezvous
 */
SYSCALL ER _tk_rpl_rdv( RNO rdvno, void *msg, INT rmsgsz )
{
	TCB	*caltcb;
	ER	ercd = E_OK;

	CHECK_RDVNO(rdvno);
	CHECK_PAR(rmsgsz >= 0);
	CHECK_INTSK();

	caltcb = get_tcb(get_tskid_rdvno(rdvno));

	BEGIN_CRITICAL_SECTION;
	if ( (caltcb->state & TS_WAIT) == 0
	  || caltcb->wspec != &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;
	wait_release_ok(caltcb);

    error_exit:
	END_CRITICAL_SECTION;

	return ercd;
}
Example #11
0
SYSCALL ER _tk_snd_mbf_u( ID mbfid, CONST void *msg, INT msgsz, TMO_U tmout )
{
	MBFCB	*mbfcb;
	TCB	*tcb;
	ER	ercd = E_OK;

	CHECK_MBFID(mbfid);
	CHECK_PAR(msgsz > 0);
	CHECK_TMOUT(tmout);
	CHECK_DISPATCH_POL(tmout);

	mbfcb = get_mbfcb(mbfid);

	BEGIN_CRITICAL_SECTION;
	if ( mbfcb->mbfid == 0 ) {
		ercd = E_NOEXS;
		goto error_exit;
	}
#if CHK_PAR
	if ( msgsz > mbfcb->maxmsz ) {
		ercd = E_PAR;
		goto error_exit;
	}
#endif

	/* Check send wait disable */
	if ( !in_indp() && is_diswai((GCB*)mbfcb, ctxtsk, TTW_SMBF) ) {
		ercd = E_DISWAI;
		goto error_exit;
	}

	if ( !isQueEmpty(&mbfcb->recv_queue) ) {
		/* Send directly to the receive wait task */
		tcb = (TCB*)mbfcb->recv_queue.next;
		memcpy(tcb->winfo.rmbf.msg, msg, (UINT)msgsz);
		*tcb->winfo.rmbf.p_msgsz = msgsz;
		wait_release_ok(tcb);

	} else if ( (in_indp() || gcb_top_of_wait_queue((GCB*)mbfcb, ctxtsk) == ctxtsk)
		  &&(mbf_free(mbfcb, msgsz)) ) {
		/* Store the message to message buffer */
		msg_to_mbf(mbfcb, msg, msgsz);

	} else {
		ercd = E_TMOUT;
		if ( tmout != TMO_POL ) {
			/* Ready for send wait */
			ctxtsk->wspec = ( (mbfcb->mbfatr & TA_TPRI) != 0 )?
					&wspec_smbf_tpri: &wspec_smbf_tfifo;
			ctxtsk->wercd = &ercd;
			ctxtsk->winfo.smbf.msg = msg;
			ctxtsk->winfo.smbf.msgsz = msgsz;
			gcb_make_wait_with_diswai((GCB*)mbfcb, tmout);
		}
	}

    error_exit:
	END_CRITICAL_SECTION;

	return ercd;
}
Example #12
0
/*
 * Forward Rendezvous to Other Port
 */
SYSCALL ER _tk_fwd_por( ID porid, UINT calptn, RNO rdvno, void *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(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 != &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;
		}

		/* Check rendezvous accept wait disable */
		if ( is_diswai((GCB*)porcb, caltcb, TTW_CAL) ) {
			wait_release_ng(caltcb, E_DISWAI);
			ercd = E_DISWAI;
			goto error_exit;
		}

		/* Send message */
		new_rdvno = 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;
		wait_release_ok(tcb);

		/* Check rendezvous end wait disable */
		if ( is_diswai((GCB*)porcb, caltcb, TTW_RDV) ) {
			wait_release_ng(caltcb, E_DISWAI);
			ercd = E_DISWAI;
			goto error_exit;
		}

		/* 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;
		caltcb->nodiswai = ( (porcb->poratr & TA_NODISWAI) != 0 )? TRUE: FALSE;
		goto error_exit;
	}

	/* Check rendezvous accept wait disable */
	if ( is_diswai((GCB*)porcb, caltcb, TTW_CAL) ) {
		wait_release_ng(caltcb, E_DISWAI);
		ercd = E_DISWAI;
		goto error_exit;
	}

	/* Change the other task to rendezvous call wait */
	caltcb->wspec = ( (porcb->poratr & TA_TPRI) != 0 )?
				&wspec_cal_tpri: &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;
	caltcb->nodiswai = ( (porcb->poratr & TA_NODISWAI) != 0 )? TRUE: FALSE;
	timer_insert(&caltcb->wtmeb, TMO_FEVR,
			(CBACK)wait_release_tmout, caltcb);
	if ( (porcb->poratr & TA_TPRI) != 0 ) {
		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;
}
Example #13
0
SYSCALL INT _tk_cal_por_u( ID porid, UINT calptn, void *msg, INT cmsgsz, TMO_U tmout )
{
	PORCB	*porcb;
	TCB	*tcb;
	QUEUE	*queue;
	RNO	rdvno;
	INT	rmsgsz;
	ER	ercd = E_OK;

	CHECK_PORID(porid);
	CHECK_PAR(calptn != 0);
	CHECK_PAR(cmsgsz >= 0);
	CHECK_TMOUT(tmout);
	CHECK_DISPATCH();

	porcb = get_porcb(porid);

	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

	/* 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;
		}

		/* Check rendezvous call wait disable */
		if ( is_diswai((GCB*)porcb, ctxtsk, TTW_CAL) ) {
			ercd = E_DISWAI;
			goto error_exit;
		}

		/* Send message */
		rdvno = gen_rdvno(ctxtsk);
		if ( cmsgsz > 0 ) {
			memcpy(tcb->winfo.acp.msg, msg, (UINT)cmsgsz);
		}
		*tcb->winfo.acp.p_rdvno = rdvno;
		*tcb->winfo.acp.p_cmsgsz = cmsgsz;
		wait_release_ok(tcb);

		/* Check rendezvous end wait disable */
		if ( is_diswai((GCB*)porcb, ctxtsk, TTW_RDV) ) {
			ercd = E_DISWAI;
			goto error_exit;
		}

		/* Ready for rendezvous end wait */
		ercd = E_TMOUT;
		ctxtsk->wspec = &wspec_rdv;
		ctxtsk->wid = 0;
		ctxtsk->wercd = &ercd;
		ctxtsk->winfo.rdv.rdvno = rdvno;
		ctxtsk->winfo.rdv.msg = msg;
		ctxtsk->winfo.rdv.maxrmsz = porcb->maxrmsz;
		ctxtsk->winfo.rdv.p_rmsgsz = &rmsgsz;
		make_wait(TMO_FEVR, porcb->poratr);
		QueInit(&ctxtsk->tskque);

		goto error_exit;
	}

	/* Ready for rendezvous call wait */
	ctxtsk->wspec = ( (porcb->poratr & TA_TPRI) != 0 )?
					&wspec_cal_tpri: &wspec_cal_tfifo;
	ctxtsk->wercd = &ercd;
	ctxtsk->winfo.cal.calptn = calptn;
	ctxtsk->winfo.cal.msg = msg;
	ctxtsk->winfo.cal.cmsgsz = cmsgsz;
	ctxtsk->winfo.cal.p_rmsgsz = &rmsgsz;
	gcb_make_wait_with_diswai((GCB*)porcb, tmout);

    error_exit:
	END_CRITICAL_SECTION;

	return ( ercd < E_OK )? ercd: rmsgsz;
}