📄 rpool.c
字号:
#ifdef __cplusplus
extern "C" {
#endif
/*
***********************************************************************************
NOTICE:
This document contains information that is proprietary to RADVISION LTD..
No part of this publication may be reproduced in any form whatsoever without
written prior approval by RADVISION LTD..
RADVISION LTD. reserves the right to revise this publication and make changes
without obligation to notify any person of such revisions or changes.
***********************************************************************************
*/
/*
rpool.c
memory allocation mechanism, implementation based on fixed size array
*/
#include "ra.h"
#include "rpool.h"
/*
An RPOOL node always has bit 0x40000000 used.
This is the case since RPOOL and RTREE are used in the same allocation space in the PVT,
and this bit is used to see which type of node is used in each case.
Each RPOOL node holds in its first parameter the location of the next block.
The last element node holds 0x60000000, ORd with the size used in the last block.
*/
/* MACRO Definitions */
#define RPOOL_LOCATION(p) ((int)p)
#define RETURNED_VALUE(p) (HRPOOLELEM)(p|0x40000000)
#define NODE_HANDLE(p) (p|0x40000000)
#define RPOOL_NODE_ID(p) ((int)p&~0x60000000)
#define IS_LAST_NODE(p) ((p)& 0x20000000)
#define GET_LAST_NODE_SIZE(p) ((p)&~0x20000000)
#define SET_LAST_NODE(p) ((p) |0x20000000)
#define rpoolGetNode(raH,location) ((rpoolElem *)raGet((raH),RPOOL_NODE_ID(location)))
#define INVALID_LOCATION(raH,location) (!((location) & 0x60000000) || (raElemIsVacant((HRA)(raH), RPOOL_NODE_ID(location))))
#define COMPARE_ERROR 0x80000000
#define RPOOL_NODE_SIZE(elemSize) ((int)((elemSize) + sizeof(int)))
#define RPOOL_ELEM_SIZE(nodeSize) ((int)((nodeSize) - sizeof(int)))
#define RPOOL_BLOCKS(size,elemSize) ((size)/(elemSize) + ( ((size)%(elemSize)) ? 1 : 0 ))
/************************************************************************
* rpoolElem
* Header of an element inside rpool
* nextBlock - Location of the next block for this allocation
* data - User's data information stored
************************************************************************/
typedef struct
{
int nextBlock;
char data;
} rpoolElem;
/************************************************************************
*
* Public functions
*
************************************************************************/
/************************************************************************
* rpoolConstruct
* purpose: Create an RPOOL object
* input : elemSize - Size of elements in the RPOOL in bytes
* maxNumOfBlocks - Number of blocks in RPOOL
* threadSafe - RV_TRUE to make allocations and deallocations
* thread-safe
* name - Name of RPOOL (used in log messages)
* output : none
* return : Handle to RPOOL constructed on success
* NULL on failure
************************************************************************/
HRPOOL rpoolConstruct(
IN int elemSize,
IN int maxNumOfBlocks,
IN RvBool threadSafe,
IN const char* name)
{
HRA raH;
if ((!elemSize) || (!maxNumOfBlocks))
return NULL;
if (!(raH = raConstruct(RPOOL_NODE_SIZE(elemSize), maxNumOfBlocks, threadSafe, name)) )
return NULL;
rpoolClear((HRPOOL)raH);
return (HRPOOL)raH;
}
/************************************************************************
* rpoolClear
* purpose: Clear the RPOOL from any allocations
* input : pool - RPOOL handle
* output : none
* return : none
************************************************************************/
void
rpoolClear(IN HRPOOL pool)
{
if (pool != NULL)
raClear((HRA)pool);
}
/************************************************************************
* rpoolDestruct
* purpose: Deallocate an RPOOL object
* input : pool - RPOOL handle
* output : none
* return : none
************************************************************************/
void rpoolDestruct(IN HRPOOL pool)
{
if (pool != NULL)
raDestruct((HRA)pool);
}
/************************************************************************
* rpoolAlloc
* purpose: Allocate a chunk of memory from RPOOL
* The allocation is automatically set to zero in all of its bytes
* input : pool - RPOOL handle
* size - Size of allocation in bytes
* output : none
* return : Pointer to memory chunk on success
* NULL on failure
************************************************************************/
HRPOOLELEM rpoolAlloc(
IN HRPOOL pool,
IN int size)
{
return rpoolAllocCopyExternal(pool, NULL, size);
}
/************************************************************************
* rpoolAllocCopyExternal
* purpose: Allocate a chunk of memory from RPOOL and set it to a specified
* value from a buffer in memory
* input : pool - RPOOL handle
* src - Source pointer of the external buffer set
* If NULL, then the memory allocated is set to zero
* size - Size of allocation in bytes
* output : none
* return : Pointer to memory chunk on success
* NULL on failure
************************************************************************/
HRPOOLELEM rpoolAllocCopyExternal(
IN HRPOOL pool,
IN const void* src,
IN int size)
{
HRA raH = (HRA)pool;
rpoolElem *elem=NULL, *newElem;
int numOfBlocks,numOfFreeBlocks;
int elemSize;
int i, cur, first=0;
if (( ! pool ) || ( size <= 0)) return NULL;
/* Calculate the number of blocks we're dealing with */
elemSize = RPOOL_ELEM_SIZE(raElemSize(raH));
numOfBlocks = RPOOL_BLOCKS(size,elemSize);
numOfFreeBlocks = raFreeSize(raH);
/* Make sure we've got enough room for it */
if (numOfFreeBlocks < numOfBlocks) return NULL;
/* Start adding blocks */
for(i = 0; i < numOfBlocks; i++)
{
/* Allocate another block */
if ( (cur = raAdd(raH, (RAElement *)&newElem)) < 0 )
{
/* This shouldn't happen ! */
if (elem != NULL)
{
/* Make sure this rpool element is valid even though it's an error */
elem->nextBlock = SET_LAST_NODE(0);
}
return NULL;
}
/* Link the last handle to the new one */
if (elem != NULL)
elem->nextBlock = NODE_HANDLE(cur);
else
first = cur;
elem = newElem; /* rpoolGetNode(raH,cur); */
elem->nextBlock = 0;
/* Fill/Clear the allocated memory chunk */
if (src != NULL)
{
/* We need to set from given external memory buffer */
if ((i == numOfBlocks-1) && (size % elemSize))
{
/* Last element - copy only the bytes that are left in it */
memcpy(&(elem->data), (char*)src+i*elemSize, (RvSize_t)size % elemSize);
}
else
{
/* Something in the middle. Copy it all */
memcpy(&(elem->data), (char*)src+i*elemSize, (RvSize_t)elemSize);
}
}
else
{
/* Clear the allocation */
memset(&(elem->data), 0, (RvSize_t)elemSize);
}
}
/* Set the last block as the last block */
elem->nextBlock = SET_LAST_NODE ( (size%elemSize) ? size%elemSize : elemSize );
/* Return the allocation */
return (RETURNED_VALUE(first));
}
/************************************************************************
* rpoolAllocCopyInternal
* purpose: Allocate a chunk of memory from RPOOL and duplicate its value
* from another allocation in RPOOL
* input : destPool- Destination RPOOL handle, where the new buffer will
* be allocated
* srcPool - Source RPOOL handle, where the buffer we copy from
* resides
* src - Source pointer of the internal buffer set
* It is actually an RPOOL allocation handle returned
* by rpoolAlloc() and other functions in RPOOL
* If NULL, then the memory allocated is set to zero
* size - Size of allocation in bytes
* output : none
* return : Pointer to memory chunk on success
* NULL on failure
************************************************************************/
HRPOOLELEM rpoolAllocCopyInternal(
IN HRPOOL destPool,
IN HRPOOL srcPool,
IN const void* src,
IN int size)
{
HRA destRa = (HRA)destPool;
HRA srcRa = (HRA)srcPool;
rpoolElem *elem=NULL, *elemSrc=NULL, *newElem;
int numOfBlocks,numOfFreeBlocks;
RvSize_t elemSize;
int i, cur, first=0;
if ((srcPool == NULL) || (destPool == NULL) || (size <= 0))
return NULL;
/* Get the source element */
if (src != NULL)
{
int location = RPOOL_LOCATION(src);
if (INVALID_LOCATION(srcRa,location))
return NULL;
elemSrc=rpoolGetNode(srcRa,location);
}
/* Calculate the number of blocks we're dealing with */
elemSize = RPOOL_ELEM_SIZE(raElemSize(srcRa));
numOfBlocks = RPOOL_BLOCKS(size,elemSize);
numOfFreeBlocks = raFreeSize(destRa);
/* Make sure we've got enough room for it */
if ( (!size) || (numOfFreeBlocks < numOfBlocks )) return NULL;
/* Start adding blocks */
for(i=0; i<numOfBlocks; i++)
{
/* Add an RPOOL block */
if ( (cur = raAdd(destRa, (RAElement *)&newElem)) < 0 )
{
if (elem != NULL)
{
/* Make sure this rpool element is valid */
elem->nextBlock = SET_LAST_NODE(0);
}
return NULL;
}
/* Link previous block to the new one */
if (elem)
elem->nextBlock = NODE_HANDLE(cur);
else
first=cur;
elem = newElem; /*rpoolGetNode(raH,cur); */
elem->nextBlock = 0;
/* Copy/Clear the allocated block */
if (src != NULL)
{
memcpy(&(elem->data), &(elemSrc->data), elemSize);
if (IS_LAST_NODE(elemSrc->nextBlock))
src=NULL;
else
elemSrc=rpoolGetNode(srcRa,elemSrc->nextBlock);
}
else
{
memset(&(elem->data), 0, elemSize);
}
}
elem->nextBlock = SET_LAST_NODE ( (size%elemSize) ? size%elemSize : elemSize );
return (RETURNED_VALUE(first));
}
/************************************************************************
* rpoolRealloc
* purpose: Reallocate chunk of memory, leaving any old bytes with the
* same value they had previously and setting new allocated
* bytes to zero.
* input : pool - RPOOL handle
* src - Element in RPOOL ot reallocate
* size - Size of allocation in bytes
* output : none
* return : Non-negative value on success, other on failure
************************************************************************/
int rpoolRealloc(
IN HRPOOL pool,
IN HRPOOLELEM ptr,
IN int size)
{
HRA raH = (HRA)pool;
int numOfBlocks;
int elemSize;
int count=0;
int contLocation, location;
rpoolElem *elem=NULL;
if(( ! pool ) || (! size))
return RV_ERROR_NULLPTR;
location = RPOOL_LOCATION(ptr);
elemSize = RPOOL_ELEM_SIZE(raElemSize(raH));
numOfBlocks = RPOOL_BLOCKS(size,elemSize);
/* Count the nodes in RPOOL that we're going to leave as is.
We might end up holding all of them if the reallocation is bigger than the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -