예제 #1
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;
}
예제 #2
0
파일: mempool.c 프로젝트: yuki74w/TRON
SYSCALL ER _tk_get_mpl_u( ID mplid, INT blksz, void **p_blk, TMO_U tmout )
{
	MPLCB	*mplcb;
	void	*blk = NULL;
	ER	ercd = E_OK;

	CHECK_MPLID(mplid);
	CHECK_PAR(blksz > 0 && blksz <= MAX_ALLOCATE);
	CHECK_TMOUT(tmout);
	CHECK_DISPATCH();

	mplcb = get_mplcb(mplid);
	blksz = roundSize(blksz);

	BEGIN_CRITICAL_SECTION;
	if ( mplcb->mplid == 0 ) {
		ercd = E_NOEXS;
		goto error_exit;
	}

#if CHK_PAR
	if ( blksz > mplcb->mplsz ) {
		ercd = E_PAR;
		goto error_exit;
	}
#endif

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

	if ( gcb_top_of_wait_queue((GCB*)mplcb, ctxtsk) == ctxtsk
	  && (blk = get_blk(mplcb, blksz)) != NULL ) {
		/* Get memory block */
		*p_blk = blk;
	} else {
		/* Ready for wait */
		ctxtsk->wspec = ( (mplcb->mplatr & TA_TPRI) != 0 )?
					&wspec_mpl_tpri: &wspec_mpl_tfifo;
		ctxtsk->wercd = &ercd;
		ctxtsk->winfo.mpl.blksz = blksz;
		ctxtsk->winfo.mpl.p_blk = p_blk;
		gcb_make_wait_with_diswai((GCB*)mplcb, tmout);
	}

    error_exit:
	END_CRITICAL_SECTION;

	return ercd;
}
예제 #3
0
SYSCALL ER _tk_rcv_mbx_u( ID mbxid, T_MSG **ppk_msg, TMO_U tmout )
{
	MBXCB	*mbxcb;
	ER	ercd = E_OK;

	CHECK_MBXID(mbxid);
	CHECK_TMOUT(tmout);
	CHECK_DISPATCH();

	mbxcb = get_mbxcb(mbxid);

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

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

	if ( headmsg(mbxcb) != NULL ) {
		/* Get message from head of queue */
		*ppk_msg = headmsg(mbxcb);
		headmsg(mbxcb) = nextmsg(*ppk_msg);
	} else {
		/* Ready for receive wait */
		ctxtsk->wspec = ( (mbxcb->mbxatr & TA_TPRI) != 0 )?
					&wspec_mbx_tpri: &wspec_mbx_tfifo;
		ctxtsk->wercd = &ercd;
		ctxtsk->winfo.mbx.ppk_msg = ppk_msg;
		gcb_make_wait_with_diswai((GCB*)mbxcb, tmout);
	}

    error_exit:
	END_CRITICAL_SECTION;

	return ercd;
}
예제 #4
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;
}
예제 #5
0
파일: rendezvous.c 프로젝트: yuki74w/TRON
/*
 * 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;
}
예제 #6
0
파일: rendezvous.c 프로젝트: yuki74w/TRON
SYSCALL INT _tk_acp_por_u( ID porid, UINT acpptn, RNO *p_rdvno, void *msg, TMO_U tmout )
{
	PORCB	*porcb;
	TCB	*tcb;
	QUEUE	*queue;
	RNO	rdvno;
	INT	cmsgsz;
	ER	ercd = E_OK;

	CHECK_PORID(porid);
	CHECK_PAR(acpptn != 0);
	CHECK_TMOUT(tmout);
	CHECK_DISPATCH();

	porcb = get_porcb(porid);
 
	BEGIN_CRITICAL_SECTION;
	if ( porcb->porid == 0 ) {
		ercd = E_NOEXS;
		goto error_exit;
	}

	/* Search call wait task */
	queue = porcb->call_queue.next;
	while ( queue != &porcb->call_queue ) {
		tcb = (TCB*)queue;
		queue = queue->next;
		if ( (acpptn & tcb->winfo.cal.calptn) == 0 ) {
			continue;
		}

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

		/* Receive message */
		*p_rdvno = rdvno = gen_rdvno(tcb);
		cmsgsz = tcb->winfo.cal.cmsgsz;
		if ( cmsgsz > 0 ) {
			memcpy(msg, tcb->winfo.cal.msg, (UINT)cmsgsz);
		}

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

		/* Make the other task at rendezvous end wait state */
		tcb->wspec = &wspec_rdv;
		tcb->wid = 0;
		tcb->winfo.rdv.rdvno = rdvno;
		tcb->winfo.rdv.msg = tcb->winfo.cal.msg;
		tcb->winfo.rdv.maxrmsz = porcb->maxrmsz;
		tcb->winfo.rdv.p_rmsgsz = tcb->winfo.cal.p_rmsgsz;
		timer_insert(&tcb->wtmeb, TMO_FEVR,
					(CBACK)wait_release_tmout, tcb);
		QueInit(&tcb->tskque);

		goto error_exit;
	}

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

	ercd = E_TMOUT;
	if ( tmout != TMO_POL ) {
		/* Ready for rendezvous accept wait */
		ctxtsk->wspec = &wspec_acp;
		ctxtsk->wid = porid;
		ctxtsk->wercd = &ercd;
		ctxtsk->winfo.acp.acpptn = acpptn;
		ctxtsk->winfo.acp.msg = msg;
		ctxtsk->winfo.acp.p_rdvno = p_rdvno;
		ctxtsk->winfo.acp.p_cmsgsz = &cmsgsz;
		make_wait(tmout, porcb->poratr);
		QueInsert(&ctxtsk->tskque, &porcb->accept_queue);
	}

    error_exit:
	END_CRITICAL_SECTION;

	return ( ercd < E_OK )? ercd: cmsgsz;
}
예제 #7
0
파일: rendezvous.c 프로젝트: yuki74w/TRON
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;
}
예제 #8
0
파일: mutex.c 프로젝트: yuki74w/TRON
SYSCALL ER _tk_loc_mtx_u( ID mtxid, TMO_U tmout )
{
	MTXCB	*mtxcb;
	TCB	*mtxtsk;
	ATR	mtxatr;
	ER	ercd = E_OK;

	CHECK_MTXID(mtxid);
	CHECK_TMOUT(tmout);
	CHECK_DISPATCH();

	mtxcb = get_mtxcb(mtxid);

	BEGIN_CRITICAL_SECTION;
	if ( mtxcb->mtxid == 0 ) {
		ercd = E_NOEXS;
		goto error_exit;
	}
	if ( mtxcb->mtxtsk == ctxtsk ) {
		ercd = E_ILUSE;  /* Multiplexed lock */
		goto error_exit;
	}

	mtxatr = mtxcb->mtxatr & TA_CEILING;
	if ( mtxatr == TA_CEILING ) {
		if ( ctxtsk->bpriority < mtxcb->ceilpri ) {
			/* Violation of highest priority limit */
			ercd = E_ILUSE;
			goto error_exit;
		}
	}

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

	mtxtsk = mtxcb->mtxtsk;
	if ( mtxtsk == NULL ) {
		/* Get lock */
		mtxcb->mtxtsk = ctxtsk;
		mtxcb->mtxlist = ctxtsk->mtxlist;
		ctxtsk->mtxlist = mtxcb;

		if ( mtxatr == TA_CEILING ) {
			if ( ctxtsk->priority > mtxcb->ceilpri ) {
				/* Raise its own task to the highest
				   priority limit */
				change_task_priority(ctxtsk, mtxcb->ceilpri);
			}
		}
	} else {
		ercd = E_TMOUT;
		if ( tmout == TMO_POL ) {
			goto error_exit;
		}

		if ( mtxatr == TA_INHERIT ) {
			if ( mtxtsk->priority > ctxtsk->priority ) {
				/* Raise the priority of task during
				   locking to the same priority as its
				   own task */
				change_task_priority(mtxtsk, ctxtsk->priority);
			}
		}

		/* Ready for wait */
		ctxtsk->wspec = ( mtxatr == TA_TFIFO   )? &wspec_mtx_tfifo:
				( mtxatr == TA_INHERIT )? &wspec_mtx_inherit:
							  &wspec_mtx_tpri;
		ctxtsk->wercd = &ercd;
		ctxtsk->wid = mtxcb->mtxid;
		make_wait(tmout, mtxcb->mtxatr);
		if ( mtxatr == TA_TFIFO ) {
			QueInsert(&ctxtsk->tskque, &mtxcb->wait_queue);
		} else {
			queue_insert_tpri(ctxtsk, &mtxcb->wait_queue);
		}
	}

    error_exit:
	END_CRITICAL_SECTION;

	return ercd;
}