mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-09-18 07:41:57 +00:00
Using angle brackets <> for include files instead of "" improves coding consistency. Change-Id: I5edb71be8f834b5090e71b16c7b542429db89711 Signed-off-by: Peter Mitsis <peter.mitsis@windriver.com> Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
595 lines
16 KiB
C
595 lines
16 KiB
C
/* ch_buff.c */
|
|
|
|
/*
|
|
* Copyright (c) 1997-2015 Wind River Systems, Inc.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1) Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2) Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* 3) Neither the name of Wind River Systems nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
|
|
/* Implementation remarks:
|
|
- when using a floating end pointer: do not use pChBuff->iBuffsize for
|
|
(Buff->pEnd - pChBuff->pBegin)
|
|
*/
|
|
|
|
/*****************************************************************************/
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <microkernel/k_types.h>
|
|
#include <ch_buff.h>
|
|
#include <ch_buffm.h>
|
|
#include <toolchain.h>
|
|
#include <sections.h>
|
|
#include <misc/__assert.h>
|
|
|
|
/**********************************************************/
|
|
|
|
#define CHECK_CHBUFF_POINTER(pData) \
|
|
__ASSERT_NO_MSG(pChBuff->pBegin <= pData && pData < pChBuff->pEnd)
|
|
|
|
/*******************/
|
|
/* General
|
|
********************/
|
|
|
|
void BuffInit(unsigned char *pBuffer, int *piBuffSize, struct chbuff *pChBuff)
|
|
{
|
|
pChBuff->pBegin = pBuffer;
|
|
|
|
pChBuff->iBuffSize = *piBuffSize;
|
|
|
|
/* reset all pointers:
|
|
*/
|
|
{
|
|
pChBuff->pEnd = pChBuff->pBegin +
|
|
OCTET_TO_SIZEOFUNIT(pChBuff->iBuffSize);
|
|
pChBuff->pEndOrig = pChBuff->pEnd;
|
|
BuffReset(pChBuff);
|
|
}
|
|
}
|
|
|
|
void BuffReset(struct chbuff *pChBuff)
|
|
{
|
|
/* assumed it is allowed */
|
|
pChBuff->BuffState = BUFF_EMPTY;
|
|
pChBuff->pEnd = pChBuff->pEndOrig;
|
|
pChBuff->pWrite = pChBuff->pBegin;
|
|
pChBuff->pWriteGuard = NULL;
|
|
pChBuff->bWriteWA = FALSE;
|
|
pChBuff->pRead = pChBuff->pBegin;
|
|
pChBuff->pReadGuard = NULL;
|
|
pChBuff->bReadWA = TRUE; /* YES!! */
|
|
/*pChBuff->iFreeSpaceTotal =pChBuff->iBuffSize; */
|
|
pChBuff->iFreeSpaceCont = pChBuff->iBuffSize;
|
|
pChBuff->iFreeSpaceAWA = 0;
|
|
pChBuff->iNbrPendingReads = 0;
|
|
/*pChBuff->iAvailDataTotal =0; */
|
|
pChBuff->iAvailDataCont = 0;
|
|
pChBuff->iAvailDataAWA = 0;
|
|
pChBuff->iNbrPendingWrites = 0;
|
|
WriteMarkersClear(pChBuff);
|
|
ReadMarkersClear(pChBuff);
|
|
}
|
|
|
|
void BuffGetFreeSpaceTotal(struct chbuff *pChBuff,
|
|
int *piFreeSpaceTotal)
|
|
{
|
|
int dummy1, dummy2;
|
|
*piFreeSpaceTotal = CalcFreeSpace(pChBuff, &dummy1, &dummy2);
|
|
__ASSERT_NO_MSG(dummy1 == pChBuff->iFreeSpaceCont);
|
|
__ASSERT_NO_MSG(dummy2 == pChBuff->iFreeSpaceAWA);
|
|
}
|
|
|
|
void BuffGetFreeSpace(struct chbuff *pChBuff,
|
|
int *piFreeSpaceTotal,
|
|
int *piFreeSpaceCont,
|
|
int *piFreeSpaceAWA)
|
|
{
|
|
int iFreeSpaceCont;
|
|
int iFreeSpaceAWA;
|
|
int iFreeSpaceTotal;
|
|
|
|
iFreeSpaceTotal =
|
|
CalcFreeSpace(pChBuff, &iFreeSpaceCont, &iFreeSpaceAWA);
|
|
__ASSERT_NO_MSG(iFreeSpaceCont == pChBuff->iFreeSpaceCont);
|
|
__ASSERT_NO_MSG(iFreeSpaceAWA == pChBuff->iFreeSpaceAWA);
|
|
*piFreeSpaceTotal = iFreeSpaceTotal;
|
|
*piFreeSpaceCont = pChBuff->iFreeSpaceCont;
|
|
*piFreeSpaceAWA = pChBuff->iFreeSpaceAWA;
|
|
}
|
|
|
|
void BuffGetAvailDataTotal(struct chbuff *pChBuff,
|
|
int *piAvailDataTotal)
|
|
{
|
|
int dummy1, dummy2;
|
|
*piAvailDataTotal = CalcAvailData(pChBuff, &dummy1, &dummy2);
|
|
__ASSERT_NO_MSG(dummy1 == pChBuff->iAvailDataCont);
|
|
__ASSERT_NO_MSG(dummy2 == pChBuff->iAvailDataAWA);
|
|
}
|
|
|
|
void BuffGetAvailData(struct chbuff *pChBuff,
|
|
int *piAvailDataTotal,
|
|
int *piAvailDataCont,
|
|
int *piAvailDataAWA)
|
|
{
|
|
int iAvailDataCont;
|
|
int iAvailDataAWA;
|
|
int iAvailDataTotal;
|
|
|
|
iAvailDataTotal =
|
|
CalcAvailData(pChBuff, &iAvailDataCont, &iAvailDataAWA);
|
|
__ASSERT_NO_MSG(iAvailDataCont == pChBuff->iAvailDataCont);
|
|
__ASSERT_NO_MSG(iAvailDataAWA == pChBuff->iAvailDataAWA);
|
|
*piAvailDataTotal = iAvailDataTotal;
|
|
*piAvailDataCont = pChBuff->iAvailDataCont;
|
|
*piAvailDataAWA = pChBuff->iAvailDataAWA;
|
|
}
|
|
|
|
/*******************/
|
|
/* Buffer en-queuing:
|
|
********************/
|
|
|
|
int BuffEnQ(struct chbuff *pChBuff, int iSize, unsigned char **ppWrite)
|
|
{
|
|
int iTransferID;
|
|
/* int ret;*/
|
|
if (0 == BuffEnQA(pChBuff, iSize, ppWrite, &iTransferID))
|
|
return 0;
|
|
BuffEnQA_End(pChBuff, iTransferID, iSize /*optional */); /* check ret
|
|
value */
|
|
return iSize;
|
|
}
|
|
|
|
int BuffEnQA(struct chbuff *pChBuff,
|
|
int iSize,
|
|
unsigned char **ppWrite,
|
|
int *piTransferID)
|
|
{
|
|
if (iSize > pChBuff->iFreeSpaceCont)
|
|
return 0;
|
|
*piTransferID = AsyncEnQRegstr(pChBuff, iSize);
|
|
if (-1 == *piTransferID)
|
|
return 0;
|
|
|
|
*ppWrite = pChBuff->pWrite;
|
|
|
|
/* adjust write pointer and free space:
|
|
*/
|
|
pChBuff->pWrite += OCTET_TO_SIZEOFUNIT(iSize);
|
|
if (pChBuff->pEnd == pChBuff->pWrite) {
|
|
pChBuff->pWrite = pChBuff->pBegin;
|
|
pChBuff->iFreeSpaceCont = pChBuff->iFreeSpaceAWA;
|
|
pChBuff->iFreeSpaceAWA = 0;
|
|
pChBuff->bWriteWA = TRUE;
|
|
pChBuff->bReadWA = FALSE;
|
|
pChBuff->ReadMarkers.iAWAMarker = -1;
|
|
} else {
|
|
pChBuff->iFreeSpaceCont -= iSize;
|
|
}
|
|
|
|
if (pChBuff->pWrite == pChBuff->pRead)
|
|
pChBuff->BuffState = BUFF_FULL;
|
|
else
|
|
pChBuff->BuffState = BUFF_OTHER;
|
|
|
|
CHECK_CHBUFF_POINTER(pChBuff->pWrite);
|
|
|
|
return iSize;
|
|
}
|
|
|
|
void BuffEnQA_End(struct chbuff *pChBuff,
|
|
int iTransferID,
|
|
int iSize /*optional */)
|
|
{
|
|
ARG_UNUSED(iSize);
|
|
|
|
/* An asynchronous data transfer to the buffer has finished
|
|
*/
|
|
AsyncEnQFinished(pChBuff, iTransferID);
|
|
}
|
|
|
|
/**************************************************/
|
|
|
|
int AsyncEnQRegstr(struct chbuff *pChBuff, int iSize)
|
|
{
|
|
int i;
|
|
|
|
ChannelCheck4Intrusion(pChBuff, pChBuff->pWrite, iSize);
|
|
|
|
i = MarkerAddLast(&(pChBuff->WriteMarkers), pChBuff->pWrite, iSize, TRUE);
|
|
if (i != -1) {
|
|
/* adjust iNbrPendingWrites: */
|
|
__ASSERT_NO_MSG(0 <= pChBuff->iNbrPendingWrites);
|
|
(pChBuff->iNbrPendingWrites)++;
|
|
/* pReadGuard changes? */
|
|
if (NULL == pChBuff->pReadGuard)
|
|
pChBuff->pReadGuard = pChBuff->pWrite;
|
|
__ASSERT_NO_MSG(pChBuff->WriteMarkers.aMarkers
|
|
[pChBuff->WriteMarkers.iFirstMarker]
|
|
.pointer == pChBuff->pReadGuard);
|
|
/* iAWAMarker changes? */
|
|
if (-1 == pChBuff->WriteMarkers.iAWAMarker && pChBuff->bWriteWA)
|
|
pChBuff->WriteMarkers.iAWAMarker = i;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
void AsyncEnQFinished(struct chbuff *pChBuff, int iTransferID)
|
|
{
|
|
pChBuff->WriteMarkers.aMarkers[iTransferID].bXferBusy = FALSE;
|
|
|
|
if (pChBuff->WriteMarkers.iFirstMarker == iTransferID) {
|
|
/*int iSizeCont=0;
|
|
int isizeAWA=0; */
|
|
int iNewFirstMarker =
|
|
ScanMarkers(&(pChBuff->WriteMarkers),
|
|
&(pChBuff->iAvailDataCont),
|
|
&(pChBuff->iAvailDataAWA),
|
|
&(pChBuff->iNbrPendingWrites));
|
|
/*pChBuff->iAvailDataCont +=iSizeCont;
|
|
pChBuff->iAvailDataAWA +=iSizeAWA; */
|
|
if (-1 != iNewFirstMarker)
|
|
pChBuff->pReadGuard =
|
|
pChBuff->WriteMarkers.aMarkers[iNewFirstMarker]
|
|
.pointer;
|
|
else
|
|
pChBuff->pReadGuard = NULL;
|
|
}
|
|
}
|
|
|
|
/**********************/
|
|
/* Buffer de-queuing: */
|
|
/**********************/
|
|
|
|
int BuffDeQ(struct chbuff *pChBuff, int iSize, unsigned char **ppRead)
|
|
{
|
|
int iTransferID;
|
|
/* int ret;*/
|
|
if (0 == BuffDeQA(pChBuff, iSize, ppRead, &iTransferID))
|
|
return 0;
|
|
BuffDeQA_End(pChBuff, iTransferID, iSize /*optional */);
|
|
return iSize;
|
|
}
|
|
|
|
int BuffDeQA(struct chbuff *pChBuff,
|
|
int iSize,
|
|
unsigned char **ppRead,
|
|
int *piTransferID)
|
|
{
|
|
/* asynchronous data transfer
|
|
read guard pointers must be set
|
|
*/
|
|
if (iSize >
|
|
pChBuff->iAvailDataCont) /* free space is from read to guard
|
|
pointer/end pointer */
|
|
return 0;
|
|
*piTransferID = AsyncDeQRegstr(pChBuff, iSize);
|
|
if (-1 == *piTransferID)
|
|
return 0;
|
|
|
|
*ppRead = pChBuff->pRead;
|
|
|
|
/* adjust read pointer and avail data:
|
|
*/
|
|
pChBuff->pRead += OCTET_TO_SIZEOFUNIT(iSize);
|
|
if (pChBuff->pEnd == pChBuff->pRead) {
|
|
pChBuff->pRead = pChBuff->pBegin;
|
|
pChBuff->iAvailDataCont = pChBuff->iAvailDataAWA;
|
|
pChBuff->iAvailDataAWA = 0;
|
|
pChBuff->bWriteWA = FALSE;
|
|
pChBuff->bReadWA = TRUE;
|
|
pChBuff->WriteMarkers.iAWAMarker = -1;
|
|
} else {
|
|
pChBuff->iAvailDataCont -= iSize;
|
|
}
|
|
|
|
if (pChBuff->pWrite == pChBuff->pRead)
|
|
pChBuff->BuffState = BUFF_EMPTY;
|
|
else
|
|
pChBuff->BuffState = BUFF_OTHER;
|
|
|
|
CHECK_CHBUFF_POINTER(pChBuff->pRead);
|
|
|
|
return iSize;
|
|
}
|
|
|
|
void BuffDeQA_End(struct chbuff *pChBuff,
|
|
int iTransferID,
|
|
int iSize /*optional */)
|
|
{
|
|
ARG_UNUSED(iSize);
|
|
|
|
/* An asynchronous data transfer from the buffer has finished
|
|
*/
|
|
AsyncDeQFinished(pChBuff, iTransferID);
|
|
|
|
#if 0
|
|
/* optimisation: reset queue when empty:
|
|
*/
|
|
if (BUFF_EMPTY == pChBuff->BuffState
|
|
&& NULL == pChBuff->pWriteGuard
|
|
/* no pending read Xfers anymore */
|
|
/* && NULL==pChBuff->pReadGuard no pending write Xfers
|
|
(here write Xfers could be started after the last DeQA,
|
|
but then the buffer is not empty anymore) */
|
|
) {
|
|
BuffReset(pChBuff); /* then we can safely reset the buffer */
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**********************************************************/
|
|
|
|
int AsyncDeQRegstr(struct chbuff *pChBuff, int iSize)
|
|
{
|
|
int i;
|
|
|
|
ChannelCheck4Intrusion(pChBuff, pChBuff->pRead, iSize);
|
|
|
|
i = MarkerAddLast(&(pChBuff->ReadMarkers), pChBuff->pRead, iSize, TRUE);
|
|
if (i != -1) {
|
|
/* adjust iNbrPendingReads: */
|
|
__ASSERT_NO_MSG(0 <= pChBuff->iNbrPendingReads);
|
|
(pChBuff->iNbrPendingReads)++;
|
|
/* pWriteGuard changes? */
|
|
if (NULL == pChBuff->pWriteGuard)
|
|
pChBuff->pWriteGuard = pChBuff->pRead;
|
|
__ASSERT_NO_MSG(pChBuff->ReadMarkers.aMarkers
|
|
[pChBuff->ReadMarkers.iFirstMarker]
|
|
.pointer == pChBuff->pWriteGuard);
|
|
/* iAWAMarker changes? */
|
|
if (-1 == pChBuff->ReadMarkers.iAWAMarker && pChBuff->bReadWA)
|
|
pChBuff->ReadMarkers.iAWAMarker = i;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
void AsyncDeQFinished(struct chbuff *pChBuff, int iTransferID)
|
|
{
|
|
pChBuff->ReadMarkers.aMarkers[iTransferID].bXferBusy = FALSE;
|
|
|
|
if (pChBuff->ReadMarkers.iFirstMarker == iTransferID) {
|
|
/*int iSizeCont=0;
|
|
int iSizeAWA=0; */
|
|
int iNewFirstMarker = ScanMarkers(&(pChBuff->ReadMarkers),
|
|
&(pChBuff->iFreeSpaceCont),
|
|
&(pChBuff->iFreeSpaceAWA),
|
|
&(pChBuff->iNbrPendingReads));
|
|
/*pChBuff->iFreeSpaceCont +=iSizeCont;
|
|
pChBuff->iFreeSpaceAWA +=iSizeAWA; */
|
|
if (-1 != iNewFirstMarker)
|
|
pChBuff->pWriteGuard =
|
|
pChBuff->ReadMarkers.aMarkers[iNewFirstMarker]
|
|
.pointer;
|
|
else
|
|
pChBuff->pWriteGuard = NULL;
|
|
}
|
|
}
|
|
|
|
/**********************************************************/
|
|
|
|
void WriteMarkersClear(struct chbuff *pChBuff)
|
|
{
|
|
MarkersClear(&(pChBuff->WriteMarkers));
|
|
}
|
|
|
|
void ReadMarkersClear(struct chbuff *pChBuff)
|
|
{
|
|
MarkersClear(&(pChBuff->ReadMarkers));
|
|
}
|
|
|
|
/********************************************************************************/
|
|
|
|
/* note on setting/clearing markers/guards:
|
|
|
|
If there is at least one marker, there is a guard and equals one of the
|
|
markers
|
|
If there are no markers (*), there is no guard
|
|
Consequently, if a marker is add when there were none, the guard will equal
|
|
it.
|
|
If additional markers are add, the guard will not change.
|
|
However, if a marker is deleted:
|
|
if it equals the guard a new guard must be selected (**)
|
|
if not, guard doesn't change
|
|
|
|
(*) we need to housekeep how much markers there are or we can inspect the
|
|
guard
|
|
(**) for this, the complete markers table needs to be investigated
|
|
*/
|
|
|
|
/***************************************/
|
|
|
|
/* This function will see if one or more 'areas' in the buffer can be made
|
|
available
|
|
(either for writing xor reading).
|
|
Note: such a series of areas starts from the beginning.
|
|
*/
|
|
int ScanMarkers(struct marker_list *pMarkerList,
|
|
int *piSizeBWA,
|
|
int *piSizeAWA,
|
|
int *piNbrPendingXfers)
|
|
{
|
|
struct marker *pM;
|
|
BOOL bMarkersAreNowAWA;
|
|
int index;
|
|
|
|
index = pMarkerList->iFirstMarker;
|
|
/*if ( -1 == index)
|
|
return;
|
|
*/
|
|
__ASSERT_NO_MSG(-1 != index);
|
|
|
|
bMarkersAreNowAWA = FALSE;
|
|
do {
|
|
int index_next;
|
|
|
|
__ASSERT_NO_MSG(index == pMarkerList->iFirstMarker);
|
|
|
|
if (index == pMarkerList->iAWAMarker) {
|
|
bMarkersAreNowAWA =
|
|
TRUE; /* from now on, everything is AWA */
|
|
}
|
|
|
|
pM = &(pMarkerList->aMarkers[index]);
|
|
|
|
if (pM->bXferBusy == TRUE)
|
|
break;
|
|
|
|
if (!bMarkersAreNowAWA)
|
|
*piSizeBWA += pM->size;
|
|
else
|
|
*piSizeAWA += pM->size;
|
|
|
|
index_next = pM->Next;
|
|
MarkerDelete(pMarkerList, index); /* pMarkerList->iFirstMarker
|
|
will be updated */
|
|
/* adjust *piNbrPendingXfers */
|
|
if (piNbrPendingXfers) {
|
|
__ASSERT_NO_MSG(0 <= *piNbrPendingXfers);
|
|
(*piNbrPendingXfers)--;
|
|
}
|
|
index = index_next;
|
|
} while (-1 != index);
|
|
|
|
__ASSERT_NO_MSG(index == pMarkerList->iFirstMarker);
|
|
|
|
if (bMarkersAreNowAWA)
|
|
pMarkerList->iAWAMarker = pMarkerList->iFirstMarker;
|
|
|
|
#ifdef STORE_NBR_MARKERS
|
|
if (0 == pMarkerList->iNbrMarkers) {
|
|
__ASSERT_NO_MSG(-1 == pMarkerList->iFirstMarker);
|
|
__ASSERT_NO_MSG(-1 == pMarkerList->iLastMarker);
|
|
__ASSERT_NO_MSG(-1 == pMarkerList->iAWAMarker);
|
|
}
|
|
#endif
|
|
|
|
return pMarkerList->iFirstMarker;
|
|
}
|
|
|
|
/**********************************************************/
|
|
|
|
int CalcAvailData(struct chbuff *pChBuff,
|
|
int *piAvailDataCont,
|
|
int *piAvailDataAWA)
|
|
{
|
|
unsigned char *pStart = pChBuff->pRead;
|
|
unsigned char *pStop = pChBuff->pWrite;
|
|
|
|
if (NULL != pChBuff->pReadGuard)
|
|
pStop = pChBuff->pReadGuard;
|
|
else {
|
|
/* else:
|
|
if BuffState==BUFF_FULL but we have a ReadGuard, we still
|
|
need to calculate it as a normal [Start,Stop] interval
|
|
*/
|
|
if (BUFF_FULL == pChBuff->BuffState) {
|
|
*piAvailDataCont =
|
|
SIZEOFUNIT_TO_OCTET(pChBuff->pEnd - pStart);
|
|
*piAvailDataAWA =
|
|
SIZEOFUNIT_TO_OCTET(pStop - pChBuff->pBegin);
|
|
return (*piAvailDataCont + *piAvailDataAWA);
|
|
/* this sum equals pEnd-pBegin */
|
|
}
|
|
}
|
|
/* on the other hand, if BuffState is empty, we do not need a special
|
|
flow;
|
|
it will be correct as (pStop - pStart) equals 0 */
|
|
|
|
if (pStop >= pStart) {
|
|
*piAvailDataCont = SIZEOFUNIT_TO_OCTET(pStop - pStart);
|
|
*piAvailDataAWA = 0;
|
|
} else {
|
|
*piAvailDataCont = SIZEOFUNIT_TO_OCTET(pChBuff->pEnd - pStart);
|
|
*piAvailDataAWA = SIZEOFUNIT_TO_OCTET(pStop - pChBuff->pBegin);
|
|
}
|
|
return (*piAvailDataCont + *piAvailDataAWA);
|
|
}
|
|
|
|
int CalcFreeSpace(struct chbuff *pChBuff,
|
|
int *piFreeSpaceCont,
|
|
int *piFreeSpaceAWA)
|
|
{
|
|
unsigned char *pStart = pChBuff->pWrite;
|
|
unsigned char *pStop = pChBuff->pRead;
|
|
|
|
if (NULL != pChBuff->pWriteGuard)
|
|
pStop = pChBuff->pWriteGuard;
|
|
else {
|
|
/* else:
|
|
if BuffState==BUFF_EMPTY but we have a WriteGuard, we still
|
|
need to calculate it as a normal [Start,Stop] interval
|
|
*/
|
|
if (BUFF_EMPTY == pChBuff->BuffState) {
|
|
*piFreeSpaceCont =
|
|
SIZEOFUNIT_TO_OCTET(pChBuff->pEnd - pStart);
|
|
*piFreeSpaceAWA =
|
|
SIZEOFUNIT_TO_OCTET(pStop - pChBuff->pBegin);
|
|
return (*piFreeSpaceCont + *piFreeSpaceAWA);
|
|
/* this sum equals pEnd-pBegin */
|
|
}
|
|
}
|
|
/* on the other hand, if BuffState is full, we do not need a special
|
|
flow;
|
|
it will be correct as (pStop - pStart) equals 0 */
|
|
|
|
if (pStop >= pStart) {
|
|
*piFreeSpaceCont = SIZEOFUNIT_TO_OCTET(pStop - pStart);
|
|
*piFreeSpaceAWA = 0;
|
|
} else {
|
|
*piFreeSpaceCont = SIZEOFUNIT_TO_OCTET(pChBuff->pEnd - pStart);
|
|
*piFreeSpaceAWA = SIZEOFUNIT_TO_OCTET(pStop - pChBuff->pBegin);
|
|
}
|
|
return (*piFreeSpaceCont + *piFreeSpaceAWA);
|
|
}
|
|
|
|
int BuffFull(struct chbuff *pChBuff)
|
|
{/* remark: 0==iTotalFreeSpace is an INcorrect condition b/c of async. behavior
|
|
*/
|
|
int iAvailDataTotal;
|
|
|
|
BuffGetAvailDataTotal(pChBuff, &iAvailDataTotal);
|
|
return (pChBuff->iBuffSize == iAvailDataTotal);
|
|
}
|
|
|
|
int BuffEmpty(struct chbuff *pChBuff)
|
|
{/* remark: 0==iAvailDataTotal is an INcorrect condition b/c of async. behavior
|
|
*/
|
|
int iTotalFreeSpace;
|
|
|
|
BuffGetFreeSpaceTotal(pChBuff, &iTotalFreeSpace);
|
|
return (pChBuff->iBuffSize == iTotalFreeSpace);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" */
|
|
#endif
|