2042 lines
58 KiB
C
2042 lines
58 KiB
C
![]() |
/****************************************************************************
|
||
|
|
||
|
(c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
|
||
|
www.systec-electronic.com
|
||
|
|
||
|
Project: Project independend shared buffer (linear + circular)
|
||
|
|
||
|
Description: Implementation of platform independend part for the
|
||
|
shared buffer
|
||
|
|
||
|
License:
|
||
|
|
||
|
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 SYSTEC electronic GmbH nor the names of its
|
||
|
contributors may be used to endorse or promote products derived
|
||
|
from this software without prior written permission. For written
|
||
|
permission, please contact info@systec-electronic.com.
|
||
|
|
||
|
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 HOLDERS 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.
|
||
|
|
||
|
Severability Clause:
|
||
|
|
||
|
If a provision of this License is or becomes illegal, invalid or
|
||
|
unenforceable in any jurisdiction, that shall not affect:
|
||
|
1. the validity or enforceability in that jurisdiction of any other
|
||
|
provision of this License; or
|
||
|
2. the validity or enforceability in other jurisdictions of that or
|
||
|
any other provision of this License.
|
||
|
|
||
|
-------------------------------------------------------------------------
|
||
|
|
||
|
2006/06/27 -rs: V 1.00 (initial version)
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
#if defined(WIN32) || defined(_WIN32)
|
||
|
|
||
|
#ifdef UNDER_RTSS
|
||
|
// RTX header
|
||
|
#include <windows.h>
|
||
|
#include <process.h>
|
||
|
#include <rtapi.h>
|
||
|
|
||
|
#elif __BORLANDC__
|
||
|
// borland C header
|
||
|
#include <windows.h>
|
||
|
#include <process.h>
|
||
|
|
||
|
#elif WINCE
|
||
|
#include <windows.h>
|
||
|
|
||
|
#else
|
||
|
// MSVC needs to include windows.h at first
|
||
|
// the following defines ar necessary for function prototypes for waitable timers
|
||
|
#define _WIN32_WINDOWS 0x0401
|
||
|
#define _WIN32_WINNT 0x0400
|
||
|
#include <windows.h>
|
||
|
#include <process.h>
|
||
|
#endif
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#include "global.h"
|
||
|
#include "SharedBuff.h"
|
||
|
#include "ShbIpc.h"
|
||
|
|
||
|
// d.k. Linux kernel modules needs other header files for memcpy()
|
||
|
#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
|
||
|
#include <linux/string.h>
|
||
|
#else
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/***************************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/* G L O B A L D E F I N I T I O N S */
|
||
|
/* */
|
||
|
/* */
|
||
|
/***************************************************************************/
|
||
|
|
||
|
#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Configuration
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Constant definitions
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
#define SBC_MAGIC_ID 0x53424323 // magic ID ("SBC#")
|
||
|
#define SBL_MAGIC_ID 0x53424C23 // magic ID ("SBL#")
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Local types
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
// structure to administrate circular shared buffer head
|
||
|
typedef struct
|
||
|
{
|
||
|
unsigned long m_ShbCirMagicID; // magic ID ("SBC#")
|
||
|
unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
|
||
|
unsigned long m_ulBufferDataSize; // size of complete data area
|
||
|
unsigned long m_ulWrIndex; // current write index (set bevore write)
|
||
|
unsigned long m_ulRdIndex; // current read index (set after read)
|
||
|
unsigned long m_ulNumOfWriteJobs; // number of currently (parallel running) write operations
|
||
|
unsigned long m_ulDataInUse; // currently used buffer size (incl. uncompleted write operations)
|
||
|
unsigned long m_ulDataApended; // buffer size of complete new written but not yet readable data (in case of m_ulNumOfWriteJobs>1)
|
||
|
unsigned long m_ulBlocksApended; // number of complete new written but not yet readable data blocks (in case of m_ulNumOfWriteJobs>1)
|
||
|
unsigned long m_ulDataReadable; // buffer size with readable (complete written) data
|
||
|
unsigned long m_ulBlocksReadable; // number of readable (complete written) data blocks
|
||
|
tShbCirSigHndlrNewData m_pfnSigHndlrNewData;// application handler to signal new data
|
||
|
unsigned int m_fBufferLocked; // TRUE if buffer is locked (because of pending reset request)
|
||
|
tShbCirSigHndlrReset m_pfnSigHndlrReset; // application handler to signal buffer reset is done
|
||
|
unsigned char m_Data; // start of data area (the real data size is unknown at this time)
|
||
|
|
||
|
} tShbCirBuff;
|
||
|
|
||
|
|
||
|
// structure to administrate linear shared buffer head
|
||
|
typedef struct
|
||
|
{
|
||
|
unsigned int m_ShbLinMagicID; // magic ID ("SBL#")
|
||
|
unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
|
||
|
unsigned long m_ulBufferDataSize; // size of complete data area
|
||
|
unsigned char m_Data; // start of data area (the real data size is unknown at this time)
|
||
|
|
||
|
} tShbLinBuff;
|
||
|
|
||
|
|
||
|
// type to save size of a single data block inside the circular shared buffer
|
||
|
typedef struct
|
||
|
{
|
||
|
unsigned int m_uiFullBlockSize : 28; // a single block must not exceed a length of 256MByte :-)
|
||
|
unsigned int m_uiAlignFillBytes : 4;
|
||
|
|
||
|
} tShbCirBlockSize;
|
||
|
|
||
|
#define SBC_BLOCK_ALIGNMENT 4 // alignment must *not* be lower than sizeof(tShbCirBlockSize)!
|
||
|
#define SBC_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
|
||
|
|
||
|
#define SBL_BLOCK_ALIGNMENT 4
|
||
|
#define SBL_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Global variables
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Local variables
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Prototypes of internal functions
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Get pointer to Circular Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
INLINE_FUNCTION tShbCirBuff* ShbCirGetBuffer (
|
||
|
tShbInstance pShbInstance_p)
|
||
|
{
|
||
|
|
||
|
tShbCirBuff* pShbCirBuff;
|
||
|
|
||
|
|
||
|
pShbCirBuff = (tShbCirBuff*) ShbIpcGetShMemPtr (pShbInstance_p);
|
||
|
ASSERT(pShbCirBuff->m_ShbCirMagicID == SBC_MAGIC_ID);
|
||
|
|
||
|
return (pShbCirBuff);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Get pointer to Linear Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
INLINE_FUNCTION tShbLinBuff* ShbLinGetBuffer (
|
||
|
tShbInstance pShbInstance_p)
|
||
|
{
|
||
|
|
||
|
tShbLinBuff* pShbLinBuff;
|
||
|
|
||
|
|
||
|
pShbLinBuff = (tShbLinBuff*) ShbIpcGetShMemPtr (pShbInstance_p);
|
||
|
ASSERT(pShbLinBuff->m_ShbLinMagicID == SBL_MAGIC_ID);
|
||
|
|
||
|
return (pShbLinBuff);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// not inlined internal functions
|
||
|
int ShbCirSignalHandlerNewData (tShbInstance pShbInstance_p);
|
||
|
void ShbCirSignalHandlerReset (tShbInstance pShbInstance_p, unsigned int fTimeOut_p);
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
//=========================================================================//
|
||
|
// //
|
||
|
// P U B L I C F U N C T I O N S //
|
||
|
// //
|
||
|
//=========================================================================//
|
||
|
|
||
|
#if !defined(INLINE_ENABLED)
|
||
|
// not inlined external functions
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Initialize Shared Buffer Module
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
tShbError ShbInit (void)
|
||
|
{
|
||
|
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
ShbError = ShbIpcInit();
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Deinitialize Shared Buffer Module
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
tShbError ShbExit (void)
|
||
|
{
|
||
|
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
ShbError = ShbIpcExit();
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-------------------------------------------------------------------------//
|
||
|
// //
|
||
|
// C i r c u l a r S h a r e d B u f f e r //
|
||
|
// //
|
||
|
//-------------------------------------------------------------------------//
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Allocate Circular Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
tShbError ShbCirAllocBuffer (
|
||
|
unsigned long ulBufferSize_p,
|
||
|
const char* pszBufferID_p,
|
||
|
tShbInstance* ppShbInstance_p,
|
||
|
unsigned int* pfShbNewCreated_p)
|
||
|
{
|
||
|
|
||
|
tShbInstance pShbInstance;
|
||
|
tShbCirBuff* pShbCirBuff;
|
||
|
unsigned int fShbNewCreated;
|
||
|
unsigned long ulBufferDataSize;
|
||
|
unsigned long ulBufferTotalSize;
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL))
|
||
|
{
|
||
|
return (kShbInvalidArg);
|
||
|
}
|
||
|
|
||
|
|
||
|
// calculate length of memory to allocate
|
||
|
ulBufferDataSize = (ulBufferSize_p + (SBC_BLOCK_ALIGNMENT-1)) & ~(SBC_BLOCK_ALIGNMENT-1);
|
||
|
ulBufferTotalSize = ulBufferDataSize + sizeof(tShbCirBuff);
|
||
|
|
||
|
// allocate a new or open an existing shared buffer
|
||
|
ShbError = ShbIpcAllocBuffer (ulBufferTotalSize, pszBufferID_p,
|
||
|
&pShbInstance, &fShbNewCreated);
|
||
|
if (ShbError != kShbOk)
|
||
|
{
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if (pShbInstance == NULL)
|
||
|
{
|
||
|
ShbError = kShbOutOfMem;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// get pointer to shared buffer
|
||
|
pShbCirBuff = (tShbCirBuff*) ShbIpcGetShMemPtr (pShbInstance);
|
||
|
|
||
|
// if the shared buffer was new created, than this process has
|
||
|
// to initialize it, otherwise the buffer is already in use
|
||
|
// and *must not* be reseted
|
||
|
if ( fShbNewCreated )
|
||
|
{
|
||
|
#ifndef NDEBUG
|
||
|
{
|
||
|
memset (pShbCirBuff, 0xCC, ulBufferTotalSize);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
pShbCirBuff->m_ShbCirMagicID = SBC_MAGIC_ID;
|
||
|
pShbCirBuff->m_ulBufferTotalSize = ulBufferTotalSize;
|
||
|
pShbCirBuff->m_ulBufferDataSize = ulBufferDataSize;
|
||
|
pShbCirBuff->m_ulWrIndex = 0;
|
||
|
pShbCirBuff->m_ulRdIndex = 0;
|
||
|
pShbCirBuff->m_ulNumOfWriteJobs = 0;
|
||
|
pShbCirBuff->m_ulDataInUse = 0;
|
||
|
pShbCirBuff->m_ulDataApended = 0;
|
||
|
pShbCirBuff->m_ulBlocksApended = 0;
|
||
|
pShbCirBuff->m_ulDataReadable = 0;
|
||
|
pShbCirBuff->m_ulBlocksReadable = 0;
|
||
|
pShbCirBuff->m_pfnSigHndlrNewData = NULL;
|
||
|
pShbCirBuff->m_fBufferLocked = FALSE;
|
||
|
pShbCirBuff->m_pfnSigHndlrReset = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
|
||
|
{
|
||
|
ShbError = kShbInvalidBufferType;
|
||
|
goto Exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
*ppShbInstance_p = pShbInstance;
|
||
|
*pfShbNewCreated_p = fShbNewCreated;
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Release Circular Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
tShbError ShbCirReleaseBuffer (
|
||
|
tShbInstance pShbInstance_p)
|
||
|
{
|
||
|
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if (pShbInstance_p == NULL)
|
||
|
{
|
||
|
ShbError = kShbOk;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
ShbError = ShbIpcReleaseBuffer (pShbInstance_p);
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif // !defined(INLINE_ENABLED)
|
||
|
|
||
|
#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Reset Circular Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
INLINE_FUNCTION tShbError ShbCirResetBuffer (
|
||
|
tShbInstance pShbInstance_p,
|
||
|
unsigned long ulTimeOut_p,
|
||
|
tShbCirSigHndlrReset pfnSignalHandlerReset_p)
|
||
|
{
|
||
|
|
||
|
tShbCirBuff* pShbCirBuff;
|
||
|
unsigned long ulNumOfWriteJobs = 0; // d.k. GCC complains about uninitialized variable otherwise
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if (pShbInstance_p == NULL)
|
||
|
{
|
||
|
ShbError = kShbInvalidArg;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
|
||
|
ShbError = kShbOk;
|
||
|
|
||
|
if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
|
||
|
{
|
||
|
ShbError = kShbInvalidBufferType;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// start reset job by setting request request in buffer header
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
if ( !pShbCirBuff->m_fBufferLocked )
|
||
|
{
|
||
|
ulNumOfWriteJobs = pShbCirBuff->m_ulNumOfWriteJobs;
|
||
|
|
||
|
pShbCirBuff->m_fBufferLocked = TRUE;
|
||
|
pShbCirBuff->m_pfnSigHndlrReset = pfnSignalHandlerReset_p;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ShbError = kShbAlreadyReseting;
|
||
|
}
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
|
||
|
if (ShbError != kShbOk)
|
||
|
{
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// if there is currently no running write operation then reset buffer
|
||
|
// immediately, otherwise wait until the last write job is ready by
|
||
|
// starting a signal process
|
||
|
if (ulNumOfWriteJobs == 0)
|
||
|
{
|
||
|
// there is currently no running write operation
|
||
|
// -> reset buffer immediately
|
||
|
ShbCirSignalHandlerReset (pShbInstance_p, FALSE);
|
||
|
ShbError = kShbOk;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// there is currently at least one running write operation
|
||
|
// -> starting signal process to wait until the last write job is ready
|
||
|
ShbError = ShbIpcStartSignalingJobReady (pShbInstance_p, ulTimeOut_p, ShbCirSignalHandlerReset);
|
||
|
}
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Write data block to Circular Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
INLINE_FUNCTION tShbError ShbCirWriteDataBlock (
|
||
|
tShbInstance pShbInstance_p,
|
||
|
const void* pSrcDataBlock_p,
|
||
|
unsigned long ulDataBlockSize_p)
|
||
|
{
|
||
|
|
||
|
tShbCirBuff* pShbCirBuff;
|
||
|
tShbCirBlockSize ShbCirBlockSize;
|
||
|
unsigned int uiFullBlockSize;
|
||
|
unsigned int uiAlignFillBytes;
|
||
|
unsigned char* pShbCirDataPtr;
|
||
|
unsigned char* pScrDataPtr;
|
||
|
unsigned long ulDataSize;
|
||
|
unsigned long ulChunkSize;
|
||
|
unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
|
||
|
unsigned int fSignalNewData;
|
||
|
unsigned int fSignalReset;
|
||
|
tShbError ShbError;
|
||
|
tShbError ShbError2;
|
||
|
int fRes;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if (pShbInstance_p == NULL)
|
||
|
{
|
||
|
ShbError = kShbInvalidArg;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0))
|
||
|
{
|
||
|
// nothing to do here
|
||
|
ShbError = kShbOk;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if (ulDataBlockSize_p > SBC_MAX_BLOCK_SIZE)
|
||
|
{
|
||
|
ShbError = kShbExceedDataSizeLimit;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
|
||
|
pScrDataPtr = (unsigned char*)pSrcDataBlock_p;
|
||
|
fSignalNewData = FALSE;
|
||
|
fSignalReset = FALSE;
|
||
|
ShbError = kShbOk;
|
||
|
|
||
|
if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
|
||
|
{
|
||
|
ShbError = kShbInvalidBufferType;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// calculate data block size in circular buffer
|
||
|
ulDataSize = (ulDataBlockSize_p + (SBC_BLOCK_ALIGNMENT-1)) & ~(SBC_BLOCK_ALIGNMENT-1);
|
||
|
uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
|
||
|
uiAlignFillBytes = ulDataSize - ulDataBlockSize_p;
|
||
|
|
||
|
ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
|
||
|
ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
|
||
|
|
||
|
|
||
|
// reserve the needed memory for the write operation to do now
|
||
|
// and make necessary adjustments in the circular buffer header
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
// check if there is sufficient memory available to store
|
||
|
// the new data
|
||
|
fRes = uiFullBlockSize <= (pShbCirBuff->m_ulBufferDataSize - pShbCirBuff->m_ulDataInUse);
|
||
|
if ( fRes )
|
||
|
{
|
||
|
// set write pointer for the write operation to do now
|
||
|
// to the current write pointer of the circular buffer
|
||
|
ulWrIndex = pShbCirBuff->m_ulWrIndex;
|
||
|
|
||
|
// reserve the needed memory for the write operation to do now
|
||
|
pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
|
||
|
|
||
|
// set new write pointer behind the reserved memory
|
||
|
// for the write operation to do now
|
||
|
pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
|
||
|
pShbCirBuff->m_ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
|
||
|
|
||
|
// increment number of currently (parallel running)
|
||
|
// write operations
|
||
|
pShbCirBuff->m_ulNumOfWriteJobs++;
|
||
|
}
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
|
||
|
|
||
|
if ( !fRes )
|
||
|
{
|
||
|
ShbError = kShbBufferFull;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// copy the data to the circular buffer
|
||
|
// (the copy process itself will be done outside of any
|
||
|
// critical/locked section)
|
||
|
pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
|
||
|
|
||
|
// write real size of current block (incl. alignment fill bytes)
|
||
|
*(tShbCirBlockSize*)(pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
|
||
|
ulWrIndex += sizeof(tShbCirBlockSize);
|
||
|
ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
|
||
|
|
||
|
if (ulWrIndex + ulDataBlockSize_p <= pShbCirBuff->m_ulBufferDataSize)
|
||
|
{
|
||
|
// linear write operation
|
||
|
memcpy (pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulDataBlockSize_p);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// wrap-around write operation
|
||
|
ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
|
||
|
memcpy (pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulChunkSize);
|
||
|
memcpy (pShbCirDataPtr, pScrDataPtr + ulChunkSize, ulDataBlockSize_p - ulChunkSize);
|
||
|
}
|
||
|
|
||
|
|
||
|
// adjust header information for circular buffer with properties
|
||
|
// of the wiritten data block
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
pShbCirBuff->m_ulDataApended += uiFullBlockSize;
|
||
|
pShbCirBuff->m_ulBlocksApended ++;
|
||
|
|
||
|
// decrement number of currently (parallel running) write operations
|
||
|
if ( !--pShbCirBuff->m_ulNumOfWriteJobs )
|
||
|
{
|
||
|
// if there is no other write process running then
|
||
|
// set new size of readable (complete written) data and
|
||
|
// adjust number of readable blocks
|
||
|
pShbCirBuff->m_ulDataReadable += pShbCirBuff->m_ulDataApended;
|
||
|
pShbCirBuff->m_ulBlocksReadable += pShbCirBuff->m_ulBlocksApended;
|
||
|
|
||
|
pShbCirBuff->m_ulDataApended = 0;
|
||
|
pShbCirBuff->m_ulBlocksApended = 0;
|
||
|
|
||
|
fSignalNewData = TRUE;
|
||
|
fSignalReset = pShbCirBuff->m_fBufferLocked;
|
||
|
}
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
|
||
|
|
||
|
// signal new data event to a potentially reading application
|
||
|
if ( fSignalNewData )
|
||
|
{
|
||
|
ShbError2 = ShbIpcSignalNewData (pShbInstance_p);
|
||
|
if (ShbError == kShbOk)
|
||
|
{
|
||
|
ShbError = ShbError2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// signal that the last write job has been finished to allow
|
||
|
// a waiting application to reset the buffer now
|
||
|
if ( fSignalReset )
|
||
|
{
|
||
|
ShbError2 = ShbIpcSignalJobReady (pShbInstance_p);
|
||
|
if (ShbError == kShbOk)
|
||
|
{
|
||
|
ShbError = ShbError2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Allocate block within the Circular Shared Buffer for chunk writing
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
INLINE_FUNCTION tShbError ShbCirAllocDataBlock (
|
||
|
tShbInstance pShbInstance_p,
|
||
|
tShbCirChunk* pShbCirChunk_p,
|
||
|
unsigned long ulDataBufferSize_p)
|
||
|
{
|
||
|
|
||
|
tShbCirBuff* pShbCirBuff;
|
||
|
tShbCirBlockSize ShbCirBlockSize;
|
||
|
unsigned int uiFullBlockSize;
|
||
|
unsigned int uiAlignFillBytes;
|
||
|
unsigned char* pShbCirDataPtr;
|
||
|
unsigned long ulDataSize;
|
||
|
unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
|
||
|
tShbError ShbError;
|
||
|
int fRes;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL))
|
||
|
{
|
||
|
ShbError = kShbInvalidArg;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if (ulDataBufferSize_p == 0)
|
||
|
{
|
||
|
ShbError = kShbInvalidArg;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if (ulDataBufferSize_p > SBC_MAX_BLOCK_SIZE)
|
||
|
{
|
||
|
ShbError = kShbExceedDataSizeLimit;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
|
||
|
ShbError = kShbOk;
|
||
|
|
||
|
if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
|
||
|
{
|
||
|
ShbError = kShbInvalidBufferType;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// calculate data block size in circular buffer
|
||
|
ulDataSize = (ulDataBufferSize_p + (SBC_BLOCK_ALIGNMENT-1)) & ~(SBC_BLOCK_ALIGNMENT-1);
|
||
|
uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
|
||
|
uiAlignFillBytes = ulDataSize - ulDataBufferSize_p;
|
||
|
|
||
|
ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
|
||
|
ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
|
||
|
|
||
|
|
||
|
// reserve the needed memory for the write operation to do now
|
||
|
// and make necessary adjustments in the circular buffer header
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
// check if there is sufficient memory available to store
|
||
|
// the new data
|
||
|
fRes = (uiFullBlockSize <= (pShbCirBuff->m_ulBufferDataSize - pShbCirBuff->m_ulDataInUse));
|
||
|
if ( fRes )
|
||
|
{
|
||
|
// set write pointer for the write operation to do now
|
||
|
// to the current write pointer of the circular buffer
|
||
|
ulWrIndex = pShbCirBuff->m_ulWrIndex;
|
||
|
|
||
|
// reserve the needed memory for the write operation to do now
|
||
|
pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
|
||
|
|
||
|
// set new write pointer behind the reserved memory
|
||
|
// for the write operation to do now
|
||
|
pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
|
||
|
pShbCirBuff->m_ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
|
||
|
|
||
|
// increment number of currently (parallel running)
|
||
|
// write operations
|
||
|
pShbCirBuff->m_ulNumOfWriteJobs++;
|
||
|
}
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
|
||
|
|
||
|
if ( !fRes )
|
||
|
{
|
||
|
ShbError = kShbBufferFull;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// setup header information for allocated buffer
|
||
|
pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
|
||
|
|
||
|
// write real size of current block (incl. alignment fill bytes)
|
||
|
*(tShbCirBlockSize*)(pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
|
||
|
ulWrIndex += sizeof(tShbCirBlockSize);
|
||
|
ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
|
||
|
|
||
|
// setup chunk descriptor
|
||
|
pShbCirChunk_p->m_uiFullBlockSize = uiFullBlockSize;
|
||
|
pShbCirChunk_p->m_ulAvailableSize = ulDataBufferSize_p;
|
||
|
pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
|
||
|
pShbCirChunk_p->m_fBufferCompleted = FALSE;
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Write data chunk into an allocated buffer of the Circular Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
INLINE_FUNCTION tShbError ShbCirWriteDataChunk (
|
||
|
tShbInstance pShbInstance_p,
|
||
|
tShbCirChunk* pShbCirChunk_p,
|
||
|
const void* pSrcDataChunk_p,
|
||
|
unsigned long ulDataChunkSize_p,
|
||
|
unsigned int* pfBufferCompleted_p)
|
||
|
{
|
||
|
|
||
|
tShbCirBuff* pShbCirBuff;
|
||
|
unsigned char* pShbCirDataPtr;
|
||
|
unsigned char* pScrDataPtr;
|
||
|
unsigned long ulSubChunkSize;
|
||
|
unsigned long ulWrIndex;
|
||
|
unsigned int fBufferCompleted;
|
||
|
unsigned int fSignalNewData;
|
||
|
unsigned int fSignalReset;
|
||
|
tShbError ShbError;
|
||
|
tShbError ShbError2;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL) || (pfBufferCompleted_p == NULL))
|
||
|
{
|
||
|
ShbError = kShbInvalidArg;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if ((pSrcDataChunk_p == NULL) || (ulDataChunkSize_p == 0))
|
||
|
{
|
||
|
// nothing to do here
|
||
|
ShbError = kShbOk;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if ( pShbCirChunk_p->m_fBufferCompleted )
|
||
|
{
|
||
|
ShbError = kShbBufferAlreadyCompleted;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if (ulDataChunkSize_p > pShbCirChunk_p->m_ulAvailableSize)
|
||
|
{
|
||
|
ShbError = kShbExceedDataSizeLimit;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
|
||
|
pScrDataPtr = (unsigned char*)pSrcDataChunk_p;
|
||
|
fSignalNewData = FALSE;
|
||
|
fSignalReset = FALSE;
|
||
|
ShbError = kShbOk;
|
||
|
|
||
|
if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
|
||
|
{
|
||
|
ShbError = kShbInvalidBufferType;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
ulWrIndex = pShbCirChunk_p->m_ulWrIndex;
|
||
|
|
||
|
|
||
|
// copy the data to the circular buffer
|
||
|
// (the copy process itself will be done outside of any
|
||
|
// critical/locked section)
|
||
|
pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
|
||
|
|
||
|
|
||
|
if (ulWrIndex + ulDataChunkSize_p <= pShbCirBuff->m_ulBufferDataSize)
|
||
|
{
|
||
|
// linear write operation
|
||
|
memcpy (pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulDataChunkSize_p);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// wrap-around write operation
|
||
|
ulSubChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
|
||
|
memcpy (pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulSubChunkSize);
|
||
|
memcpy (pShbCirDataPtr, pScrDataPtr + ulSubChunkSize, ulDataChunkSize_p - ulSubChunkSize);
|
||
|
}
|
||
|
|
||
|
|
||
|
// adjust chunk descriptor
|
||
|
ulWrIndex += ulDataChunkSize_p;
|
||
|
ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
|
||
|
|
||
|
pShbCirChunk_p->m_ulAvailableSize -= ulDataChunkSize_p;
|
||
|
pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
|
||
|
|
||
|
fBufferCompleted = (pShbCirChunk_p->m_ulAvailableSize == 0);
|
||
|
pShbCirChunk_p->m_fBufferCompleted = fBufferCompleted;
|
||
|
|
||
|
|
||
|
// if the complete allocated buffer is filled with data then
|
||
|
// adjust header information for circular buffer with properties
|
||
|
// of the wiritten data block
|
||
|
if ( fBufferCompleted )
|
||
|
{
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
pShbCirBuff->m_ulDataApended += pShbCirChunk_p->m_uiFullBlockSize;
|
||
|
pShbCirBuff->m_ulBlocksApended ++;
|
||
|
|
||
|
// decrement number of currently (parallel running) write operations
|
||
|
if ( !--pShbCirBuff->m_ulNumOfWriteJobs )
|
||
|
{
|
||
|
// if there is no other write process running then
|
||
|
// set new size of readable (complete written) data and
|
||
|
// adjust number of readable blocks
|
||
|
pShbCirBuff->m_ulDataReadable += pShbCirBuff->m_ulDataApended;
|
||
|
pShbCirBuff->m_ulBlocksReadable += pShbCirBuff->m_ulBlocksApended;
|
||
|
|
||
|
pShbCirBuff->m_ulDataApended = 0;
|
||
|
pShbCirBuff->m_ulBlocksApended = 0;
|
||
|
|
||
|
fSignalNewData = TRUE;
|
||
|
fSignalReset = pShbCirBuff->m_fBufferLocked;
|
||
|
}
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
}
|
||
|
|
||
|
|
||
|
// signal new data event to a potentially reading application
|
||
|
if ( fSignalNewData )
|
||
|
{
|
||
|
ShbError2 = ShbIpcSignalNewData (pShbInstance_p);
|
||
|
if (ShbError == kShbOk)
|
||
|
{
|
||
|
ShbError = ShbError2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// signal that the last write job has been finished to allow
|
||
|
// a waiting application to reset the buffer now
|
||
|
if ( fSignalReset )
|
||
|
{
|
||
|
ShbError2 = ShbIpcSignalJobReady (pShbInstance_p);
|
||
|
if (ShbError == kShbOk)
|
||
|
{
|
||
|
ShbError = ShbError2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
*pfBufferCompleted_p = fBufferCompleted;
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Read data block from Circular Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
INLINE_FUNCTION tShbError ShbCirReadDataBlock (
|
||
|
tShbInstance pShbInstance_p,
|
||
|
void* pDstDataBlock_p,
|
||
|
unsigned long ulRdBuffSize_p,
|
||
|
unsigned long* pulDataBlockSize_p)
|
||
|
{
|
||
|
|
||
|
tShbCirBuff* pShbCirBuff;
|
||
|
tShbCirBlockSize ShbCirBlockSize;
|
||
|
unsigned long ulDataReadable;
|
||
|
unsigned char* pShbCirDataPtr;
|
||
|
unsigned char* pDstDataPtr;
|
||
|
unsigned long ulDataSize = 0; // d.k. GCC complains about uninitialized variable otherwise
|
||
|
unsigned long ulChunkSize;
|
||
|
unsigned long ulRdIndex;
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL))
|
||
|
{
|
||
|
return (kShbInvalidArg);
|
||
|
}
|
||
|
|
||
|
if ((pDstDataBlock_p == NULL) || (ulRdBuffSize_p == 0))
|
||
|
{
|
||
|
// nothing to do here
|
||
|
ShbError = kShbOk;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
ShbError = kShbOk;
|
||
|
pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
|
||
|
pDstDataPtr = (unsigned char*)pDstDataBlock_p;
|
||
|
ulDataSize = 0;
|
||
|
|
||
|
if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
|
||
|
{
|
||
|
ShbError = kShbInvalidBufferType;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// get total number of readable bytes for the whole circular buffer
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
ulDataReadable = pShbCirBuff->m_ulDataReadable;
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
|
||
|
|
||
|
// if there are readable data available, then there must be at least
|
||
|
// one complete readable data block
|
||
|
if (ulDataReadable > 0)
|
||
|
{
|
||
|
// get pointer to start of data area and current read index
|
||
|
pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
|
||
|
ulRdIndex = pShbCirBuff->m_ulRdIndex;
|
||
|
|
||
|
// get real size of current block (incl. alignment fill bytes)
|
||
|
ShbCirBlockSize = *(tShbCirBlockSize*)(pShbCirDataPtr + ulRdIndex);
|
||
|
ulRdIndex += sizeof(tShbCirBlockSize);
|
||
|
ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
|
||
|
|
||
|
// get size of user data inside the current block
|
||
|
ulDataSize = ShbCirBlockSize.m_uiFullBlockSize - ShbCirBlockSize.m_uiAlignFillBytes;
|
||
|
ulDataSize -= sizeof(tShbCirBlockSize);
|
||
|
}
|
||
|
|
||
|
|
||
|
// ulDataSize = MIN(ulDataSize, ulRdBuffSize_p);
|
||
|
if (ulDataSize > ulRdBuffSize_p)
|
||
|
{
|
||
|
ulDataSize = ulRdBuffSize_p;
|
||
|
ShbError = kShbDataTruncated;
|
||
|
}
|
||
|
|
||
|
if (ulDataSize == 0)
|
||
|
{
|
||
|
// nothing to do here
|
||
|
ShbError = kShbNoReadableData;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// copy the data from the circular buffer
|
||
|
// (the copy process itself will be done outside of any
|
||
|
// critical/locked section)
|
||
|
if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize)
|
||
|
{
|
||
|
// linear read operation
|
||
|
memcpy (pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulDataSize);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// wrap-around read operation
|
||
|
ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
|
||
|
memcpy (pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulChunkSize);
|
||
|
memcpy (pDstDataPtr + ulChunkSize, pShbCirDataPtr, ulDataSize - ulChunkSize);
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifndef NDEBUG
|
||
|
{
|
||
|
tShbCirBlockSize ClrShbCirBlockSize;
|
||
|
|
||
|
if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize)
|
||
|
{
|
||
|
// linear buffer
|
||
|
memset (pShbCirDataPtr + ulRdIndex, 0xDD, ulDataSize);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// wrap-around read operation
|
||
|
ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
|
||
|
memset (pShbCirDataPtr + ulRdIndex, 0xDD, ulChunkSize);
|
||
|
memset (pShbCirDataPtr, 0xDD, ulDataSize - ulChunkSize);
|
||
|
}
|
||
|
|
||
|
ClrShbCirBlockSize.m_uiFullBlockSize = /*(unsigned int)*/ -1; // -1 = xFFFFFFF
|
||
|
ClrShbCirBlockSize.m_uiAlignFillBytes = /*(unsigned int)*/ -1; // -1 = Fxxxxxxx
|
||
|
*(tShbCirBlockSize*)(pShbCirDataPtr + pShbCirBuff->m_ulRdIndex) = ClrShbCirBlockSize;
|
||
|
}
|
||
|
#endif // #ifndef NDEBUG
|
||
|
|
||
|
|
||
|
// set new size of readable data, data in use, new read index
|
||
|
// and adjust number of readable blocks
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
pShbCirBuff->m_ulDataInUse -= ShbCirBlockSize.m_uiFullBlockSize;
|
||
|
pShbCirBuff->m_ulDataReadable -= ShbCirBlockSize.m_uiFullBlockSize;
|
||
|
pShbCirBuff->m_ulBlocksReadable --;
|
||
|
|
||
|
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
||
|
if ((pShbCirBuff->m_ulDataInUse == 0) && (pShbCirBuff->m_ulDataReadable == 0))
|
||
|
{
|
||
|
ASSERT(pShbCirBuff->m_ulBlocksReadable == 0);
|
||
|
|
||
|
pShbCirBuff->m_ulWrIndex = 0;
|
||
|
pShbCirBuff->m_ulRdIndex = 0;
|
||
|
}
|
||
|
else
|
||
|
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
||
|
{
|
||
|
pShbCirBuff->m_ulRdIndex += ShbCirBlockSize.m_uiFullBlockSize;
|
||
|
pShbCirBuff->m_ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
|
||
|
}
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
*pulDataBlockSize_p = ulDataSize;
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Get data size of next readable block from Circular Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
INLINE_FUNCTION tShbError ShbCirGetReadDataSize (
|
||
|
tShbInstance pShbInstance_p,
|
||
|
unsigned long* pulDataBlockSize_p)
|
||
|
{
|
||
|
|
||
|
tShbCirBuff* pShbCirBuff;
|
||
|
unsigned long ulDataReadable;
|
||
|
unsigned char* pShbCirDataPtr;
|
||
|
tShbCirBlockSize ShbCirBlockSize;
|
||
|
unsigned long ulDataSize;
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL))
|
||
|
{
|
||
|
return (kShbInvalidArg);
|
||
|
}
|
||
|
|
||
|
|
||
|
pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
|
||
|
ulDataSize = 0;
|
||
|
ShbError = kShbOk;
|
||
|
|
||
|
if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
|
||
|
{
|
||
|
ShbError = kShbInvalidBufferType;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// get total number of readable bytes for the whole circular buffer
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
ulDataReadable = pShbCirBuff->m_ulDataReadable;
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
|
||
|
|
||
|
// if there are readable data available, then there must be at least
|
||
|
// one complete readable data block
|
||
|
if (ulDataReadable > 0)
|
||
|
{
|
||
|
pShbCirDataPtr = &pShbCirBuff->m_Data + pShbCirBuff->m_ulRdIndex;
|
||
|
|
||
|
// get real size of current block (incl. alignment fill bytes)
|
||
|
ShbCirBlockSize = *(tShbCirBlockSize*)pShbCirDataPtr;
|
||
|
|
||
|
// get size of user data inside the current block
|
||
|
ulDataSize = ShbCirBlockSize.m_uiFullBlockSize - ShbCirBlockSize.m_uiAlignFillBytes;
|
||
|
ulDataSize -= sizeof(tShbCirBlockSize);
|
||
|
}
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
*pulDataBlockSize_p = ulDataSize;
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Get number of readable blocks from Circular Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
INLINE_FUNCTION tShbError ShbCirGetReadBlockCount (
|
||
|
tShbInstance pShbInstance_p,
|
||
|
unsigned long* pulDataBlockCount_p)
|
||
|
{
|
||
|
|
||
|
tShbCirBuff* pShbCirBuff;
|
||
|
unsigned long ulBlockCount;
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if ((pShbInstance_p == NULL) || (pulDataBlockCount_p == NULL))
|
||
|
{
|
||
|
ShbError = kShbInvalidArg;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
|
||
|
ulBlockCount = 0;
|
||
|
ShbError = kShbOk;
|
||
|
|
||
|
if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
|
||
|
{
|
||
|
ShbError = kShbInvalidBufferType;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
ulBlockCount = pShbCirBuff->m_ulBlocksReadable;
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
|
||
|
|
||
|
*pulDataBlockCount_p = ulBlockCount;
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Set application handler to signal new data for Circular Shared Buffer
|
||
|
// d.k.: new parameter priority as enum
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
INLINE_FUNCTION tShbError ShbCirSetSignalHandlerNewData (
|
||
|
tShbInstance pShbInstance_p,
|
||
|
tShbCirSigHndlrNewData pfnSignalHandlerNewData_p,
|
||
|
tShbPriority ShbPriority_p)
|
||
|
{
|
||
|
|
||
|
tShbCirBuff* pShbCirBuff;
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if (pShbInstance_p == NULL)
|
||
|
{
|
||
|
ShbError = kShbInvalidArg;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
|
||
|
ShbError = kShbOk;
|
||
|
|
||
|
if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
|
||
|
{
|
||
|
ShbError = kShbInvalidBufferType;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (pfnSignalHandlerNewData_p != NULL)
|
||
|
{
|
||
|
// set a new signal handler
|
||
|
if (pShbCirBuff->m_pfnSigHndlrNewData != NULL)
|
||
|
{
|
||
|
ShbError = kShbAlreadySignaling;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
pShbCirBuff->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
|
||
|
ShbError = ShbIpcStartSignalingNewData (pShbInstance_p, ShbCirSignalHandlerNewData, ShbPriority_p);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// remove existing signal handler
|
||
|
ShbError = ShbIpcStopSignalingNewData (pShbInstance_p);
|
||
|
if (pShbCirBuff->m_pfnSigHndlrNewData != NULL)
|
||
|
{
|
||
|
pShbCirBuff->m_pfnSigHndlrNewData (pShbInstance_p, 0);
|
||
|
}
|
||
|
pShbCirBuff->m_pfnSigHndlrNewData = NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#if !defined(INLINE_ENABLED)
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// DEBUG: Trace Circular Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
#ifndef NDEBUG
|
||
|
tShbError ShbCirTraceBuffer (
|
||
|
tShbInstance pShbInstance_p)
|
||
|
{
|
||
|
|
||
|
tShbCirBuff* pShbCirBuff;
|
||
|
char szMagigID[sizeof(SBC_MAGIC_ID)+1];
|
||
|
tShbCirBlockSize ShbCirBlockSize;
|
||
|
unsigned long ulDataReadable;
|
||
|
unsigned char* pShbCirDataPtr;
|
||
|
unsigned long ulBlockIndex;
|
||
|
unsigned int nBlockCount;
|
||
|
unsigned long ulDataSize;
|
||
|
unsigned long ulChunkSize;
|
||
|
unsigned long ulRdIndex;
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
TRACE0("\n\n##### Circular Shared Buffer #####\n");
|
||
|
|
||
|
// check arguments
|
||
|
if (pShbInstance_p == NULL)
|
||
|
{
|
||
|
TRACE1("\nERROR: invalid buffer address (0x%08lX)\n", (unsigned long)pShbInstance_p);
|
||
|
ShbError = kShbInvalidArg;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
|
||
|
ShbError = kShbOk;
|
||
|
|
||
|
if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
|
||
|
{
|
||
|
ShbError = kShbInvalidBufferType;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
*(unsigned long*) &szMagigID[0] = pShbCirBuff->m_ShbCirMagicID;
|
||
|
szMagigID[sizeof(SBC_MAGIC_ID)] = '\0';
|
||
|
|
||
|
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
TRACE1("\nBuffer Address: 0x%08lX\n", (unsigned long)pShbCirBuff);
|
||
|
|
||
|
TRACE0("\nHeader Info:");
|
||
|
TRACE2("\nMagigID: '%s' (%08lX)", szMagigID, pShbCirBuff->m_ShbCirMagicID);
|
||
|
TRACE1("\nBufferTotalSize: %4lu [Bytes]", pShbCirBuff->m_ulBufferTotalSize);
|
||
|
TRACE1("\nBufferDataSize: %4lu [Bytes]", pShbCirBuff->m_ulBufferDataSize);
|
||
|
TRACE1("\nWrIndex: %4lu", pShbCirBuff->m_ulWrIndex);
|
||
|
TRACE1("\nRdIndex: %4lu", pShbCirBuff->m_ulRdIndex);
|
||
|
TRACE1("\nNumOfWriteJobs: %4lu", pShbCirBuff->m_ulNumOfWriteJobs);
|
||
|
TRACE1("\nDataInUse: %4lu [Bytes]", pShbCirBuff->m_ulDataInUse);
|
||
|
TRACE1("\nDataApended: %4lu [Bytes]", pShbCirBuff->m_ulDataApended);
|
||
|
TRACE1("\nBlocksApended: %4lu", pShbCirBuff->m_ulBlocksApended);
|
||
|
TRACE1("\nDataReadable: %4lu [Bytes]", pShbCirBuff->m_ulDataReadable);
|
||
|
TRACE1("\nBlocksReadable: %4lu", pShbCirBuff->m_ulBlocksReadable);
|
||
|
TRACE1("\nSigHndlrNewData: %08lX", (unsigned long)pShbCirBuff->m_pfnSigHndlrNewData);
|
||
|
TRACE1("\nBufferLocked: %d", pShbCirBuff->m_fBufferLocked);
|
||
|
TRACE1("\nSigHndlrReset: %08lX", (unsigned long)pShbCirBuff->m_pfnSigHndlrReset);
|
||
|
|
||
|
ShbTraceDump (&pShbCirBuff->m_Data, pShbCirBuff->m_ulBufferDataSize,
|
||
|
0x00000000L, "\nData Area:");
|
||
|
|
||
|
|
||
|
ulDataReadable = pShbCirBuff->m_ulDataReadable;
|
||
|
nBlockCount = 1;
|
||
|
ulBlockIndex = pShbCirBuff->m_ulRdIndex;
|
||
|
|
||
|
while (ulDataReadable > 0)
|
||
|
{
|
||
|
TRACE1("\n\n--- Block #%u ---", nBlockCount);
|
||
|
|
||
|
// get pointer to start of data area and current read index
|
||
|
pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
|
||
|
ulRdIndex = ulBlockIndex;
|
||
|
|
||
|
// get real size of current block (incl. alignment fill bytes)
|
||
|
ShbCirBlockSize = *(tShbCirBlockSize*)(pShbCirDataPtr + ulRdIndex);
|
||
|
ulRdIndex += sizeof(tShbCirBlockSize);
|
||
|
ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
|
||
|
|
||
|
// get size of user data inside the current block
|
||
|
ulDataSize = ShbCirBlockSize.m_uiFullBlockSize - ShbCirBlockSize.m_uiAlignFillBytes;
|
||
|
ulDataSize -= sizeof(tShbCirBlockSize);
|
||
|
|
||
|
TRACE1("\nFull Data Size: %4u [Bytes] (incl. header and alignment fill bytes)", ShbCirBlockSize.m_uiFullBlockSize);
|
||
|
TRACE1("\nUser Data Size: %4lu [Bytes]", ulDataSize);
|
||
|
TRACE1("\nAlignment Fill Bytes: %4u [Bytes]", ShbCirBlockSize.m_uiAlignFillBytes);
|
||
|
|
||
|
|
||
|
if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize)
|
||
|
{
|
||
|
// linear data buffer
|
||
|
ShbTraceDump (pShbCirDataPtr + ulRdIndex, ulDataSize, 0x00000000L, NULL);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// wrap-around data buffer
|
||
|
ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
|
||
|
ShbTraceDump (pShbCirDataPtr + ulRdIndex, ulChunkSize, 0x00000000L, NULL);
|
||
|
ShbTraceDump (pShbCirDataPtr, ulDataSize - ulChunkSize, ulChunkSize, NULL);
|
||
|
}
|
||
|
|
||
|
nBlockCount++;
|
||
|
|
||
|
ulBlockIndex += ShbCirBlockSize.m_uiFullBlockSize;
|
||
|
ulBlockIndex %= pShbCirBuff->m_ulBufferDataSize;
|
||
|
|
||
|
ulDataReadable -= ShbCirBlockSize.m_uiFullBlockSize;
|
||
|
}
|
||
|
|
||
|
ASSERT(pShbCirBuff->m_ulBlocksReadable == nBlockCount-1);
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-------------------------------------------------------------------------//
|
||
|
// //
|
||
|
// L i n e a r S h a r e d B u f f e r //
|
||
|
// //
|
||
|
//-------------------------------------------------------------------------//
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Allocate Linear Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
tShbError ShbLinAllocBuffer (
|
||
|
unsigned long ulBufferSize_p,
|
||
|
const char* pszBufferID_p,
|
||
|
tShbInstance* ppShbInstance_p,
|
||
|
unsigned int* pfShbNewCreated_p)
|
||
|
{
|
||
|
|
||
|
tShbInstance pShbInstance;
|
||
|
tShbLinBuff* pShbLinBuff;
|
||
|
unsigned int fShbNewCreated;
|
||
|
unsigned long ulBufferDataSize;
|
||
|
unsigned long ulBufferTotalSize;
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL))
|
||
|
{
|
||
|
return (kShbInvalidArg);
|
||
|
}
|
||
|
|
||
|
|
||
|
// calculate length of memory to allocate
|
||
|
ulBufferDataSize = (ulBufferSize_p + (SBL_BLOCK_ALIGNMENT-1)) & ~(SBL_BLOCK_ALIGNMENT-1);
|
||
|
ulBufferTotalSize = ulBufferDataSize + sizeof(tShbLinBuff);
|
||
|
|
||
|
// allocate a new or open an existing shared buffer
|
||
|
ShbError = ShbIpcAllocBuffer (ulBufferTotalSize, pszBufferID_p,
|
||
|
&pShbInstance, &fShbNewCreated);
|
||
|
if (ShbError != kShbOk)
|
||
|
{
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if (pShbInstance == NULL)
|
||
|
{
|
||
|
ShbError = kShbOutOfMem;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// get pointer to shared buffer
|
||
|
pShbLinBuff = (tShbLinBuff*) ShbIpcGetShMemPtr (pShbInstance);
|
||
|
|
||
|
// if the shared buffer was new created, than this process has
|
||
|
// to initialize it, otherwise the buffer is already in use
|
||
|
// and *must not* be reseted
|
||
|
if ( fShbNewCreated )
|
||
|
{
|
||
|
#ifndef NDEBUG
|
||
|
{
|
||
|
memset (pShbLinBuff, 0xCC, ulBufferTotalSize);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
pShbLinBuff->m_ShbLinMagicID = SBL_MAGIC_ID;
|
||
|
pShbLinBuff->m_ulBufferTotalSize = ulBufferTotalSize;
|
||
|
pShbLinBuff->m_ulBufferDataSize = ulBufferDataSize;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID)
|
||
|
{
|
||
|
ShbError = kShbInvalidBufferType;
|
||
|
goto Exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
*ppShbInstance_p = pShbInstance;
|
||
|
*pfShbNewCreated_p = fShbNewCreated;
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Release Linear Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
tShbError ShbLinReleaseBuffer (
|
||
|
tShbInstance pShbInstance_p)
|
||
|
{
|
||
|
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if (pShbInstance_p == NULL)
|
||
|
{
|
||
|
ShbError = kShbOk;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
ShbError = ShbIpcReleaseBuffer (pShbInstance_p);
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif // !defined(INLINE_ENABLED)
|
||
|
|
||
|
#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Write data block to Linear Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
INLINE_FUNCTION tShbError ShbLinWriteDataBlock (
|
||
|
tShbInstance pShbInstance_p,
|
||
|
unsigned long ulDstBufferOffs_p,
|
||
|
const void* pSrcDataBlock_p,
|
||
|
unsigned long ulDataBlockSize_p)
|
||
|
{
|
||
|
|
||
|
tShbLinBuff* pShbLinBuff;
|
||
|
unsigned char* pShbLinDataPtr;
|
||
|
unsigned char* pScrDataPtr;
|
||
|
unsigned long ulBufferDataSize;
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if (pShbInstance_p == NULL)
|
||
|
{
|
||
|
ShbError = kShbInvalidArg;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0))
|
||
|
{
|
||
|
// nothing to do here
|
||
|
ShbError = kShbOk;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE)
|
||
|
{
|
||
|
ShbError = kShbExceedDataSizeLimit;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
pShbLinBuff = ShbLinGetBuffer (pShbInstance_p);
|
||
|
pScrDataPtr = (unsigned char*)pSrcDataBlock_p;
|
||
|
ShbError = kShbOk;
|
||
|
|
||
|
if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID)
|
||
|
{
|
||
|
ShbError = kShbInvalidBufferType;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// check if offeset and size for the write operation matches with
|
||
|
// the size of the shared buffer
|
||
|
ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
|
||
|
if ( (ulDstBufferOffs_p > ulBufferDataSize) ||
|
||
|
(ulDataBlockSize_p > ulBufferDataSize) ||
|
||
|
((ulDstBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize) )
|
||
|
{
|
||
|
ShbError = kShbDataOutsideBufferArea;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// copy the data to the linear buffer
|
||
|
// (the copy process will be done inside of any critical/locked section)
|
||
|
pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
|
||
|
pShbLinDataPtr += ulDstBufferOffs_p;
|
||
|
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
memcpy (pShbLinDataPtr, pScrDataPtr, ulDataBlockSize_p);
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Read data block from Linear Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
INLINE_FUNCTION tShbError ShbLinReadDataBlock (
|
||
|
tShbInstance pShbInstance_p,
|
||
|
void* pDstDataBlock_p,
|
||
|
unsigned long ulSrcBufferOffs_p,
|
||
|
unsigned long ulDataBlockSize_p)
|
||
|
{
|
||
|
|
||
|
tShbLinBuff* pShbLinBuff;
|
||
|
unsigned char* pShbLinDataPtr;
|
||
|
unsigned char* pDstDataPtr;
|
||
|
unsigned long ulBufferDataSize;
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if (pShbInstance_p == NULL)
|
||
|
{
|
||
|
ShbError = kShbInvalidArg;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if ((pDstDataBlock_p == NULL) || (ulDataBlockSize_p == 0))
|
||
|
{
|
||
|
// nothing to do here
|
||
|
ShbError = kShbOk;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE)
|
||
|
{
|
||
|
ShbError = kShbExceedDataSizeLimit;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
pShbLinBuff = ShbLinGetBuffer (pShbInstance_p);
|
||
|
pDstDataPtr = (unsigned char*)pDstDataBlock_p;
|
||
|
ShbError = kShbOk;
|
||
|
|
||
|
if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID)
|
||
|
{
|
||
|
ShbError = kShbInvalidBufferType;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// check if offeset and size for the read operation matches with
|
||
|
// the size of the shared buffer
|
||
|
ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
|
||
|
if ( (ulSrcBufferOffs_p > ulBufferDataSize) ||
|
||
|
(ulDataBlockSize_p > ulBufferDataSize) ||
|
||
|
((ulSrcBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize) )
|
||
|
{
|
||
|
ShbError = kShbDataOutsideBufferArea;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
// copy the data to the linear buffer
|
||
|
// (the copy process will be done inside of any critical/locked section)
|
||
|
pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
|
||
|
pShbLinDataPtr += ulSrcBufferOffs_p;
|
||
|
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
memcpy (pDstDataPtr, pShbLinDataPtr, ulDataBlockSize_p);
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#if !defined(INLINE_ENABLED)
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// DEBUG: Trace Linear Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
#ifndef NDEBUG
|
||
|
tShbError ShbLinTraceBuffer (
|
||
|
tShbInstance pShbInstance_p)
|
||
|
{
|
||
|
|
||
|
tShbLinBuff* pShbLinBuff;
|
||
|
char szMagigID[sizeof(SBL_MAGIC_ID)+1];
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
TRACE0("\n\n##### Linear Shared Buffer #####\n");
|
||
|
|
||
|
// check arguments
|
||
|
if (pShbInstance_p == NULL)
|
||
|
{
|
||
|
TRACE1("\nERROR: invalid buffer address (0x%08lX)\n", (unsigned long)pShbInstance_p);
|
||
|
ShbError = kShbInvalidArg;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
pShbLinBuff = ShbLinGetBuffer (pShbInstance_p);
|
||
|
ShbError = kShbOk;
|
||
|
|
||
|
if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID)
|
||
|
{
|
||
|
ShbError = kShbInvalidBufferType;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
|
||
|
*(unsigned int*) &szMagigID[0] = pShbLinBuff->m_ShbLinMagicID;
|
||
|
szMagigID[sizeof(SBL_MAGIC_ID)] = '\0';
|
||
|
|
||
|
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
TRACE1("\nBuffer Address: 0x%08lX\n", (unsigned long)pShbLinBuff);
|
||
|
|
||
|
TRACE0("\nHeader Info:");
|
||
|
TRACE2("\nMagigID: '%s' (%08X)", szMagigID, pShbLinBuff->m_ShbLinMagicID);
|
||
|
TRACE1("\nBufferTotalSize: %4lu [Bytes]", pShbLinBuff->m_ulBufferTotalSize);
|
||
|
TRACE1("\nBufferDataSize: %4lu [Bytes]", pShbLinBuff->m_ulBufferDataSize);
|
||
|
|
||
|
ShbTraceDump (&pShbLinBuff->m_Data, pShbLinBuff->m_ulBufferDataSize,
|
||
|
0x00000000L, "\nData Area:");
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
return (ShbError);
|
||
|
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Dump buffer contents
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
#ifndef NDEBUG
|
||
|
tShbError ShbTraceDump (
|
||
|
const unsigned char* pabStartAddr_p,
|
||
|
unsigned long ulDataSize_p,
|
||
|
unsigned long ulAddrOffset_p,
|
||
|
const char* pszInfoText_p)
|
||
|
{
|
||
|
|
||
|
const unsigned char* pabBuffData;
|
||
|
unsigned long ulBuffSize;
|
||
|
unsigned char bData;
|
||
|
int nRow;
|
||
|
int nCol;
|
||
|
|
||
|
|
||
|
// get pointer to buffer and length of buffer
|
||
|
pabBuffData = pabStartAddr_p;
|
||
|
ulBuffSize = ulDataSize_p;
|
||
|
|
||
|
|
||
|
if (pszInfoText_p != NULL)
|
||
|
{
|
||
|
TRACE0(pszInfoText_p);
|
||
|
}
|
||
|
|
||
|
// dump buffer contents
|
||
|
for (nRow=0; ; nRow++)
|
||
|
{
|
||
|
TRACE1("\n%08lX: ", (unsigned long)(nRow*0x10) + ulAddrOffset_p);
|
||
|
|
||
|
for (nCol=0; nCol<16; nCol++)
|
||
|
{
|
||
|
if ((unsigned long)nCol < ulBuffSize)
|
||
|
{
|
||
|
TRACE1("%02X ", (unsigned int)*(pabBuffData+nCol));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TRACE0(" ");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TRACE0(" ");
|
||
|
|
||
|
for (nCol=0; nCol<16; nCol++)
|
||
|
{
|
||
|
bData = *pabBuffData++;
|
||
|
if ((unsigned long)nCol < ulBuffSize)
|
||
|
{
|
||
|
if ((bData >= 0x20) && (bData < 0x7F))
|
||
|
{
|
||
|
TRACE1("%c", bData);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TRACE0(".");
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TRACE0(" ");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ulBuffSize > 16)
|
||
|
{
|
||
|
ulBuffSize -= 16;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
return (kShbOk);
|
||
|
|
||
|
}
|
||
|
#endif // #ifndef NDEBUG
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//=========================================================================//
|
||
|
// //
|
||
|
// P R I V A T E F U N C T I O N S //
|
||
|
// //
|
||
|
//=========================================================================//
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Handler to signal new data event for Circular Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
int ShbCirSignalHandlerNewData (
|
||
|
tShbInstance pShbInstance_p)
|
||
|
{
|
||
|
|
||
|
tShbCirBuff* pShbCirBuff;
|
||
|
unsigned long ulDataSize;
|
||
|
unsigned long ulBlockCount;
|
||
|
tShbError ShbError;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if (pShbInstance_p == NULL)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
|
||
|
ShbError = kShbOk;
|
||
|
|
||
|
if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
// call application handler
|
||
|
if (pShbCirBuff->m_pfnSigHndlrNewData != NULL)
|
||
|
{
|
||
|
/* do
|
||
|
{*/
|
||
|
ShbError = ShbCirGetReadDataSize (pShbInstance_p, &ulDataSize);
|
||
|
if ((ulDataSize > 0) && (ShbError == kShbOk))
|
||
|
{
|
||
|
pShbCirBuff->m_pfnSigHndlrNewData (pShbInstance_p, ulDataSize);
|
||
|
}
|
||
|
|
||
|
ShbError = ShbCirGetReadBlockCount (pShbInstance_p, &ulBlockCount);
|
||
|
/* }
|
||
|
while ((ulBlockCount > 0) && (ShbError == kShbOk));*/
|
||
|
}
|
||
|
|
||
|
// Return TRUE if there are pending blocks.
|
||
|
// In that case ShbIpc tries to call this function again immediately if there
|
||
|
// is no other filled shared buffer with higher priority.
|
||
|
return ((ulBlockCount > 0) && (ShbError == kShbOk));
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
// Handler to reset Circular Shared Buffer
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
void ShbCirSignalHandlerReset (
|
||
|
tShbInstance pShbInstance_p,
|
||
|
unsigned int fTimeOut_p)
|
||
|
{
|
||
|
|
||
|
tShbCirBuff* pShbCirBuff;
|
||
|
|
||
|
|
||
|
// check arguments
|
||
|
if (pShbInstance_p == NULL)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
pShbCirBuff = ShbCirGetBuffer (pShbInstance_p);
|
||
|
if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
// reset buffer header
|
||
|
if ( !fTimeOut_p )
|
||
|
{
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
pShbCirBuff->m_ulWrIndex = 0;
|
||
|
pShbCirBuff->m_ulRdIndex = 0;
|
||
|
pShbCirBuff->m_ulNumOfWriteJobs = 0;
|
||
|
pShbCirBuff->m_ulDataInUse = 0;
|
||
|
pShbCirBuff->m_ulDataApended = 0;
|
||
|
pShbCirBuff->m_ulBlocksApended = 0;
|
||
|
pShbCirBuff->m_ulDataReadable = 0;
|
||
|
pShbCirBuff->m_ulBlocksReadable = 0;
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
|
||
|
|
||
|
#ifndef NDEBUG
|
||
|
{
|
||
|
memset (&pShbCirBuff->m_Data, 0xCC, pShbCirBuff->m_ulBufferDataSize);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
// call application handler
|
||
|
if (pShbCirBuff->m_pfnSigHndlrReset != NULL)
|
||
|
{
|
||
|
pShbCirBuff->m_pfnSigHndlrReset (pShbInstance_p, fTimeOut_p);
|
||
|
}
|
||
|
|
||
|
|
||
|
// unlock buffer
|
||
|
ShbIpcEnterAtomicSection (pShbInstance_p);
|
||
|
{
|
||
|
pShbCirBuff->m_fBufferLocked = FALSE;
|
||
|
pShbCirBuff->m_pfnSigHndlrReset = NULL;
|
||
|
}
|
||
|
ShbIpcLeaveAtomicSection (pShbInstance_p);
|
||
|
|
||
|
|
||
|
return;
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
// EOF
|
||
|
|