📄 cm_mem.c
字号:
/********************************************************************20**
Name: Common Memory Manager
Type: C source file
Desc: C source code for the Commom Memory Manager module.
File: cm_mem.c
Sid: cm_mem.c 1.4 - 10/14/98 14:31:52
Prg: rm
*********************************************************************21*/
/************************************************************************
The following functions are provided in this file.
cmMmRegInit Memory Region Initialization.
cmMmRegDeInit Memory Region Deinitialization.
************************************************************************/
/* header include files (.h) */
#include "envopt.h" /* environment options */
#include "envdep.h" /* environment dependent */
#include "envind.h" /* environment independent */
#include "gen.h" /* general */
#include "ssi.h" /* system services */
#include "cm_mem.h" /* Common memory manager */
/* header/extern include files (.x) */
#include "gen.x" /* general */
#include "ssi.x" /* system services */
#include "cm_mem.x" /* Common memory manager */
/* local typedefs */
/* local externs */
/* forward references */
PRIVATE S16 cmAlloc ARGS((Void *regionCb, Size *size, U32 flags, Data **ptr));
PRIVATE S16 cmFree ARGS((Void *regionCb, Data *ptr, Size size));
PRIVATE S16 cmCtl ARGS((Void *regionCb, Event event, SMemCtl *memCtl));
PRIVATE S16 cmHeapAlloc ARGS((CmMmHeapCb *heapCb, Data **ptr, Size *size));
PRIVATE S16 cmHeapFree ARGS((CmMmHeapCb *heapCb, Data *ptr, Size size));
PRIVATE Void cmMmHeapInit ARGS((Data *memAddr, CmMmHeapCb *heapCb, Size size));
PRIVATE Void cmMmBktInit ARGS((Data **memAddr, CmMmRegCb *regCb,
CmMmRegCfg *cfg, U16 bktIdx, U16 *lstMapIdx));
PRIVATE S16 cmPrntMem ARGS((Void *regionCb, Size msgLen));
/* public variable declarations */
/* private variable declarations */
/*
*
* Fun: cmMmRegInit
*
* Desc: Configure the memory region for allocation. The function
* registers the memory region with System Service by calling
* SRegRegion.
*
*
* Ret: ROK - successful,
* RFAILED - unsuccessful.
*
* Notes: The memory owner calls this function to initialize the memory
* manager with the information of the memory region. Before
* calling this function, the memory owner should allocate memory
* for the memory region. The memory owner should also provide the
* memory for the control block needed by the memory manager. The
* memory owner should allocate the memory for the region control
* block as cachable memory. This may increase the average
* throughput in allocation and deallocation as the region control
* block is mostly accessed by the CMM.
*
* File: cm_mem.c
*
*/
#ifdef ANSI
PUBLIC S16 cmMmRegInit
(
Region region,
CmMmRegCb *regCb,
CmMmRegCfg *cfg
)
#else
PUBLIC S16 cmMmRegInit(region, regCb, cfg)
Region region;
CmMmRegCb *regCb;
CmMmRegCfg *cfg;
#endif
{
Data *memAddr;
U16 bktIdx;
U16 lstMapIdx;
#if (ERRCLASS & ERRCLS_INT_PAR)
Size lstQnSize;
Size bktBlkSize;
#endif
TRC2(cmMmRegInit);
#if (ERRCLASS & ERRCLS_INT_PAR)
/* error check on parameters */
if((regCb == NULLP) || (cfg == NULLP))
{
RETVALUE(RFAILED);
}
/* Error check on the configuration fields */
if((!cfg->size) || (cfg->vAddr == NULLP) ||
(cfg->numBkts > CMM_MAX_BKT_ENT))
{
RETVALUE(RFAILED);
}
/* Error check whether the size of the mapping table is sufficient */
if((cfg->numBkts) &&
((cfg->bktCfg[cfg->numBkts - 1].size) / \
cfg->bktQnSize) > CMM_MAX_MAP_ENT)
{
RETVALUE(RFAILED);
}
/* Check if the quantum size is power of 2 */
if((cfg->numBkts) &&
((cfg->bktQnSize - 1) & (cfg->bktQnSize)))
{
RETVALUE(RFAILED);
}
/*
* Check if the size of the memory region is enough and also whether two
* consecutive buckets falls within same quanta.
*/
lstQnSize = cfg->bktQnSize;
regCb->bktSize = 0;
for( bktIdx =0; bktIdx < cfg->numBkts; bktIdx++)
{
if((bktBlkSize = cfg->bktCfg[bktIdx].size) < lstQnSize)
{
/*
* Two consecutive buckets are not separated by quantum size.
*/
RETVALUE(RFAILED);
}
regCb->bktSize += (cfg->bktCfg[bktIdx].size *
cfg->bktCfg[bktIdx].numBlks);
if(regCb->bktSize > cfg->size)
{
/* Size of the memory region is less than the required size */
RETVALUE(RFAILED);
}
lstQnSize = ((bktBlkSize / cfg->bktQnSize) + 1) * cfg->bktQnSize;
}
#endif
/* Initialize the region control block */
regCb->region = region;
regCb->regInfo.regCb = regCb;
regCb->regInfo.start = cfg->vAddr;
regCb->regInfo.size = cfg->size;
if( cfg->chFlag & CMM_REG_OUTBOARD)
{
/* Out_of_board memory */
regCb->regInfo.flags = CMM_REG_OUTBOARD;
}
else
{
regCb->regInfo.flags = 0;
}
/* Initialize the memory manager function handlers */
regCb->regInfo.alloc = cmAlloc;
regCb->regInfo.free = cmFree;
regCb->regInfo.ctl = cmCtl;
/* Initialize the physical address */
if((regCb->chFlag = cfg->chFlag) & CMM_REG_PHY_VALID)
{
regCb->pAddr = cfg->pAddr;
}
/* Initial address of the memory region block */
memAddr = cfg->vAddr;
/* Initialize the fields related to the bucket pool */
regCb->bktMaxBlkSize = 0;
regCb->bktSize = 0;
if(cfg->numBkts)
{
/* Last bucket has the maximum size */
regCb->bktMaxBlkSize = cfg->bktCfg[cfg->numBkts - 1].size;
/* Get the power of the bktQnSize */
regCb->bktQnPwr = 0;
while( !((cfg->bktQnSize >> regCb->bktQnPwr) & 0x01))
{
regCb->bktQnPwr++;
}
/* Initilaize the bktIndex of the map entries to FF */
for( lstMapIdx = 0; lstMapIdx < CMM_MAX_MAP_ENT; lstMapIdx++)
{
regCb->mapTbl[lstMapIdx].bktIdx = 0xFF;
}
lstMapIdx = 0;
for( bktIdx = 0; bktIdx < cfg->numBkts; bktIdx++)
{
/* Allocate the lock for the bucket pool */
if(SInitLock (&(regCb->bktTbl[bktIdx].bktLock), cfg->lType) != ROK)
{
/* Free the initialzed lock for the earlier buckets. */
for( ;bktIdx > 0;)
{
SDestroyLock(&(regCb->bktTbl[--bktIdx].bktLock));
}
RETVALUE(RFAILED);
}
cmMmBktInit( &memAddr, regCb, cfg, bktIdx, &lstMapIdx);
}
/* Used while freeing the bktLock in cmMmRegDeInit */
regCb->numBkts = cfg->numBkts;
}
/*
* Initialize the heap pool if size the memory region region is more
* than the size of the bucket pool
*/
regCb->heapSize = 0;
regCb->heapFlag = FALSE;
/* Align the memory address */
memAddr = (Data *)(PTRALIGN(memAddr));
regCb->heapSize = cfg->vAddr + cfg->size - memAddr;
/*
* Round the heap size so that the heap size is multiple
* of CMM_MINBUFSIZE
*/
regCb->heapSize -= (regCb->heapSize % CMM_MINBUFSIZE);
if(regCb->heapSize)
{
/* Allocate the lock for the heap pool */
if(SInitLock (®Cb->heapCb.heapLock, cfg->lType) != ROK)
{
if((bktIdx = cfg->numBkts))
{
/* Free the initialzed locks of the buckets */
for(; bktIdx > 0;)
{
SDestroyLock(&(regCb->bktTbl[--bktIdx].bktLock));
}
}
RETVALUE(RFAILED);
}
regCb->heapFlag = TRUE;
cmMmHeapInit(memAddr, &(regCb->heapCb), regCb->heapSize);
}
/* Call SRegRegion to register the memory region with SSI */
if(SRegRegion(region, ®Cb->regInfo) != ROK)
{
RETVALUE(RFAILED);
}
RETVALUE(ROK);
} /* end of cmMmRegInit*/
/*
*
* Fun: cmMmRegDeInit
*
* Desc: Deinitialize the memory region. The function call SDeregRegion
* to deregister the memory region with System Service.
*
*
* Ret: ROK - successful
* RFAILED - unsuccessful.
*
* Notes: The memory owner calls this function to deinitialize the region.
* The memory manager does not return the memory to the system.
* Before calling this function, the memory owner must be sure that
* no layer is using any memory block from this region. On
* successful return from the function, any request to the memory
* manager to allocate/deallocate memory will fail. The memory owner
* can reuse the memory for other region or return the memory to the
* system memory pool.
*
*
*
* File: cm_mem.c
*
*/
#ifdef ANSI
PUBLIC S16 cmMmRegDeInit
(
CmMmRegCb *regCb
)
#else
PUBLIC S16 cmMmRegDeInit(regCb)
CmMmRegCb *regCb;
#endif
{
U16 bktIdx;
TRC2(cmMmRegDeInit);
#if (ERRCLASS & ERRCLS_INT_PAR)
/* error check on parameters */
if(regCb == NULLP)
{
RETVALUE(RFAILED);
}
#endif
/* Call SDeregRegion first to deregister the memory region with SSI */
(Void) SDeregRegion (regCb->region);
if(regCb->bktSize)
{
/* Bucket pool is configured */
/* Free the initialzed locks of the buckets */
for( bktIdx = regCb->numBkts; bktIdx > 0;)
{
SDestroyLock(&(regCb->bktTbl[--bktIdx].bktLock));
}
}
if(regCb->heapFlag)
{
/* Heap pool is configured */
/* Destroy the bucket lock */
SDestroyLock(®Cb->heapCb.heapLock);
}
RETVALUE(ROK);
} /* end of cmMmRegDeInit */
/*
*
* Fun: cmAlloc
*
* Desc: Allocate a memory block for the memory region.
*
*
* Ret: ROK - successful
* RFAILED - unsuccessful.
*
* Notes:
* The function allocates a memory block of size atleast equal to
* the requested size. The size parameter will be updated with the
* actual size of the memory block allocated for the request. The
* CMM tries to allocate the memory block form the bucket pool. If
* there is no memory in the bucket the CMM allocates the memory
* block form the heap pool. This function is always called by the
* System Service module.
*
* The caller of the function should try to use the out value of
* the size while returning the memory block to the region. However
* the current design of the memory manager does not enforce to pass
* the actual size of the memory block. (Due to the SGetSBuf
* semantics the layer will not able to pass the correct size of the
* memory block while calling SPutSBuf).
*
*
* File: cm_mem.c
*
*/
#ifdef ANSI
PRIVATE S16 cmAlloc
(
Void *regionCb,
Size *size,
U32 flags,
Data **ptr
)
#else
PRIVATE S16 cmAlloc(regionCb, size, flags, ptr)
Void *regionCb;
Size *size;
U32 flags;
Data **ptr;
#endif
{
U16 idx;
CmMmBkt *bkt;
CmMmRegCb *regCb;
S16 ret;
TRC2(cmAlloc);
UNUSED(flags);
regCb = (CmMmRegCb *)regionCb;
#if (ERRCLASS & ERRCLS_INT_PAR)
/* error check on parameters */
if((regCb == NULLP) || (size == NULLP) || !(*size) || (ptr == NULLP))
{
RETVALUE(RFAILED);
}
#endif
/*
* Check if the requested size is less than or equal to the maximum block
* size in the bucket.
*/
if( *size <= regCb->bktMaxBlkSize)
{
/* Get the map to the mapping table */
idx = ((*size - 1) >> regCb->bktQnPwr);
#if (ERRCLASS & ERRCLS_DEBUG)
if(regCb->mapTbl[idx].bktIdx == 0xFF)
{
/* Some fatal error in the map table initialization. */
RETVALUE(RFAILED);
}
#endif
/* Dequeue the memory block and return it to the user */
bkt = &(regCb->bktTbl[regCb->mapTbl[idx].bktIdx]);
/* While loop is introduced to use the "break statement inside */
while(1)
{
/*
* Check if the size request is not greater than the size available
* in the bucket
*/
if(*size > bkt->size)
{
/* Try to go to the next bucket if available */
if((idx < (CMM_MAX_MAP_ENT - 1)) &&
(regCb->mapTbl[++idx].bktIdx != 0xFF))
{
bkt = &(regCb->bktTbl[regCb->mapTbl[idx].bktIdx]);
}
else
{
/* This is the last bucket, try to allocate from heap */
break;
}
}
else
break;
}
/* Acquire the bucket lock */
(Void) SLock(&(bkt->bktLock));
#if (ERRCLASS & ERRCLS_DEBUG)
regCb->mapTbl[idx].numReq++;
#endif
if((*ptr = bkt->next))
{
bkt->next = *((CmMmEntry **)(bkt->next));
/*
* Increment the statistics variable of number of memory block
* allocated
*/
bkt->numAlloc++;
/* Update the size parameter */
*size = bkt->size;
/* Release the lock */
(Void) SUnlock(&(bkt->bktLock));
RETVALUE(ROK);
}
#if (ERRCLASS & ERRCLS_DEBUG)
regCb->mapTbl[idx].numFailure++;
#endif
/* Release the lock */
(Void) SUnlock(&(bkt->bktLock));
}
/* Memory not available in the bucket pool */
if(regCb->heapFlag && (*size < regCb->heapSize))
{
/*
* The heap memory block is available. Allocate the memory block from
* heap pool.
*/
ret = cmHeapAlloc(&(regCb->heapCb), ptr, size);
if(ret != ROK)
{
cmPrntMem(regionCb, *size);
}
RETVALUE(ret);
}
/* No memory available */
RETVALUE(RFAILED);
} /* end of cmAlloc */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -