📄 rbufflib.c
字号:
/* rBuffLib.c - dynamic ring buffer (rBuff) library *//* Copyright 1984-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01z,20apr00,max Change tid == NULL to tid == 0 (like in es.coretools)01y,28aug98,dgp FCS man page edit01x,27aug98,dgp add lib description, edit wvRBuffMgrPrioritySet() for manpgs01w,18aug98,cjtc event buffer full handled more gracefully (SPR 22133)01v,22jul98,cjtc optimise ring buffer scheme for windview (SPR 21752) Avoids multiple rBuffMgr tasks (SPR 21805)01u,30jun98,cjtc make priority of rBuffMgr task variable (SPR 21543)01t,06may98,pr fix wrong spell of portWorkQAdd1 for x86.01t,01may98,nps reworked msg passing for rBuff maintenance.01s,26mar98,nps fix 2 buffer / continuous upload problem.01r,25mar98,pr used portable portWorkQAdd1 only for the I80X86. moved portWorkQAdd1 into trgLib.c01q,20mar98,pr replaced workQAdd1 with portable version (for x86).01p,19mar98,nps only give upload threshold semaphore when necessary.01o,13mar98,nps added rBuffVerify.01n,03mar98,nps Source control structures from specfied source partition.01m,21feb98,nps Don't use msgQ fn to pass msgs - it causes problems when used with WV instrumentation.01l,04feb98,nps remove diagnostic messages.01k,03feb98,nps Changed msgQSend option from WAIT_FOREVER to NO_WAIT.01j,12jan98,nps Don't initialise rBuff multiple times.01i,18dec97,cth updated include files, added flushRtn init to rBuffCreate01h,25nov97,nps Tom's fix incorporated. Maintain statistic of peak buffer utilisation. Fix count of empty buffers.01g,16nov97,cth changed every public routine to accept generic buffer id, described in buffer.h, rather than rBuffId. added initialization for generic buffer id in rBuffCreate01f,15Sep97,nps rBuffShow moved out to its own file. SEMAPHOREs now init'd rather than created. added support for 'infinite' extension. added support for RBUFF_WRAPAROUND. buffers for ring are now added and freed by dedicated task.01e,18Aug97,nps fixed counting of emptyBuffs.01d,18Aug97,nps use semBGiveDefer to signal event upload.01c,11Aug97,nps rBuffReset now resets *all* buffers.01b,28jul97,nps further implementation/testing. rBuffReset returns STATUS type. added rBuffSetFd.01a,14jul97,nps written.*//*DESCRIPTIONThis library contains a routine for changing the default priority of the rBuffmanager task.INTERNALThis library also contains the non-public routines creating and managing thedynamic ring buffer. It provides both a WindView-specific version and ageneric version.SEE ALSO: memLib, rngLib,.pG "Basic OS"*/#undef RBUFF_DEBUG#ifndef GENERIC_RBUFF/* * Below this point the WindView specific version of the ring buffer * library. In order to compile with the old (generic version of the * ring buffer, you should use EXTRA_DEFINE='-DGENERIC_RBUFF' in the * make command line, or #define GENERIC_RBUFF at the head of this * file. */#include "vxWorks.h"#include "semLib.h"#include "classLib.h"#include "errno.h"#include "intLib.h"#include "logLib.h"#include "taskLib.h"#include "fioLib.h"#include "rBuffLib.h"#include "private/wvBufferP.h"#include "private/classLibP.h"#include "private/objLibP.h"#include "private/workQLibP.h"#include "stdio.h"#include "string.h"#include "unistd.h"extern int wvRBuffMgr();#if (CPU_FAMILY == I80X86)extern void portWorkQAdd1();#endif/* locals */#if defined(__STDC__) || defined(__cplusplus)LOCAL STATUS rBuffAdd ( RBUFF_ID rBuff, RBUFF_PTR buffToAdd );LOCAL STATUS rBuffFree ( RBUFF_ID rBuff, RBUFF_PTR buffToFree );LOCAL STATUS rBuffHandleEmpty ( RBUFF_ID rBuff );#else /* __STDC__ */LOCAL STATUS rBuffAdd();LOCAL STATUS rBuffFree();LOCAL STATUS rBuffHandleEmpty();#endif /* __STDC__ */extern BOOL kernelState;#if (CPU_FAMILY == I80X86)# define WQADD1 portWorkQAdd1#else /* CPU_FAMILY == I80X86 */# define WQADD1 workQAdd1#endif#define RBUFF_SEND_MSG(RMSG_TYPE,RMSG_PRI,RB_ID,RMSG_PARAM) \ { \ if ((RB_ID)->nestLevel++ == 0) \ { \ BOOL doIt = TRUE ; \ if (RMSG_TYPE == RBUFF_MSG_ADD) \ { \ if ((RB_ID)->msgOutstanding) \ { \ doIt = FALSE; \ } \ (RB_ID)->msgOutstanding = TRUE; \ } \ if (doIt) \ { \ WV_RBUFF_MGR_ID pMgr; \ pMgr = (WV_RBUFF_MGR_ID)(RB_ID)->rBuffMgrId; \ pMgr->msg[pMgr->msgWriteIndex].ringId = (RB_ID); \ pMgr->msg[pMgr->msgWriteIndex].msgType = RMSG_TYPE; \ pMgr->msg[pMgr->msgWriteIndex].arg = (UINT32) RMSG_PARAM; \ \ if(++pMgr->msgWriteIndex > (WV_RBUFF_MGR_MSGQ_MAX - 1)) \ { \ pMgr->msgWriteIndex = 0; \ } \ \ if(kernelState) \ { \ WQADD1 ((FUNCPTR)semCGiveDefer, (int)&pMgr->msgSem); \ } \ else \ { \ semCGiveDefer (&pMgr->msgSem); \ } \ } \ } \ (RB_ID)->nestLevel--; \ }LOCAL BOOL rBuffLibInstalled = FALSE; /* protect from multiple inits *//* global variables */IMPORT BOOL wvEvtBufferFullNotify; /* event buffer full notification */OBJ_CLASS rBuffClass; /* rBuff object Class */CLASS_ID rBuffClassId = &rBuffClass; /* rBuff class ID */WV_RBUFF_MGR_ID wvRBuffMgrId = NULL; /* WV rbuff mgr structure id *//********************************************************************************* rBuffLibInit - initialise the ring of buffers library** This routine initialises the ring of buffers library. If INCLUDE_RBUFF is* defined in configAll.h, it is called by the root task, usrRoot(), in* usrConfig.c.** NOMANUAL** RETURNS: OK, or ERROR if the library could not be initialized.*/STATUS rBuffLibInit (void) { if (rBuffLibInstalled) { return(TRUE); } /* Initialise the WindView rBuff Manager */ if ((wvRBuffMgrId = malloc (sizeof (WV_RBUFF_MGR_TYPE))) == NULL) return (ERROR); wvRBuffMgrId->tid = 0; wvRBuffMgrId->priorityDefault = WV_RBUFF_MGR_PRIORITY; if (semCInit (&wvRBuffMgrId->msgSem, SEM_Q_PRIORITY, 0) == ERROR) { free (wvRBuffMgrId); wvRBuffMgrId = NULL; return (ERROR); } wvRBuffMgrId->msgWriteIndex = 0; wvRBuffMgrId->msgReadIndex = 0; rBuffLibInstalled = TRUE; /* initialize the rBuff class structure */ return (classInit (rBuffClassId, sizeof (RBUFF_TYPE), OFFSET (RBUFF_TYPE, buffDesc), (FUNCPTR) rBuffCreate, (FUNCPTR) NULL, (FUNCPTR) rBuffDestroy)); } /********************************************************************************* rBuffCreate - create an extendable ring of buffers** This routine creates an extendable ring of buffers from* the specified partition.** NOMANUAL*/BUFFER_ID rBuffCreate ( void *Params ) { RBUFF_ID rBuff; UINT32 count; RBUFF_PTR newBuff; rBuffCreateParamsType * rBuffCreateParams = Params; if ((!rBuffLibInstalled) && (rBuffLibInit() == OK)) { rBuffLibInstalled = TRUE; } if (!rBuffLibInstalled) {#ifdef RBUFF_DEBUG logMsg ("rBuff: rBuffLib not installed\n",0,0,0,0,0,0);#endif return (NULL); } /* validate params */ if (rBuffCreateParams->minimum < 2 || ((rBuffCreateParams->minimum > rBuffCreateParams->maximum) || (rBuffCreateParams->maximum < 2 && rBuffCreateParams->maximum != RBUFF_MAX_AVAILABLE)) || rBuffCreateParams->buffSize == 0) {#ifdef RBUFF_DEBUG logMsg ("rBuff: invalid params\n",0,0,0,0,0,0);#endif return (NULL); } /* * Set source partition for object class memory allocation * - note this only works overall if all rBuffs share a source * partition. */ classMemPartIdSet(rBuffClassId, rBuffCreateParams->sourcePartition); /* allocate control structure */ rBuff = (RBUFF_ID) objAlloc (rBuffClassId); if (rBuff == NULL) {#ifdef RBUFF_DEBUG logMsg ("rBuff: objAlloc failed\n",0,0,0,0,0,0);#endif return (NULL); } objCoreInit (&rBuff->buffDesc.objCore, rBuffClassId); /* record parameters */ rBuff->info.srcPart = rBuffCreateParams->sourcePartition; rBuff->info.options = rBuffCreateParams->options; rBuff->info.buffSize = rBuffCreateParams->buffSize; rBuff->info.threshold = rBuffCreateParams->threshold; rBuff->info.minBuffs = rBuffCreateParams->minimum; rBuff->info.maxBuffs = (unsigned int) rBuffCreateParams->maximum; rBuff->errorHandler = rBuffCreateParams->errorHandler; if (semBInit (&rBuff->buffDesc.threshXSem, SEM_Q_PRIORITY, SEM_EMPTY) == ERROR) { objFree (rBuffClassId, (UINT8 *) rBuff); return (NULL); } if (semBInit (&rBuff->readBlk, SEM_Q_PRIORITY, SEM_FULL) == ERROR) { semTerminate (&rBuff->buffDesc.threshXSem); objFree (rBuffClassId, (UINT8 *) rBuff); return (NULL); } if (semBInit (&rBuff->bufferFull, SEM_Q_PRIORITY, SEM_EMPTY) == ERROR) { semTerminate (&rBuff->buffDesc.threshXSem); semTerminate (&rBuff->readBlk); objFree (rBuffClassId, (UINT8 *)rBuff); return (NULL); } if (semCInit (&rBuff->msgSem, SEM_Q_PRIORITY, 0) == ERROR) { semTerminate (&rBuff->bufferFull); semTerminate (&rBuff->buffDesc.threshXSem); semTerminate (&rBuff->readBlk); objFree (rBuffClassId, (UINT8 *)rBuff); return (NULL); } rBuff->rBuffMgrId = 0; /* ...so we can use rBuffDestroy safely */ /* * If things go wrong from here, use rBuffDestroy to throw back what * we've caught. */ /* allocate 'rBuffCreateParams->minimum' buffers */ rBuff->info.currBuffs = rBuff->info.emptyBuffs = 0; rBuff->buffWrite = NULL; for (count=0; count < rBuffCreateParams->minimum; count++) { /* First we need a buffer */ newBuff = (RBUFF_PTR) memPartAlloc (rBuffCreateParams->sourcePartition, sizeof(RBUFF_BUFF_TYPE) + rBuffCreateParams->buffSize);#ifdef RBUFF_DEBUG logMsg ("rBuff: adding buffer %p to ring\n",newBuff,0,0,0,0,0);#endif /* newBuff will be returned as NULL if source partition is exhausted */ /* Don't need to lock ints around rBuffAdd as no-one knows about * this rBuff. */ if ((newBuff == NULL) || (rBuffAdd (rBuff, newBuff) == ERROR)) {#ifdef RBUFF_DEBUG logMsg ("rBuff: abandoned creation\n",0,0,0,0,0,0);#endif rBuffDestroy ((BUFFER_ID) rBuff); return (NULL); } } /* * The first time around, spawn the rBuffMgr task. Once it exists, * don't create another one. It should never be deleted. This bit is * specific to WindView and will need attention for generic buffers */ if (wvRBuffMgrId->tid == 0) { wvRBuffMgrId->tid = taskSpawn ( "tWvRBuffMgr", wvRBuffMgrId->priorityDefault, WV_RBUFF_MGR_OPTIONS, 2048, wvRBuffMgr, (int)wvRBuffMgrId, 0,0,0,0,0,0,0,0,0); } rBuff->rBuffMgrId = (int)wvRBuffMgrId; if (wvRBuffMgrId->tid == 0) {#ifdef RBUFF_DEBUG logMsg ("rBuff: error creating wvRBuffMgr\n",0,0,0,0,0,0);#endif rBuffDestroy ((BUFFER_ID) rBuff); return (NULL); } /* set control pointers */ rBuff->nestLevel = 0; /* rBuff->buffWrite initialised by rBuffAdd */ rBuff->buffRead = rBuff->buffWrite; rBuff->dataWrite = rBuff->dataRead = rBuff->buffWrite->dataStart; /* reset info */ rBuff->info.maxBuffsActual = rBuffCreateParams->minimum; rBuff->info.dataContent = rBuff->info.writesSinceReset = rBuff->info.readsSinceReset = rBuff->info.timesExtended = rBuff->info.timesXThreshold = rBuff->info.bytesWritten = rBuff->info.bytesRead = rBuff->info.bytesPeak = 0; /* Reset msg passing mechanism */ rBuff->msgOutstanding = FALSE; rBuff->msgWriteIndex = rBuff->msgReadIndex = 0; /* now set up func ptrs allowing it to be called */ rBuff->buffDesc.readReserveRtn = (FUNCPTR) rBuffReadReserve; rBuff->buffDesc.readCommitRtn = (FUNCPTR) rBuffReadCommit; rBuff->buffDesc.writeRtn = rBuffWrite; rBuff->buffDesc.flushRtn = rBuffFlush; rBuff->buffDesc.threshold = rBuffCreateParams->threshold; rBuff->buffDesc.nBytesRtn = rBuffNBytes; /* made it! */#ifdef RBUFF_DEBUG logMsg("Created rBuff with ID %p\n",rBuff,0,0,0,0,0);#endif return ((BUFFER_ID) rBuff); }int rBuffVerify ( BUFFER_ID rBuff
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -