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

📄 mailbox.c

📁 日本著名的的嵌入式实时操作系统T-Kernel的源码及用户手册。
💻 C
字号:
/* *---------------------------------------------------------------------- *    T-Kernel * *    Copyright (C) 2004 by Ken Sakamura. All rights reserved. *    T-Kernel is distributed under the T-License. *---------------------------------------------------------------------- * *    Version:   1.01.00 *    Released by T-Engine Forum(http://www.t-engine.org) at 2004/6/28. * *---------------------------------------------------------------------- *//* *	mailbox.c (T-Kernel/OS) *	Mailbox */#include "kernel.h"#include "task.h"#include "wait.h"#include "check.h"#ifdef NUM_MBXIDEXPORT ID	max_mbxid;	/* Maximum mailbox ID *//* * Mailbox control block * *	'mq_head' is the first message queue pointer that *	points a message. *	It is NULL if the message queue is empty. *	'mq_tail' is a pointer that points end of message *	queue that is not empty. *	The message queue value is not guaranteed if the *	message queue is empty. *	It is used only if the message queue is FIFO (TA_MFIFO). */typedef struct mailbox_control_block {	QUEUE	wait_queue;	/* Mailbox wait queue*/	ID	mbxid;		/* Mailbox ID */	VP	exinf;		/* Extended information */	ATR	mbxatr;		/* Mailbox attribute */	T_MSG	mq_head;	/* Head of message queue */	T_MSG	*mq_tail;	/* End of message queue */#if USE_OBJECT_NAME	UB	name[OBJECT_NAME_LENGTH];	/* name */#endif} MBXCB;LOCAL MBXCB	*mbxcb_table;	/* Mailbox control block */LOCAL QUEUE	free_mbxcb;	/* FreeQue */#define get_mbxcb(id)	( &mbxcb_table[INDEX_MBX(id)] )/* * Initialization of mailbox control block  */EXPORT ER mailbox_initialize( void ){	MBXCB	*mbxcb, *end;	W	n;	/* Get system information */	n = _tk_get_cfn("TMaxMbxId", &max_mbxid, 1);	if ( n < 1 || NUM_MBXID < 1 ) return E_SYS;	/* Create mailbox control block */	mbxcb_table = Imalloc(NUM_MBXID * sizeof(MBXCB));	if ( mbxcb_table == NULL ) return E_NOMEM;	/* Register all control blocks onto FreeQue */	QueInit(&free_mbxcb);	end = mbxcb_table + NUM_MBXID;	for ( mbxcb = mbxcb_table; mbxcb < end; mbxcb++ ) {		mbxcb->mbxid = 0;		QueInsert(&mbxcb->wait_queue, &free_mbxcb);	}	return E_OK;}/* * Head message */#define	headmsg(mbxcb)	( (T_MSG*)(mbxcb)->mq_head.msgque[0] )/* * Next message */#define nextmsg(msg)	( (T_MSG*)((T_MSG*)msg)->msgque[0] )/* * Insert a message queue following priority */Inline void queue_insert_mpri( T_MSG_PRI *pk_msg, T_MSG *head ){	T_MSG_PRI	*msg;	T_MSG		*prevmsg = head;	while ( (msg = (T_MSG_PRI*)nextmsg(prevmsg)) != NULL ) {		if ( msg->msgpri > pk_msg->msgpri ) break;		prevmsg = (T_MSG*)msg;	}	nextmsg(pk_msg) = msg;	nextmsg(prevmsg) = pk_msg;}/* * Processing if the priority of wait task changes */LOCAL void mbx_chg_pri( TCB *tcb, INT oldpri ){	MBXCB	*mbxcb;	mbxcb = get_mbxcb(tcb->wid);	gcb_change_priority((GCB*)mbxcb, tcb);}/* * Definition of mailbox wait specification */LOCAL WSPEC wspec_mbx_tfifo = { TTW_MBX, NULL, NULL };LOCAL WSPEC wspec_mbx_tpri  = { TTW_MBX, mbx_chg_pri, NULL };/* * Create mailbox */SYSCALL ID _tk_cre_mbx( T_CMBX *pk_cmbx ){	const ATR VALID_MBXATR = {		 TA_MPRI		|TA_TPRI		|TA_NODISWAI#if USE_OBJECT_NAME		|TA_DSNAME#endif	};	MBXCB	*mbxcb;	ID	mbxid;	ER	ercd;	CHECK_RSATR(pk_cmbx->mbxatr, VALID_MBXATR);	BEGIN_CRITICAL_SECTION;	/* Get control block from FreeQue */	mbxcb = (MBXCB*)QueRemoveNext(&free_mbxcb);	if ( mbxcb == NULL ) {		ercd = E_LIMIT;	} else {		mbxid = ID_MBX(mbxcb - mbxcb_table);		/* Initialize control block */		QueInit(&mbxcb->wait_queue);		mbxcb->mbxid  = mbxid;		mbxcb->exinf  = pk_cmbx->exinf;		mbxcb->mbxatr = pk_cmbx->mbxatr;		mbxcb->mq_head.msgque[0] = NULL;#if USE_OBJECT_NAME		if ( (pk_cmbx->mbxatr & TA_DSNAME) != 0 ) {			strncpy(mbxcb->name, pk_cmbx->dsname,				OBJECT_NAME_LENGTH);		}#endif		ercd = mbxid;	}	END_CRITICAL_SECTION;	return ercd;}/* * Delete mailbox */SYSCALL ER _tk_del_mbx( ID mbxid ){	MBXCB	*mbxcb;	ER	ercd = E_OK;	CHECK_MBXID(mbxid);	mbxcb = get_mbxcb(mbxid);	BEGIN_CRITICAL_SECTION;	if ( mbxcb->mbxid == 0 ) {		ercd = E_NOEXS;	} else {		/* Release wait state of task (E_DLT) */		wait_delete(&mbxcb->wait_queue);		/* Return to FreeQue */		QueInsert(&mbxcb->wait_queue, &free_mbxcb);		mbxcb->mbxid = 0;	}	END_CRITICAL_SECTION;	return ercd;}/* * 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 ( !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;}/* * Receive from mailbox */SYSCALL ER _tk_rcv_mbx( ID mbxid, T_MSG **ppk_msg, TMO 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;	}	if ( headmsg(mbxcb) != NULL ) {		/* Check receive wait disable */		if ( is_diswai((GCB*)mbxcb, ctxtsk, TTW_MBX) ) {			ercd = E_DISWAI;			goto error_exit;		}		/* 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;}/* * Refer mailbox state  */SYSCALL ER _tk_ref_mbx( ID mbxid, T_RMBX *pk_rmbx ){	MBXCB	*mbxcb;	ER	ercd = E_OK;	CHECK_MBXID(mbxid);	mbxcb = get_mbxcb(mbxid);	BEGIN_CRITICAL_SECTION;	if ( mbxcb->mbxid == 0 ) {		ercd = E_NOEXS;	} else {		pk_rmbx->exinf = mbxcb->exinf;		pk_rmbx->wtsk = wait_tskid(&mbxcb->wait_queue);		if ( headmsg(mbxcb) != NULL ) {			pk_rmbx->pk_msg = headmsg(mbxcb);		} else {			pk_rmbx->pk_msg = NULL; /* No message */		}	}	END_CRITICAL_SECTION;	return ercd;}/* ------------------------------------------------------------------------ *//* *	Debugger support function */#if USE_DBGSPT/* * Get object name from control block */#if USE_OBJECT_NAMEEXPORT ER mailbox_getname(ID id, UB **name){	MBXCB	*mbxcb;	ER	ercd = E_OK;	CHECK_MBXID(id);	BEGIN_DISABLE_INTERRUPT;	mbxcb = get_mbxcb(id);	if ( mbxcb->mbxid == 0 ) {		ercd = E_NOEXS;		goto error_exit;	}	if ( (mbxcb->mbxatr & TA_DSNAME) == 0 ) {		ercd = E_OBJ;		goto error_exit;	}	*name = mbxcb->name;    error_exit:	END_DISABLE_INTERRUPT;	return ercd;}#endif /* USE_OBJECT_NAME *//* * Refer mailbox usage state */SYSCALL INT _td_lst_mbx( ID list[], INT nent ){	MBXCB	*mbxcb, *end;	INT	n = 0;	BEGIN_DISABLE_INTERRUPT;	end = mbxcb_table + NUM_MBXID;	for ( mbxcb = mbxcb_table; mbxcb < end; mbxcb++ ) {		if ( mbxcb->mbxid == 0 ) continue;		if ( n++ < nent ) {			*list++ = mbxcb->mbxid;		}	}	END_DISABLE_INTERRUPT;	return n;}/* * Refer mailbox state */SYSCALL ER _td_ref_mbx( ID mbxid, TD_RMBX *pk_rmbx ){	MBXCB	*mbxcb;	ER	ercd = E_OK;	CHECK_MBXID(mbxid);	mbxcb = get_mbxcb(mbxid);	BEGIN_DISABLE_INTERRUPT;	if ( mbxcb->mbxid == 0 ) {		ercd = E_NOEXS;	} else {		pk_rmbx->exinf = mbxcb->exinf;		pk_rmbx->wtsk = wait_tskid(&mbxcb->wait_queue);		if ( headmsg(mbxcb) != NULL ) {			pk_rmbx->pk_msg = headmsg(mbxcb);		} else {			pk_rmbx->pk_msg = NULL; /* No message */		}	}	END_DISABLE_INTERRUPT;	return ercd;}/* * Refer mailbox wait queue */SYSCALL INT _td_mbx_que( ID mbxid, ID list[], INT nent ){	MBXCB	*mbxcb;	QUEUE	*q;	ER	ercd = E_OK;	CHECK_MBXID(mbxid);	mbxcb = get_mbxcb(mbxid);	BEGIN_DISABLE_INTERRUPT;	if ( mbxcb->mbxid == 0 ) {		ercd = E_NOEXS;	} else {		INT n = 0;		for ( q = mbxcb->wait_queue.next; q != &mbxcb->wait_queue;							q = q->next ) {			if ( n++ < nent ) {				*list++ = ((TCB*)q)->tskid;			}		}		ercd = n;	}	END_DISABLE_INTERRUPT;	return ercd;}#endif /* USE_DBGSPT */#endif /* NUM_MBXID */

⌨️ 快捷键说明

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