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

📄 messagebuf.c

📁 uT Kernel os source code for AT91
💻 C
字号:
/* *---------------------------------------------------------------------- *    micro T-Kernel * *    Copyright (C) 2006-2007 by Ken Sakamura. All rights reserved. *    micro T-Kernel is distributed under the micro T-License. *---------------------------------------------------------------------- * *    Version:   1.00.00 *    Released by T-Engine Forum(http://www.t-engine.org) at 2007/03/26. * *---------------------------------------------------------------------- *//* *	messagebuf.c *	Message Buffer *//** [BEGIN Common Definitions] */#include "kernel.h"#include "task.h"#include "wait.h"#include "check.h"#include "messagebuf.h"/** [END Common Definitions] */#if CFN_MAX_MBFID > 0#ifdef USE_FUNC_MBFCB_TABLENoinit(EXPORT MBFCB knl_mbfcb_table[NUM_MBFID]);	/* Message buffer control block */Noinit(EXPORT QUEUE knl_free_mbfcb);	/* FreeQue */#endif /* USE_FUNC_MBFCB_TABLE */#ifdef USE_FUNC_MESSAGEBUFFER_INITIALIZE/* * Initialization of message buffer control block  */EXPORT ER knl_messagebuffer_initialize( void ){	MBFCB	*mbfcb, *end;	/* Get system information */	if ( NUM_MBFID < 1 ) {		return E_SYS;	}	/* Register all control blocks onto FreeQue */	QueInit(&knl_free_mbfcb);	end = knl_mbfcb_table + NUM_MBFID;	for ( mbfcb = knl_mbfcb_table; mbfcb < end; mbfcb++ ) {		mbfcb->mbfid = 0;		QueInsert(&mbfcb->send_queue, &knl_free_mbfcb);	}	return E_OK;}#endif /* USE_FUNC_MESSAGEBUFFER_INITIALIZE *//* ------------------------------------------------------------------------ */#ifdef USE_FUNC_MSG_TO_MBF/* * Store the message to message buffer. */EXPORT void knl_msg_to_mbf( MBFCB *mbfcb, VP msg, INT msgsz ){	W	tail = mbfcb->tail;	VB	*buffer = mbfcb->buffer;	W	remsz;	mbfcb->frbufsz -= (W)(HEADERSZ + ROUNDSZ(msgsz));	*(HEADER*)&buffer[tail] = msgsz;	tail += HEADERSZ;	if ( tail >= mbfcb->bufsz ) {		tail = 0;	}	if ( (remsz = mbfcb->bufsz - tail) < (W)msgsz ) {		memcpy(&buffer[tail], msg, (size_t)remsz);		msg = (VB*)msg + remsz;		msgsz -= (INT)remsz;		tail = 0;	}	memcpy(&buffer[tail], msg, (size_t)msgsz);	tail += (W)ROUNDSZ(msgsz);	if ( tail >= mbfcb->bufsz ) {		tail = 0;	}	mbfcb->tail = tail;}#endif /* USE_FUNC_MSG_TO_MBF *//* ------------------------------------------------------------------------ */#ifdef USE_FUNC_MBF_WAKEUP/* * Accept message and release wait task, * as long as there are free message area. */EXPORT void knl_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 ( !knl_mbf_free(mbfcb, msgsz) ) {			break;		}		/* Store a message from waiting task and release it */		knl_msg_to_mbf(mbfcb, top->winfo.smbf.msg, msgsz);		knl_wait_release_ok(top);	}}#endif /* USE_FUNC_MBF_WAKEUP */#ifdef USE_FUNC_TK_CRE_MBF/* * Create message buffer */SYSCALL ID tk_cre_mbf_impl( T_CMBF *pk_cmbf ){	const ATR VALID_MBFATR = {		 TA_TPRI		|TA_USERBUF#if USE_OBJECT_NAME		|TA_DSNAME#endif	};	MBFCB	*mbfcb;	ID	mbfid;	W	bufsz;	VB	*msgbuf;	ER	ercd;	CHECK_RSATR(pk_cmbf->mbfatr, VALID_MBFATR);	CHECK_PAR(pk_cmbf->bufsz >= 0);	CHECK_PAR(pk_cmbf->maxmsz > 0);#if !USE_IMALLOC	/* TA_USERBUF must be specified if configured in no Imalloc */	CHECK_PAR((pk_cmbf->mbfatr & TA_USERBUF) != 0);#endif	bufsz = (W)ROUNDSZ(pk_cmbf->bufsz);	if ( bufsz > 0 ) {#if USE_IMALLOC		if ( (pk_cmbf->mbfatr & TA_USERBUF) != 0 ) {			/* Size of user buffer must be multiples of sizeof(HEADER) */			if ( bufsz != pk_cmbf->bufsz ) {				return E_PAR;			}			/* Use user buffer */			msgbuf = (VB*) pk_cmbf->bufptr;		} else {			/* Allocate by kernel */			msgbuf = knl_Imalloc((UW)bufsz);			if ( msgbuf == NULL ) {				return E_NOMEM;			}		}#else		/* Size of user buffer must be multiples of sizeof(HEADER) */		if ( bufsz != pk_cmbf->bufsz ) {			return E_PAR;		}		/* Use user buffer */		msgbuf = (VB*) pk_cmbf->bufptr;#endif	} else {		msgbuf = NULL;	}	BEGIN_CRITICAL_SECTION;	/* Get control block from FreeQue */	mbfcb = (MBFCB*)QueRemoveNext(&knl_free_mbfcb);	if ( mbfcb == NULL ) {		ercd = E_LIMIT;	} else {		mbfid = ID_MBF(mbfcb - knl_mbfcb_table);		/* Initialize control block */		QueInit(&mbfcb->send_queue);		mbfcb->mbfid = mbfid;		mbfcb->exinf = pk_cmbf->exinf;		mbfcb->mbfatr = pk_cmbf->mbfatr;		QueInit(&mbfcb->recv_queue);		mbfcb->buffer = msgbuf;		mbfcb->bufsz = mbfcb->frbufsz = bufsz;		mbfcb->maxmsz = pk_cmbf->maxmsz;		mbfcb->head = mbfcb->tail = 0;#if USE_OBJECT_NAME		if ( (pk_cmbf->mbfatr & TA_DSNAME) != 0 ) {			strncpy((char*)mbfcb->name, (char*)pk_cmbf->dsname,				OBJECT_NAME_LENGTH);		}#endif		ercd = mbfid;	}	END_CRITICAL_SECTION;#if USE_IMALLOC	if ( (ercd < E_OK) && (msgbuf != NULL) && ((pk_cmbf->mbfatr & TA_USERBUF) == 0 ) ) {		knl_Ifree(msgbuf);	}#endif	return ercd;}#endif /* USE_FUNC_TK_CRE_MBF */#ifdef USE_FUNC_TK_DEL_MBF/* * Delete message buffer */SYSCALL ER tk_del_mbf_impl( ID mbfid ){	MBFCB	*mbfcb;	VB	*msgbuf = NULL;	ER	ercd = E_OK;	CHECK_MBFID(mbfid);	mbfcb = get_mbfcb(mbfid);	BEGIN_CRITICAL_SECTION;	if ( mbfcb->mbfid == 0 ) {		ercd = E_NOEXS;	} else {		msgbuf = mbfcb->buffer;		/* Release wait state of task (E_DLT) */		knl_wait_delete(&mbfcb->recv_queue);		knl_wait_delete(&mbfcb->send_queue);		/* Return to FreeQue */		QueInsert(&mbfcb->send_queue, &knl_free_mbfcb);		mbfcb->mbfid = 0;	}	END_CRITICAL_SECTION;#if USE_IMALLOC	if ( msgbuf != NULL && ((mbfcb->mbfatr & TA_USERBUF) == 0 ) ) {		knl_Ifree(msgbuf);	}#endif	return ercd;}#endif /* USE_FUNC_TK_DEL_MBF */#ifdef USE_FUNC_TK_SND_MBF/* * Processing if the priority of wait task changes */LOCAL void knl_mbf_chg_pri( TCB *tcb, INT oldpri ){	MBFCB	*mbfcb;	mbfcb = get_mbfcb(tcb->wid);	if ( oldpri >= 0 ) {		/* Reorder wait queue */		knl_gcb_change_priority((GCB*)mbfcb, tcb);	}	/* If the new head task in a send wait queue is able to sent, 	   send its message */	knl_mbf_wakeup(mbfcb);}/* * Processing if the wait task is released */LOCAL void knl_mbf_rel_wai( TCB *tcb ){	knl_mbf_chg_pri(tcb, -1);}/* * Definition of message buffer wait specification */LOCAL WSPEC knl_wspec_smbf_tfifo = { TTW_SMBF, NULL,	knl_mbf_rel_wai };LOCAL WSPEC knl_wspec_smbf_tpri  = { TTW_SMBF, knl_mbf_chg_pri,	knl_mbf_rel_wai };/* * Send to message buffer */SYSCALL ER tk_snd_mbf_impl( ID mbfid, VP msg, INT msgsz, TMO 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	if ( !isQueEmpty(&mbfcb->recv_queue) ) {		/* Send directly to the receive wait task */		tcb = (TCB*)mbfcb->recv_queue.next;		memcpy(tcb->winfo.rmbf.msg, msg, (size_t)msgsz);		*tcb->winfo.rmbf.p_msgsz = msgsz;		knl_wait_release_ok(tcb);	} else if ( (in_indp() || knl_gcb_top_of_wait_queue((GCB*)mbfcb, knl_ctxtsk) == knl_ctxtsk)		  &&(knl_mbf_free(mbfcb, msgsz)) ) {		/* Store the message to message buffer */		knl_msg_to_mbf(mbfcb, msg, msgsz);	} else {		ercd = E_TMOUT;		if ( tmout != TMO_POL ) {			/* Ready for send wait */			knl_ctxtsk->wspec = ( (mbfcb->mbfatr & TA_TPRI) != 0 )?					&knl_wspec_smbf_tpri: &knl_wspec_smbf_tfifo;			knl_ctxtsk->wercd = &ercd;			knl_ctxtsk->winfo.smbf.msg = msg;			knl_ctxtsk->winfo.smbf.msgsz = msgsz;			knl_gcb_make_wait((GCB*)mbfcb, tmout);		}	}    error_exit:	END_CRITICAL_SECTION;	return ercd;}#endif /* USE_FUNC_TK_SND_MBF */#ifdef USE_FUNC_TK_RCV_MBFLOCAL WSPEC knl_wspec_rmbf       = { TTW_RMBF, NULL,	NULL	    };/* * Get a message from message buffer. * Return the message size. */LOCAL INT knl_mbf_to_msg( MBFCB *mbfcb, VP msg ){	W	head = mbfcb->head;	VB	*buffer = mbfcb->buffer;	INT	msgsz, actsz;	W	remsz;	actsz = msgsz = *(HEADER*)&buffer[head];	mbfcb->frbufsz += (W)(HEADERSZ + ROUNDSZ(msgsz));	head += (W)HEADERSZ;	if ( head >= mbfcb->bufsz ) {		head = 0;	}	if ( (remsz = mbfcb->bufsz - head) < (W)msgsz ) {		memcpy(msg, &buffer[head], (size_t)remsz);		msg = (VB*)msg + remsz;		msgsz -= (INT)remsz;		head = 0;	}	memcpy(msg, &buffer[head], (size_t)msgsz);	head += (INT)ROUNDSZ(msgsz);	if ( head >= mbfcb->bufsz ) {		head = 0;	}	mbfcb->head = head;	return actsz;}/* * Receive from message buffer */SYSCALL INT tk_rcv_mbf_impl( ID mbfid, VP msg, TMO 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;	}	if ( !knl_mbf_empty(mbfcb) ) {		/* Read from message buffer */		rcvsz = knl_mbf_to_msg(mbfcb, msg);		/* Accept message from sending task(s) */		knl_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, (size_t)rcvsz);		knl_wait_release_ok(tcb);	} else {		ercd = E_TMOUT;		if ( tmout != TMO_POL ) {			/* Ready for receive wait */			knl_ctxtsk->wspec = &knl_wspec_rmbf;			knl_ctxtsk->wid = mbfid;			knl_ctxtsk->wercd = &ercd;			knl_ctxtsk->winfo.rmbf.msg = msg;			knl_ctxtsk->winfo.rmbf.p_msgsz = &rcvsz;			knl_make_wait(tmout, mbfcb->mbfatr);			QueInsert(&knl_ctxtsk->tskque, &mbfcb->recv_queue);		}	}    error_exit:	END_CRITICAL_SECTION;	return ( ercd < E_OK )? ercd: rcvsz;}#endif /* USE_FUNC_TK_RCV_MBF */#ifdef USE_FUNC_TK_REF_MBF/* * Refer message buffer state */SYSCALL ER tk_ref_mbf_impl( ID mbfid, T_RMBF *pk_rmbf ){	MBFCB	*mbfcb;	ER	ercd = E_OK;	CHECK_MBFID(mbfid);	mbfcb = get_mbfcb(mbfid);	BEGIN_CRITICAL_SECTION;	if ( mbfcb->mbfid == 0 ) {		ercd = E_NOEXS;	} else {		pk_rmbf->exinf = mbfcb->exinf;		pk_rmbf->wtsk = knl_wait_tskid(&mbfcb->recv_queue);		pk_rmbf->stsk = knl_wait_tskid(&mbfcb->send_queue);		pk_rmbf->msgsz = knl_mbf_empty(mbfcb)? 0:				*(HEADER*)&mbfcb->buffer[mbfcb->head];		pk_rmbf->frbufsz = mbfcb->frbufsz;		pk_rmbf->maxmsz = mbfcb->maxmsz;	}	END_CRITICAL_SECTION;	return ercd;}#endif /* USE_FUNC_TK_REF_MBF *//* ------------------------------------------------------------------------ *//* *	Debugger support function */#if USE_DBGSPT#ifdef USE_FUNC_MESSAGEBUFFER_GETNAME#if USE_OBJECT_NAME/* * Get object name from control block */EXPORT ER knl_messagebuffer_getname(ID id, UB **name){	MBFCB	*mbfcb;	ER	ercd = E_OK;	CHECK_MBFID(id);	BEGIN_DISABLE_INTERRUPT;	mbfcb = get_mbfcb(id);	if ( mbfcb->mbfid == 0 ) {		ercd = E_NOEXS;		goto error_exit;	}	if ( (mbfcb->mbfatr & TA_DSNAME) == 0 ) {		ercd = E_OBJ;		goto error_exit;	}	*name = mbfcb->name;    error_exit:	END_DISABLE_INTERRUPT;	return ercd;}#endif /* USE_OBJECT_NAME */#endif /* USE_FUNC_MESSAGEBUFFER_GETNAME */#ifdef USE_FUNC_TD_LST_MBF/* * Refer message buffer usage state */SYSCALL INT td_lst_mbf_impl( ID list[], INT nent ){	MBFCB	*mbfcb, *end;	INT	n = 0;	BEGIN_DISABLE_INTERRUPT;	end = knl_mbfcb_table + NUM_MBFID;	for ( mbfcb = knl_mbfcb_table; mbfcb < end; mbfcb++ ) {		if ( mbfcb->mbfid == 0 ) {			continue;		}		if ( n++ < nent ) {			*list++ = mbfcb->mbfid;		}	}	END_DISABLE_INTERRUPT;	return n;}#endif /* USE_FUNC_TD_LST_MBF */#ifdef USE_FUNC_TD_REF_MBF/* * Refer message buffer state */SYSCALL ER td_ref_mbf_impl( ID mbfid, TD_RMBF *pk_rmbf ){	MBFCB	*mbfcb;	ER	ercd = E_OK;	CHECK_MBFID(mbfid);	mbfcb = get_mbfcb(mbfid);	BEGIN_DISABLE_INTERRUPT;	if ( mbfcb->mbfid == 0 ) {		ercd = E_NOEXS;	} else {		pk_rmbf->exinf = mbfcb->exinf;		pk_rmbf->wtsk = knl_wait_tskid(&mbfcb->recv_queue);		pk_rmbf->stsk = knl_wait_tskid(&mbfcb->send_queue);		pk_rmbf->msgsz = knl_mbf_empty(mbfcb)? 0:				*(HEADER*)&mbfcb->buffer[mbfcb->head];		pk_rmbf->frbufsz = mbfcb->frbufsz;		pk_rmbf->maxmsz = mbfcb->maxmsz;	}	END_DISABLE_INTERRUPT;	return ercd;}#endif /* USE_FUNC_TD_REF_MBF */#ifdef USE_FUNC_TD_SMBF_QUE/* * Refer message buffer send wait queue */SYSCALL INT td_smbf_que_impl( ID mbfid, ID list[], INT nent ){	MBFCB	*mbfcb;	QUEUE	*q;	ER	ercd = E_OK;	CHECK_MBFID(mbfid);	mbfcb = get_mbfcb(mbfid);	BEGIN_DISABLE_INTERRUPT;	if ( mbfcb->mbfid == 0 ) {		ercd = E_NOEXS;	} else {		INT n = 0;		for ( q = mbfcb->send_queue.next; q != &mbfcb->send_queue; q = q->next ) {			if ( n++ < nent ) {				*list++ = ((TCB*)q)->tskid;			}		}		ercd = n;	}	END_DISABLE_INTERRUPT;	return ercd;}#endif /* USE_FUNC_TD_SMBF_QUE */#ifdef USE_FUNC_TD_RMBF_QUE/* * Refer message buffer receive wait queue */SYSCALL INT td_rmbf_que_impl( ID mbfid, ID list[], INT nent ){	MBFCB	*mbfcb;	QUEUE	*q;	ER	ercd = E_OK;	CHECK_MBFID(mbfid);	mbfcb = get_mbfcb(mbfid);	BEGIN_DISABLE_INTERRUPT;	if ( mbfcb->mbfid == 0 ) {		ercd = E_NOEXS;	} else {		INT n = 0;		for ( q = mbfcb->recv_queue.next; q != &mbfcb->recv_queue; q = q->next ) {			if ( n++ < nent ) {				*list++ = ((TCB*)q)->tskid;			}		}		ercd = n;	}	END_DISABLE_INTERRUPT;	return ercd;}#endif /* USE_FUNC_TD_RMBF_QUE */#endif /* USE_DBGSPT */#endif /* CFN_MAX_MBFID */

⌨️ 快捷键说明

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