⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cm_mem.c

📁 中国石油二期加油站IC系统后台通讯软件
💻 C
📖 第 1 页 / 共 3 页
字号:

/********************************************************************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 (&regCb->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, &regCb->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(&regCb->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 + -