⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rendezvous.c

📁 T-Engine源代码 基于ARM9平台
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *---------------------------------------------------------------------- *    T-Kernel * *    Copyright (C) 2004-2008 by Ken Sakamura. All rights reserved. *    T-Kernel is distributed under the T-License. *---------------------------------------------------------------------- * *    Version:   1.02.04 *    Released by T-Engine Forum(http://www.t-engine.org) at 2008/02/29. * *---------------------------------------------------------------------- *//* *	rendezvous.c (T-Kernel/OS) *	Rendezvous */#include "kernel.h"#include "task.h"#include "wait.h"#include "check.h"#include <sys/rominfo.h>#ifdef NUM_PORIDEXPORT ID	max_porid;	/* Maximum rendezvous port ID *//* * Rendezvous port control block */typedef struct port_control_block {	QUEUE	call_queue;	/* Port call wait queue */	ID	porid;		/* Port ID */	VP	exinf;		/* Extended information */	ATR	poratr;		/* Port attribute */	QUEUE	accept_queue;	/* Port accept wait queue */	INT	maxcmsz;	/* Maximum length of call message */	INT	maxrmsz;	/* Maximum length of reply message */#if USE_OBJECT_NAME	UB	name[OBJECT_NAME_LENGTH];	/* name */#endif} PORCB;LOCAL PORCB	*porcb_table;	/* Rendezvous port control block */LOCAL QUEUE	free_porcb;	/* FreeQue */#define get_porcb(id)	( &porcb_table[INDEX_POR(id)] )/*  * Initialization of port control block  */EXPORT ER rendezvous_initialize( void ){	PORCB	*porcb, *end;	W	n;	/* Get system information */	n = _tk_get_cfn(SCTAG_TMAXPORID, &max_porid, 1);	if ( n < 1 || NUM_PORID < 1 ) {		return E_SYS;	}	/* Create port control block */	porcb_table = Imalloc((UINT)NUM_PORID * sizeof(PORCB));	if ( porcb_table == NULL ) {		return E_NOMEM;	}	/* Register all control blocks onto FeeQue */	QueInit(&free_porcb);	end = porcb_table + NUM_PORID;	for ( porcb = porcb_table; porcb < end; porcb++ ) {		porcb->porid = 0;		QueInsert(&porcb->call_queue, &free_porcb);	}	return E_OK;}#define RDVNO_SHIFT	16/* * Create rendezvous number */Inline RNO gen_rdvno( TCB *tcb ){	RNO	rdvno;	rdvno = tcb->wrdvno;	tcb->wrdvno += (1 << RDVNO_SHIFT);	return rdvno;}/* * Get task ID from rendezvous number  */Inline ID get_tskid_rdvno( RNO rdvno ){	return (ID)((UINT)rdvno & ((1 << RDVNO_SHIFT) - 1));}/* * Check validity of rendezvous number */#define CHECK_RDVNO(rdvno) {					\	if ( !CHK_TSKID(get_tskid_rdvno(rdvno)) ) {		\		return E_OBJ;					\	}							\}/* * Processing if the priority of send wait task changes */LOCAL void cal_chg_pri( TCB *tcb, INT oldpri ){	PORCB	*porcb;	porcb = get_porcb(tcb->wid);	gcb_change_priority((GCB*)porcb, tcb);}/* * Definition of rendezvous wait specification */LOCAL WSPEC wspec_cal_tfifo = { TTW_CAL, NULL, NULL };LOCAL WSPEC wspec_cal_tpri  = { TTW_CAL, cal_chg_pri, NULL };LOCAL WSPEC wspec_acp       = { TTW_ACP, NULL, NULL };LOCAL WSPEC wspec_rdv       = { TTW_RDV, NULL, NULL };/* * Create rendezvous port */SYSCALL ID _tk_cre_por( 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;}/* * Delete rendezvous port */SYSCALL ER _tk_del_por( 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) */		wait_delete(&porcb->call_queue);		wait_delete(&porcb->accept_queue);		/* Return to FreeQue */		QueInsert(&porcb->call_queue, &free_porcb);		porcb->porid = 0;	}	END_CRITICAL_SECTION;	return ercd;}/* * Call rendezvous */SYSCALL INT _tk_cal_por( ID porid, UW calptn, VP msg, INT cmsgsz, TMO 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;}/* * Accept rendezvous */SYSCALL INT _tk_acp_por( ID porid, UINT acpptn, RNO *p_rdvno, VP msg, TMO 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,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -