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

📄 rvpoolmem.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 2 页
字号:
/***********************************************************************
Filename   : rvosmem.c
Description: memdriver for dynamic memory allocation from OS itself
************************************************************************
        Copyright (c) 2001 RADVISION Inc. and RADVISION Ltd.
************************************************************************
NOTICE:
This document contains information that is confidential and proprietary
to RADVISION Inc. and RADVISION Ltd.. No part of this document may be
reproduced in any form whatsoever without written prior approval by
RADVISION Inc. or RADVISION Ltd..

RADVISION Inc. and RADVISION Ltd. reserve the right to revise this
publication and make changes without obligation to notify any person of
such revisions or changes.
***********************************************************************/

/* Block Pool memory manager. Not currently OS specific (so it doesn't */
/* have to be ported but could be modified to use an OS specific block pool */
/* manager if needed. */

#include "rvpoolmem.h"

/* Default attribute values if user passes in NULL attr pointer */
static RvPoolMemAttr RvPoolMemDefaultAttr = {
	RV_OBJPOOL_TYPE_EXPANDING, /* pooltype */
	32,                        /* pageitems */
	0,                         /* pagesize */
	0,                         /* maxblocks */
	0,                         /* minblocks */
	0,                         /* freelevel */
	0,                         /* startblocks */
	0                          /* startpages */
};

/* Item that is put into the pool, since we just want raw memory */
/* we only need the pool element. */
typedef struct {
	RvObjPoolElement poolelem;
} RvPoolMemElem;

static void *RvPoolMemGetPage(RvSize_t size, void *data);
static void RvPoolMemFreePage(void *ptr, void *data);

/* Lets make error codes a little easier to type */
#define RvPoolMemErrorCode(_e) RvErrorCode(RV_ERROR_LIBCODE_CCORE, RV_CCORE_MODULE_POOLMEM, (_e))

RvStatus RvPoolMemInit(void)
{
	return RV_OK;
}

RvStatus RvPoolMemEnd(void)
{
	return RV_OK;
}

/* Start is ignored and size is block size. Minimum block size is sizeof(RvPoolMemElem). */
/* Pool pages are allocated from moremem. Pool configuration passed in via attr */
/* parameter (see rvpoolmem.h) */
RvStatus RvPoolMemConstruct(void *driverRegion, void *start, RvSize_t size, RvSize_t overhead, RvMemory *moremem, void *attr)
{
	RvStatus result;
	RvPoolMemData *pool;
	RvPoolMemElem tempobj;
	RvPoolMemAttr *poolattr;
	RvObjPoolFuncs callbacks;
	RvBool salvage;
	size_t numblocks, numpages;

    RV_UNUSED_ARG(start);

	pool = (RvPoolMemData *)driverRegion;
	poolattr = (RvPoolMemAttr *)attr;
	if(poolattr == NULL)
		poolattr = &RvPoolMemDefaultAttr; /* Use default attributes */
	
	/* Each region will maintin its own lock, so create it */
	result = RvLockConstruct(&pool->lock);
	if(result != RV_OK)
		return result;

	/* save some info which is only used later for calculating statistics */
	pool->usersize = size;
	pool->overhead = overhead;
	pool->moremem = moremem;
	pool->pooltype = poolattr->pooltype;
	
	/* Calculate minimum needed blocksize: requested + overhead. */
	/* Must be >= sizeof(RvPoolMemElem). The real blocksize will */
	/* be calculated by rvobjpool. */
	pool->blocksize = size + overhead;
	if(pool->blocksize < sizeof(RvPoolMemElem))
		pool->blocksize = pool->blocksize = sizeof(RvPoolMemElem);

	/* Set pooldata appropriately based on the pool type. */
	if(poolattr->pooltype == RV_OBJPOOL_TYPE_DYNAMIC) {
		salvage = RV_OBJPOOL_SALVAGE_ALLOWED;
	} else salvage = RV_OBJPOOL_SALVAGE_NEVER; /* Saves overhead */

	/* Construct object pool. Object is actually empty memory so no constructor/destructor. */
	callbacks.objconstruct = NULL;
	callbacks.objdestruct = NULL;
	callbacks.pagealloc = RvPoolMemGetPage;
	callbacks.pageallocdata = (void *)moremem;
	callbacks.pagefree = RvPoolMemFreePage;
	callbacks.pagefreedata = (void *)moremem;
	if(RvObjPoolConstruct(&pool->objpool, &tempobj, &tempobj.poolelem, &callbacks, pool->blocksize, poolattr->pageblocks, poolattr->pagesize, poolattr->pooltype, salvage, poolattr->maxblocks, poolattr->minblocks, poolattr->freelevel) == NULL) {
		/* Can't construct pool, abort */
		RvLockDestruct(&pool->lock);
		return RvPoolMemErrorCode(RV_ERROR_UNKNOWN);
	}
	
	/* Allocate starting blocks or pages. */
	result = RV_OK;
	if(poolattr->startblocks > RvObjPoolTotalItems(&pool->objpool)) {
		numblocks = poolattr->startblocks - RvObjPoolTotalItems(&pool->objpool);
		if(RvObjPoolAddItems(&pool->objpool, numblocks) < numblocks)
			result = RvPoolMemErrorCode(RV_ERROR_UNKNOWN);
	} else {
		/* Only use startpages if we're not using startblocks */
		if(poolattr->startpages > RvObjPoolTotalPages(&pool->objpool)) {
			numpages = poolattr->startpages - RvObjPoolTotalPages(&pool->objpool);
			if(RvObjPoolAddPages(&pool->objpool, numpages) < numpages)
				result = RvPoolMemErrorCode(RV_ERROR_UNKNOWN);
		}
	}
	if(result != RV_OK) {
		/* Couldn't create starting blocks/pages so undo construct. */
		RvObjPoolDestruct(&pool->objpool);
		RvLockDestruct(&pool->lock);
	}

	return result;
}

RvStatus RvPoolMemDestruct(void *driverRegion)
{
	RvPoolMemData *pool;
	RvStatus result;
	
	pool = (RvPoolMemData *)driverRegion;
	result = RV_OK;
	RvLockGet(&pool->lock);
	if(RvObjPoolDestruct(&pool->objpool) == RV_FALSE) {
		/* PoolDestruct failed so don't destroy anything */
		RvLockRelease(&pool->lock);
		result =  RvPoolMemErrorCode(RV_ERROR_UNKNOWN);
	} else RvLockDestruct(&pool->lock);
	return result;
}

RvStatus RvPoolMemAlloc(void *driverRegion, void **result, RvSize_t size)
{
	RvPoolMemData *pool;
	void *ptr;
	RvStatus status;

	pool = (RvPoolMemData *)driverRegion;
	status = RvLockGet(&pool->lock);
	if(status != RV_OK)
		return status;

#if defined(RV_RANGECHECK)
	if(size > pool->blocksize) {
		RvLockRelease(&pool->lock);
		return RvPoolMemErrorCode(RV_ERROR_OUTOFRANGE);
	}
#endif

	ptr = RvObjPoolGetItem(&pool->objpool);
	if(ptr == NULL) {
		status = RvPoolMemErrorCode(RV_ERROR_OUTOFRESOURCES);
	} else *result = ptr;
	RvLockRelease(&pool->lock);
	return status;
}

RvStatus RvPoolMemFree(void *driverRegion, void *ptr)
{
	RvPoolMemData *pool;
	RvStatus result;

	pool = (RvPoolMemData *)driverRegion;
	result = RvLockGet(&pool->lock);
	if(result == RV_OK) {
		RvObjPoolReleaseItem(&pool->objpool, ptr);
		RvLockRelease(&pool->lock);
	}
	return result;
}

/* Allocate new page, data points to memory region to allocate from. */
static void *RvPoolMemGetPage(RvSize_t size, void *data)
{
	void *result;
	RvMemory *pagemem;

	pagemem = (RvMemory *)data;
	if(RvMemoryAlloc(pagemem, &result, size) != RV_OK)
		result = NULL;
	return result;
}

/* Free page, data points to memory region it came from (but we don't need it). */
static void RvPoolMemFreePage(void *ptr, void *data)
{
    RV_UNUSED_ARG(data);
	RvMemoryFree(ptr);
}

/* Since there's no run-time additional overhead we can always return */
/* statistics regardless of the RV_MEMORY_KEEPSTATS flag except for */
/* those that depend on other memory regions (which may not be keeping */
/* them. */
RvStatus RvPoolMemGetInfo(void *driverRegion, RvMemoryInfo *meminfo)
{
	RvPoolMemData *pool;
	RvStatus result;
	RvMemoryInfo morememinfo;
	RvSize_t newblocks, newpages;

	pool = (RvPoolMemData *)driverRegion;
	result = RvLockGet(&pool->lock);
	if(result != RV_OK)
		return result;

	meminfo->allocs_free_now = RvObjPoolFreeItems(&pool->objpool);
	meminfo->bytes_free_now = meminfo->allocs_free_now * pool->usersize;
	meminfo->allocs_requested = RvObjPoolTotalItems(&pool->objpool) - meminfo->allocs_free_now;
	meminfo->bytes_requested_byuser = meminfo->allocs_requested * pool->usersize;
	meminfo->bytes_requested_bymem = meminfo->allocs_requested * (pool->usersize + pool->overhead);
	meminfo->bytes_requested_total = meminfo->allocs_requested * RvObjPoolItemBlockSize(&pool->objpool);
	meminfo->bytes_total_inuse = RvObjPoolTotalPages(&pool->objpool) * RvObjPoolPageSize(&pool->objpool);

	meminfo->allocs_free_total = meminfo->allocs_free_now;
	meminfo->bytes_free_total = meminfo->bytes_free_now;
	if(pool->pooltype != RV_OBJPOOL_TYPE_FIXED) {
		/* Estimate number of blocks and memory that can be aquired. */
		/* Doesn't account for fragmentation that might cause a page allocation to fail */
		result = RvMemoryGetInfo(pool->moremem, &morememinfo);
		if(result == RV_OK) {
			newpages = morememinfo.bytes_free_total / RvObjPoolPageSize(&pool->objpool);
			if(morememinfo.allocs_free_total < newpages)
			   newpages = morememinfo.allocs_free_total;
			newblocks = newpages * RvObjPoolItemsPerPage(&pool->objpool);
			if(newblocks > RvObjPoolGetMaxitems(&pool->objpool)) {
				newpages = RvObjPoolGetMaxitems(&pool->objpool) / RvObjPoolItemsPerPage(&pool->objpool);
				newblocks = newpages * RvObjPoolItemsPerPage(&pool->objpool);
			}
			meminfo->allocs_free_total += newblocks;
			meminfo->bytes_free_total += (newblocks * pool->usersize);
		}
	}

	RvLockRelease(&pool->lock);
	return result;
}

#if defined(RV_TEST_CODE)
#include "rvstdio.h"
#include "rvsemaphore.h"

/* Define quick macro to make error output more readable */
#define RvPoolMemPrintError(_r) RvPrintf("Error %d/%d/%d\n",  RvErrorGetLib((_r)), RvErrorGetModule((_r)), RvErrorGetCode((_r)))

static void RvPoolMemTestGetInfo(RvMemory *region)
{
	RvStatus result;
	RvMemoryInfo meminfo;

	RvPrintf("RvMemoryGetInfo(%p): ", region);
	result = RvMemoryGetInfo(region, &meminfo);
	if(result == RV_OK) {
		RvPrintf("OK. Info for region:\n");
		RvPrintf("name = %s, Driver type = %d\n", meminfo.name, meminfo.drivernum);
		RvPrintf("    Bytes requested by user                = %u\n", meminfo.bytes_requested_byuser);
		RvPrintf("    Bytes requested by rvmemory            = %u\n", meminfo.bytes_requested_bymem);
		RvPrintf("    Total bytes requested                  = %u\n", meminfo.bytes_requested_total);
		RvPrintf("    Total bytes being used                 = %u\n", meminfo.bytes_total_inuse);
		RvPrintf("    Allocated blocks in use                = %u\n", meminfo.allocs_requested);
		RvPrintf("    Bytes immediately available            = %u\n", meminfo.bytes_free_now);
		RvPrintf("    Total bytes available                  = %u\n", meminfo.bytes_free_total);
		RvPrintf("    Number of blocks immediately available = %u\n", meminfo.allocs_free_now);
		RvPrintf("    Total number of blocks available       = %u\n", meminfo.allocs_free_total);
	} else RvPoolMemPrintError(result);
}

RvStatus RvPoolMemTestNoMemory(RvSize_t size)
{
	RvPrintf("**Out of Memory callback executed. Size = %u.\n", size);
	return -1; /* Don't retry */
}

static void RvPoolMemTestPool(RvSize_t blocksize, RvPoolMemAttr *attr, RvChar *name)
{
	RvMemory region;
	RvStatus result;
	RvObjPool *objpool;
	void *ptr;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -