📄 ixosalbuffermgt.c
字号:
/**
* @file IxOsalBufferMgt.c
*
* @brief Default buffer pool management and buffer management
* Implementation.
*
* Design Notes:
*
* @par
* <COPYRIGHT_TAG>
*/
/*
* OS may choose to use default bufferMgt by defining
* IX_OSAL_USE_DEFAULT_BUFFER_MGT in IxOsalOsBufferMgt.h
*/
#include "IxOsal.h"
#define IX_OSAL_BUFFER_FREE_PROTECTION /* Define this to enable Illegal MBuf Freed Protection*/
/*
* The implementation is only used when the following
* is defined.
*/
#ifdef IX_OSAL_USE_DEFAULT_BUFFER_MGT
#define IX_OSAL_MBUF_SYS_SIGNATURE (0x8BADF00D)
#define IX_OSAL_MBUF_SYS_SIGNATURE_MASK (0xEFFFFFFF)
#define IX_OSAL_MBUF_USED_FLAG (0x10000000)
#define IX_OSAL_MBUF_SYS_SIGNATURE_INIT(bufPtr) IX_OSAL_MBUF_SIGNATURE (bufPtr) = (UINT32)IX_OSAL_MBUF_SYS_SIGNATURE
/*
* This implementation is protect, the buffer pool management's ixOsalMBufFree
* against an invalid MBUF pointer argument that already has been freed earlier
* or in other words resides in the free pool of MBUFs. This added feature,
* checks the MBUF "USED" FLAG. The Flag tells if the MBUF is still not freed
* back to the Buffer Pool.
* Disable this feature for performance reasons by undef
* IX_OSAL_BUFFER_FREE_PROTECTION macro.
*/
#ifdef IX_OSAL_BUFFER_FREE_PROTECTION /*IX_OSAL_BUFFER_FREE_PROTECTION With Buffer Free protection*/
#define IX_OSAL_MBUF_GET_SYS_SIGNATURE(bufPtr) (IX_OSAL_MBUF_SIGNATURE (bufPtr)&(IX_OSAL_MBUF_SYS_SIGNATURE_MASK) )
#define IX_OSAL_MBUF_SET_SYS_SIGNATURE(bufPtr) do { \
IX_OSAL_MBUF_SIGNATURE (bufPtr)&(~IX_OSAL_MBUF_SYS_SIGNATURE_MASK);\
IX_OSAL_MBUF_SIGNATURE (bufPtr)|=IX_OSAL_MBUF_SYS_SIGNATURE; \
}while(0)
#define IX_OSAL_MBUF_SET_USED_FLAG(bufPtr) IX_OSAL_MBUF_SIGNATURE (bufPtr)|=IX_OSAL_MBUF_USED_FLAG
#define IX_OSAL_MBUF_CLEAR_USED_FLAG(bufPtr) IX_OSAL_MBUF_SIGNATURE (bufPtr)&=~IX_OSAL_MBUF_USED_FLAG
#define IX_OSAL_MBUF_ISSET_USED_FLAG(bufPtr) (IX_OSAL_MBUF_SIGNATURE (bufPtr)&IX_OSAL_MBUF_USED_FLAG)
#else
#define IX_OSAL_MBUF_GET_SYS_SIGNATURE(bufPtr) IX_OSAL_MBUF_SIGNATURE (bufPtr)
#define IX_OSAL_MBUF_SET_SYS_SIGNATURE(bufPtr) IX_OSAL_MBUF_SIGNATURE (bufPtr) = IX_OSAL_MBUF_SYS_SIGNATURE
#endif /*IX_OSAL_BUFFER_FREE_PROTECTION With Buffer Free protection*/
/*
* Variable declarations global to this file only. Externs are followed by
* static variables.
*/
/*
* A unit of 32, used to provide bit-shift for pool
* management. Needs some work if users want more than 32 pools.
*/
#define IX_OSAL_BUFF_FREE_BITS 32
PRIVATE UINT32 ixOsalBuffFreePools[IX_OSAL_MBUF_MAX_POOLS /
IX_OSAL_BUFF_FREE_BITS];
PUBLIC IX_OSAL_MBUF_POOL ixOsalBuffPools[IX_OSAL_MBUF_MAX_POOLS];
PRIVATE INT32 ixOsalBuffPoolsInUse = 0;
PRIVATE BOOL ixOsalBuffMgmtInited=FALSE;
PRIVATE IxOsalMutex ixOsalBufferFreePoolsAccess;
#ifdef __linux_user
PRIVATE IxOsalMutex ixOsalBufferPoolAccess[IX_OSAL_MBUF_MAX_POOLS];
#endif /* __linux_user */
#ifdef IX_OSAL_BUFFER_ALLOC_SEPARATELY
PRIVATE IX_OSAL_MBUF *
ixOsalBuffPoolMbufInit (UINT32 mbufSizeAligned,
UINT32 dataSizeAligned,
IX_OSAL_MBUF_POOL *poolPtr);
#endif
PRIVATE IX_OSAL_MBUF_POOL * ixOsalPoolAlloc (VOID);
/*
* Function definition: ixOsalPoolAlloc
*/
/****************************/
PRIVATE IX_OSAL_MBUF_POOL *
ixOsalPoolAlloc (VOID)
{
register UINT32 i = 0;
if (ixOsalBuffMgmtInited == FALSE)
{
ixOsalBuffMgmtInited = TRUE;
ixOsalMutexInit(&ixOsalBufferFreePoolsAccess);
}
/*
* Scan for the first free buffer. Free buffers are indicated by 0
* on the corrsponding bit in ixOsalBuffFreePools.
*/
if (ixOsalBuffPoolsInUse >= IX_OSAL_MBUF_MAX_POOLS)
{
/*
* Fail to grab a ptr this time
*/
return NULL;
}
/*
* Lock the shared resource before accessing it
*/
ixOsalMutexLock(&ixOsalBufferFreePoolsAccess, IX_OSAL_WAIT_FOREVER);
while (ixOsalBuffFreePools[i / IX_OSAL_BUFF_FREE_BITS] &
(1 << (i % IX_OSAL_BUFF_FREE_BITS)))
i++;
/*
* Free buffer found. Mark it as busy and initialize.
*/
ixOsalBuffFreePools[i / IX_OSAL_BUFF_FREE_BITS] |=
(1 << (i % IX_OSAL_BUFF_FREE_BITS));
/*
* Unlock the shared resource after accessing it
*/
ixOsalMutexUnlock(&ixOsalBufferFreePoolsAccess);
ixOsalMemSet (&ixOsalBuffPools[i], 0, sizeof (IX_OSAL_MBUF_POOL));
ixOsalBuffPools[i].poolIdx = i;
ixOsalBuffPoolsInUse++;
return &ixOsalBuffPools[i];
}
#ifdef IX_OSAL_BUFFER_ALLOC_SEPARATELY
/*
* mbufSize, would be made to align to cache boundary in kernel space,
* similarly for dataSize.
*/
PRIVATE IX_OSAL_MBUF *
ixOsalBuffPoolMbufInit (UINT32 mbufSize,
UINT32 dataSize,
IX_OSAL_MBUF_POOL *poolPtr)
{
UINT8 *dataPtr;
IX_OSAL_MBUF *realMbufPtr;
/* Allocate cache-aligned memory for mbuf header */
realMbufPtr = (IX_OSAL_MBUF *) IX_OSAL_BUFF_MEM_ALLOC (mbufSize);
IX_OSAL_ASSERT (realMbufPtr != NULL);
ixOsalMemSet (realMbufPtr, 0, mbufSize);
/* Allocate cache-aligned memory for mbuf data */
dataPtr = (UINT8 *) IX_OSAL_BUFF_MEM_ALLOC (dataSize);
IX_OSAL_ASSERT (dataPtr != NULL);
ixOsalMemSet (dataPtr, 0, dataSize);
/* Fill in mbuf header fields */
IX_OSAL_MBUF_MDATA (realMbufPtr) = dataPtr;
IX_OSAL_MBUF_ALLOCATED_BUFF_DATA (realMbufPtr) = (UINT32)dataPtr;
IX_OSAL_MBUF_MLEN (realMbufPtr) = dataSize;
IX_OSAL_MBUF_ALLOCATED_BUFF_LEN (realMbufPtr) = dataSize;
IX_OSAL_MBUF_NET_POOL (realMbufPtr) = (IX_OSAL_MBUF_POOL *) poolPtr;
IX_OSAL_MBUF_SYS_SIGNATURE_INIT(realMbufPtr);
/* update some statistical information */
poolPtr->mbufMemSize += mbufSize;
poolPtr->dataMemSize += dataSize;
return realMbufPtr;
}
#endif /* #ifdef IX_OSAL_BUFFER_ALLOC_SEPARATELY */
/*
* Function definition: ixOsalBuffPoolInit
*/
PUBLIC IX_OSAL_MBUF_POOL *
ixOsalPoolInit (UINT32 count, UINT32 size, const char *name)
{
/* These variables are only used if IX_OSAL_BUFFER_ALLOC_SEPARATELY
* is defined .
*/
#ifdef IX_OSAL_BUFFER_ALLOC_SEPARATELY
UINT32 i, mbufSize, dataSize;
IX_OSAL_MBUF *currentMbufPtr = NULL;
#else /* IX_OSAL_BUFFER_ALLOC_SEPARATELY */
VOID *poolBufPtr;
VOID *poolDataPtr;
INT32 mbufMemSize;
INT32 dataMemSize;
#endif /* IX_OSAL_BUFFER_ALLOC_SEPARATELY */
IX_OSAL_MBUF_POOL *poolPtr = NULL;
if ((UINT8 *)name == NULL)
{
ixOsalLog (IX_OSAL_LOG_LVL_WARNING,
IX_OSAL_LOG_DEV_STDOUT,
"ixOsalPoolInit(): Failed due to NULL name\n", 0, 0, 0, 0, 0, 0);
return NULL;
}
if (count <= 0)
{
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
IX_OSAL_LOG_DEV_STDOUT,
"ixOsalPoolInit(): count = 0 \n", 0, 0, 0, 0, 0, 0);
return NULL;
}
if (strlen (name) > IX_OSAL_MBUF_POOL_NAME_LEN)
{
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
IX_OSAL_LOG_DEV_STDOUT,
"ixOsalPoolInit(): "
"ERROR - name length should be no greater than %d \n",
IX_OSAL_MBUF_POOL_NAME_LEN, 0, 0, 0, 0, 0);
return NULL;
}
/* OS can choose whether to allocate all buffers all together (if it
* can handle a huge single alloc request), or to allocate buffers
* separately by the defining IX_OSAL_BUFFER_ALLOC_SEPARATELY.
*/
#ifdef IX_OSAL_BUFFER_ALLOC_SEPARATELY
/* Get a pool Ptr */
poolPtr = ixOsalPoolAlloc ();
#ifdef __linux_user
ixOsalMutexInit(&ixOsalBufferPoolAccess[poolPtr->poolIdx]);
#endif /* __linux_user */
if (poolPtr == NULL)
{
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
IX_OSAL_LOG_DEV_STDOUT,
"ixOsalPoolInit(): " "Fail to Get PoolPtr \n", 0, 0, 0, 0, 0, 0);
return NULL;
}
/*
* In Kernel space allocate cache aligned boundary. But in user
* space these macros would return the value of the input without
* any modification
*/
mbufSize = IX_OSAL_MBUF_POOL_SIZE_ALIGN (sizeof (IX_OSAL_MBUF));
dataSize = IX_OSAL_MBUF_POOL_SIZE_ALIGN(size);
poolPtr->nextFreeBuf = NULL;
poolPtr->mbufMemPtr = NULL;
poolPtr->dataMemPtr = NULL;
poolPtr->bufDataSize = dataSize;
poolPtr->totalBufsInPool = count;
poolPtr->poolAllocType = IX_OSAL_MBUF_POOL_TYPE_SYS_ALLOC;
strcpy (poolPtr->name, name);
for (i = 0; i < count; i++)
{
/* create an mbuf */
currentMbufPtr = ixOsalBuffPoolMbufInit (mbufSize,
dataSize,
poolPtr);
#ifdef IX_OSAL_BUFFER_FREE_PROTECTION
/* Set the Buffer USED Flag. If not, ixOsalMBufFree will fail.
ixOsalMbufFree used here is in a special case whereby, it's
used to add MBUF to the Pool. By specification, ixOsalMbufFree
deallocates an allocated MBUF from Pool.
*/
IX_OSAL_MBUF_SET_USED_FLAG(currentMbufPtr);
#endif
/* Add it to the pool */
ixOsalMbufFree (currentMbufPtr);
/*
* Flush the pool information to RAM. If caching is done then
* flush information explicitly
*/
IX_OSAL_BUFF_FLUSH_INFO(currentMbufPtr, mbufSize);
}
/*
* update the number of free buffers in the pool
*/
poolPtr->freeBufsInPool = count;
#else
/* Otherwise allocate buffers in a continuous block fashion */
poolBufPtr = IX_OSAL_MBUF_POOL_MBUF_AREA_ALLOC (count, mbufMemSize);
IX_OSAL_ASSERT (poolBufPtr != NULL);
poolDataPtr = IX_OSAL_MBUF_POOL_DATA_AREA_ALLOC (count, size, dataMemSize);
IX_OSAL_ASSERT (poolDataPtr != NULL);
poolPtr = ixOsalNoAllocPoolInit (poolBufPtr, poolDataPtr, count, size, name);
if (poolPtr == NULL)
{
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
IX_OSAL_LOG_DEV_STDOUT,
"ixOsalPoolInit(): " "Fail to get pool ptr \n", 0, 0, 0, 0, 0, 0);
return NULL;
}
poolPtr->poolAllocType = IX_OSAL_MBUF_POOL_TYPE_SYS_ALLOC;
#endif /* IX_OSAL_BUFFER_ALLOC_SEPARATELY */
return poolPtr;
}
PUBLIC IX_OSAL_MBUF_POOL *
ixOsalNoAllocPoolInit (VOID *poolBufPtr, VOID *poolDataPtr, UINT32 count, UINT32 size, const char *name)
{
UINT32 i, mbufSize, dataSize;
IX_OSAL_MBUF *currentMbufPtr = NULL;
IX_OSAL_MBUF *nextMbufPtr = NULL;
IX_OSAL_MBUF_POOL *poolPtr = NULL;
/*
* check parameters
*/
if (poolBufPtr == NULL)
{
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
IX_OSAL_LOG_DEV_STDOUT,
"ixOsalNoAllocPoolInit(): "
"ERROR - NULL poolBufPtr \n", 0, 0, 0, 0, 0, 0);
return NULL;
}
if ((UINT8 *)name == NULL)
{
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
IX_OSAL_LOG_DEV_STDOUT,
"ixOsalNoAllocPoolInit(): "
"ERROR - NULL name ptr \n", 0, 0, 0, 0, 0, 0);
return NULL;
}
if (count <= 0)
{
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
IX_OSAL_LOG_DEV_STDOUT,
"ixOsalNoAllocPoolInit(): "
"ERROR - count must > 0 \n", 0, 0, 0, 0, 0, 0);
return NULL;
}
if (strlen (name) > IX_OSAL_MBUF_POOL_NAME_LEN)
{
ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
IX_OSAL_LOG_DEV_STDOUT,
"ixOsalNoAllocPoolInit(): "
"ERROR - name length should be no greater than %d \n",
IX_OSAL_MBUF_POOL_NAME_LEN, 0, 0, 0, 0, 0);
return NULL;
}
poolPtr = ixOsalPoolAlloc ();
if (poolPtr == NULL)
{
return NULL;
}
#ifdef __linux_user
ixOsalMutexInit(&ixOsalBufferPoolAccess[poolPtr->poolIdx]);
#endif /* __linux_user */
mbufSize = IX_OSAL_MBUF_POOL_SIZE_ALIGN (sizeof (IX_OSAL_MBUF));
/*
* Clear the mbuf memory area
*/
ixOsalMemSet (poolBufPtr, 0, mbufSize * count);
if (poolDataPtr != NULL)
{
dataSize = IX_OSAL_MBUF_POOL_SIZE_ALIGN(size);
/*
* Clear the data memory area
*/
ixOsalMemSet (poolDataPtr, 0, dataSize * count);
}
else
{
dataSize = 0;
}
/*
* Initialise pool fields
*/
strcpy ((poolPtr)->name, name);
poolPtr->dataMemPtr = poolDataPtr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -