📄 rbufflib.c
字号:
) { if (OBJ_VERIFY (rBuff, rBuffClassId) == OK) /* validate rBuff ID */ { return (OK); } else { return (ERROR); } }/********************************************************************************* rBuffWrite - Write data to a ring of buffers** This routine writes data to an extendable ring of buffers. If the existing* structure is full, and the existing number of buffers is less than the* specified minimum, then this function will attempt to add another buffer to* the ring.** This function may be called from interrupt level.** Mutually exclusive access must be guaranteed by the caller.** NOMANUAL*/UINT8* rBuffWrite ( BUFFER_ID buffId, /* ring buffer id */ UINT8 * pDummy, /* not used for WV ring buffer */ UINT32 numOfBytes /* number of bytes to reserve */ ) { BOOL startUploading; RBUFF_ID rBuff; /* access this particular rBuff */ UINT8 *returnPtr = (UINT8 *) ~0; /* Return a non-zero value if OK */ /* Get access to the private members of this buffer's descriptor. */ rBuff = (RBUFF_ID) buffId; /* Get out early if this request makes no sense. */ if (numOfBytes > rBuff->info.buffSize) { return (NULL); } /* Critical Region Start */ if (rBuff->info.dataContent >= rBuff->info.threshold) { startUploading = TRUE; } else { startUploading = FALSE; } if (rBuff->buffWrite->spaceAvail >= numOfBytes) { /* Record the start of the reserved area */ returnPtr = rBuff->dataWrite; /* * If we are consuming one of our precious empty buffs, * check we have enough in reserve. */ if (rBuff->buffWrite->dataLen == 0) { --rBuff->info.emptyBuffs; } if (rBuff->info.emptyBuffs < RBUFF_EMPTY_KEEP && rBuff->info.currBuffs != rBuff->info.maxBuffs) { /* Schedule the rBuff Mgr to extend the buffer */ RBUFF_SEND_MSG (RBUFF_MSG_ADD, MSG_PRI_URGENT, rBuff, 0); } rBuff->buffWrite->dataLen += numOfBytes; rBuff->dataWrite += numOfBytes; rBuff->buffWrite->spaceAvail -= numOfBytes; /* * It may be that the current buffer is full at this point, * but don't do anything about it yet as the situation will * be handled next time through. Also, it's possible that * the current buffer may even have been emptied by then. */ } else { /* * Data won't fit in this buffer (at least not entirely), * is the next buffer available? */ if (rBuff->buffWrite->next == rBuff->buffRead) { /* We've caught the reader. This will only happen when * we have actually filled the maximum allocation of * buffers *or* the reserved buffer has been filled * before the buffer has had the opportunity to * be extended. We cannot extend the buffer at this point * as we may be in a critical region, the design is such * that if the buffer could be extended it should have * been done by now (for that matter, the wrap-around * should have also occurred). * * If we have filled the reserved buffer without having * the opportunity to extend the buffer then the buffer * is configured badly and must be retuned. * * Meanwhile, at this moment, options are: * * 1) If we have filled the entire buffer and cannot wrap- * around then return ERROR. * 2) If we have filled the entire buffer but can wrap- * around then do that. */ if (rBuff->info.options & RBUFF_WRAPAROUND) { /* * OK, perform an inline ring extension supplying NULL * as the new buffer forcing the ring to wrap-around. * This is a deterministic action. */ /* Interrupts already locked out */ rBuffAdd(rBuff, NULL); } else { /* Oh dear, can't wrap-round */ RBUFF_SEND_MSG (RBUFF_MSG_FULL, MSG_PRI_NORMAL, rBuff, 0); wvEvtBufferFullNotify = TRUE; return (NULL); } } /* * OK. * In the case that this function is writing the data, it * can be shared between this and next buffer. * In the case that we are only reserving the space, we must * return a pointer to contiguous space and therefore skip the * remainder of the previous buffer. */ /* skip the remainder of the current buffer */ rBuff->buffWrite->spaceAvail = 0; /* Move on to the next buffer */ rBuff->buffWrite = rBuff->buffWrite->next; /* Record the start of the reserved area */ returnPtr = rBuff->buffWrite->dataStart; /* Point dataWrite past the reserved area */ rBuff->dataWrite = rBuff->buffWrite->dataStart; rBuff->buffWrite->dataLen = numOfBytes; rBuff->dataWrite += numOfBytes; rBuff->buffWrite->spaceAvail = rBuff->info.buffSize - numOfBytes; if (--rBuff->info.emptyBuffs < RBUFF_EMPTY_KEEP && rBuff->info.currBuffs != rBuff->info.maxBuffs) { /* Schedule the rBuff Mgr to extend the buffer */ RBUFF_SEND_MSG (RBUFF_MSG_ADD, MSG_PRI_URGENT, rBuff, 0); } } rBuff->info.dataContent += numOfBytes; /* update info */ if(rBuff->info.dataContent > rBuff->info.bytesPeak) { rBuff->info.bytesPeak = rBuff->info.dataContent; } rBuff->info.bytesWritten += numOfBytes; rBuff->info.writesSinceReset++; if (!startUploading && rBuff->info.dataContent >= rBuff->info.threshold) { rBuff->info.timesXThreshold++; if (!(rBuff->info.options & RBUFF_UP_DEFERRED)) { /* * Signal for uploading to begin. Note that if we have just * reserved space it is imperative that uploading does not * actually begin until the data is in the buffer. */#if (CPU_FAMILY == I80X86) portWorkQAdd1 ((FUNCPTR)semBGiveDefer, (int) &rBuff->buffDesc.threshXSem);#else workQAdd1 ((FUNCPTR)semBGiveDefer, (int) &rBuff->buffDesc.threshXSem);#endif } } /* Critical Region End */ return (returnPtr); }/********************************************************************************* rBuffRead - Read data from a ring of buffers** This routine reads data from an extendable ring of buffers.** This function assumes mutually exclusive access is guaranteed by the caller.** NOMANUAL*/INT32 rBuffRead ( BUFFER_ID buffId, /* generic buffer descriptor */ UINT8 * dataDest, UINT32 numOfBytes ) { UINT32 bytesToCopy; UINT32 remaining = numOfBytes; RBUFF_ID rBuff; /* access private members of this rBuff desc */ /* Get access to the private members of this particular rBuff. */ rBuff = (RBUFF_ID) buffId; /* Critical Region Start */ while (remaining > 0) { bytesToCopy = (rBuff->buffRead->dataLen < remaining ? rBuff->buffRead->dataLen : remaining); if (bytesToCopy > 0) { memcpy (dataDest,rBuff->dataRead,bytesToCopy); remaining -= bytesToCopy; dataDest += bytesToCopy; /* Update buffer */ rBuff->buffRead->dataLen -= bytesToCopy; rBuff->dataRead += bytesToCopy; rBuff->info.dataContent -= bytesToCopy; } if (rBuff->buffRead->dataLen != 0) { /* This buffer is now empty */ rBuffHandleEmpty (rBuff); } else { /* this buffer is not yet emptied */ rBuff->dataRead += bytesToCopy; } } /* update info */ rBuff->info.bytesRead += (numOfBytes - remaining); rBuff->info.readsSinceReset++; /* Critical Region End */ return (numOfBytes - remaining); }/********************************************************************************* rBuffReadReserve - Return the number of contiguous bytes available for* reading.** NOMANUAL*/UINT32 rBuffReadReserve ( BUFFER_ID buffId, /* generic identifier for this buffer */ UINT8 **src ) { RBUFF_ID rBuff; /* specific identifier for this rBuff */ INT32 bytesAvailable; /* Get access to the private members of this particular rBuff. */ rBuff = (RBUFF_ID) buffId; /* Generate and return the available contiguous bytes. */ if ((bytesAvailable = rBuff->buffRead->dataLen)) { *src = rBuff->dataRead; } else { *src = NULL; } return (bytesAvailable); }/********************************************************************************* rBuffReadCommit - Move the read data ptr along a ring of buffers** This routine moves the data ptr along a ring of buffers.** It is equivalent to reading data from the buffers and should be used* when the data has been copied elsewhere.** This function assumes mutually exclusive access is guaranteed by the caller.** NOMANUAL*/STATUS rBuffReadCommit ( BUFFER_ID buffId, /* generic identifier for this buffer */ UINT32 numOfBytes ) { RBUFF_ID rBuff; /* specific identifier for this rBuff */ /* Get access to the private members of this particular rBuff. */ if (!numOfBytes) { return (OK); } rBuff = (RBUFF_ID) buffId; /* Critical Region Start */ if (numOfBytes == rBuff->buffRead->dataLen) { rBuffHandleEmpty (rBuff); } else if (numOfBytes < rBuff->buffRead->dataLen) { rBuff->buffRead->dataLen -= numOfBytes; rBuff->dataRead += numOfBytes; } else { /* Moving ahead through multiple buffers */ /* Not yet supported */ return(ERROR); } rBuff->info.dataContent -= numOfBytes; /* update info */ rBuff->info.bytesRead += numOfBytes; rBuff->info.readsSinceReset++; /* Critical Region End */ return (OK); }/********************************************************************************* rBuffFlush - Flush data from a ring of buffers** This routine causes any data held in a buffer to be uploaded and is* used to clear data that falls below the specified threshold.** NOMANUAL*/STATUS rBuffFlush ( BUFFER_ID buffId /* generic identifier for this buffer */ ) { RBUFF_ID rBuff; /* specific identifier for this rBuff */ int result, originalThreshold; /* Get access to the private members of this particular rBuff. */ rBuff = (RBUFF_ID) buffId; result = OK; if (!rBuff->info.dataContent) { return(OK); } /* Store the original threshold */ originalThreshold = rBuff->info.threshold; rBuff->info.threshold = 0; while (rBuff->info.dataContent > 0 && result != ERROR) { if (semGive (&rBuff->buffDesc.threshXSem) == OK) { /* Cause a reschedule to allow uploader in */ taskDelay(0); } else { result = ERROR; } } rBuff->info.threshold = originalThreshold; return(result);}/********************************************************************************* rBuffReset - reset an extendable ring of buffers** This routine resets an already created extendable ring of buffers to its* initial state. This loses any data held in the buffer. Any buffers held* above the specified minimum number are deallocated.** NOMANUAL*/STATUS rBuffReset ( BUFFER_ID buffId /* generic identifier for this buffer */ ) { RBUFF_ID rBuff; /* specific identifier for this rBuff */ RBUFF_LOCK (rBuff); /* Get access to the private members of this particular rBuff. */ rBuff = (RBUFF_ID) buffId; /* Now reset the ring of buffers. */ if (rBuff->info.currBuffs > rBuff->info.minBuffs) { UINT32 excessBuffs, count;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -