📄 rvosmem.c
字号:
bytesrequested = *blocksize;
bytesused = bytesrequested + RV_OSMEM_STATS_OVERHEAD;
#endif
/* Call the OS to free the memory. For statistics, set bytesused to actual */
/* amount of memory used by the allocation if its not standard. */
#if (RV_OSMEM_TYPE == RV_OSMEM_MALLOC) || (RV_OSMEM_TYPE == RV_OSMEM_VXWORKS)
free(memptr);
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_OSE)
heap_free_shared(memptr);
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_NUCLEUS)
NU_Deallocate_Memory(memptr);
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_PSOS)
block = (RvOsMemPsosPoolElem *)((RvInt8 *)memptr - RV_PSOS_BLOCK_OVERHEAD);
if(block->sourcepool != NULL) {
/* Memory is in a pool */
if(RvLockGet(&block->sourcepool->lock) == RV_OK) {
RvObjPoolReleaseItem(&block->sourcepool->objpool, block); /* Block allocated from a pool */
#if (RV_MEMORY_KEEPSTATS == 1)
bytesused = RvObjPoolItemBlockSize(&block->sourcepool->objpool); /* Use real size */
#endif
RvLockRelease(&block->sourcepool->lock);
}
} else {
/* memory was allocated directly from the pSOS region */
rn_retseg(region->psos_region, block); /* Block allocated directly from pSOS */
#if (RV_MEMORY_KEEPSTATS == 1)
/* Account for an entire segment being allocated */
bytesused += RV_PSOS_BLOCK_OVERHEAD;
segmentadjust = bytesused % (RvSize_t)region->segment_size;
if(segmentadjust > 0)
bytesused += ((RvSize_t)region->segment_size - segmentadjust);
region->region_bytes_used -= bytesused; /* Remember this seperately */
#endif
}
#endif /* pSOS */
/* Statistics collection */
#if (RV_MEMORY_KEEPSTATS == 1)
if(RvLockGet(®ion->lock) == RV_OK) {
region->allocs_requested--;
region->bytes_requested -= bytesrequested;
region->bytes_used -= bytesused;
RvLockRelease(®ion->lock);
}
#endif
return RV_OK;
}
RvStatus RvOsMemGetInfo(void *driverRegion, RvMemoryInfo *meminfo)
{
#if (RV_MEMORY_KEEPSTATS == 1)
RvOsMemData *region;
#if (RV_OSMEM_TYPE == RV_OSMEM_VXWORKS)
MEM_PART_STATS pinfo;
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_PSOS)
RvInt pool;
struct rninfo rbuf;
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_NUCLEUS)
CHAR name[10];
VOID *start_address;
UNSIGNED pool_size, min_allocation, available, task_waiting;
OPTION suspend_type;
NU_TASK *first_task;
#endif
#endif /* Stats */
/* Start with everything at 0 in case we don't or can't calculate it */
meminfo->bytes_requested_byuser = 0;
meminfo->bytes_requested_bymem = 0;
meminfo->bytes_requested_total = 0;
meminfo->bytes_total_inuse = 0;
meminfo->allocs_requested = 0;
meminfo->bytes_free_now = 0;
meminfo->bytes_free_total = 0;
meminfo->allocs_free_now = 0;
meminfo->allocs_free_total = 0;
#if (RV_MEMORY_KEEPSTATS == 1)
region = (RvOsMemData *)driverRegion;
if(RvLockGet(®ion->lock) != RV_OK)
return RV_OK; /* Not much we can do other than return nothing */
/* Common calculations */
meminfo->bytes_requested_byuser = region->bytes_requested - (region->allocs_requested * region->overhead);
meminfo->bytes_requested_bymem = region->bytes_requested;
meminfo->bytes_requested_total = region->bytes_used;
meminfo->allocs_requested = region->allocs_requested;
/* Calls to OS to fill in rest (Generic Malloc does nothing) */
#if (RV_OSMEM_TYPE == RV_OSMEM_VXWORKS)
meminfo->bytes_total_inuse = meminfo->bytes_requested_total; /* we don't know internal overhead */
if(memPartInfoGet(memSysPartId, &pinfo) == OK) {
meminfo->bytes_free_now = pinfo.numBytesFree;
meminfo->allocs_free_now = pinfo.numBytesFree / (region->overhead + RV_OSMEM_STATS_OVERHEAD + RV_ALIGN_SIZE); /* best guess */;
meminfo->bytes_free_total = pinfo.numBytesFree;
meminfo->allocs_free_total = meminfo->allocs_free_now;
}
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_PSOS)
/* Account for aarray overhead in total memory used. */
meminfo->bytes_total_inuse = region->region_bytes_used; /* start with direct allocations */
for(pool = 0; pool < region->numpools; pool++) {
if(RvLockGet(®ion->mempools[pool].lock) == RV_OK) {
meminfo->bytes_total_inuse += (RvObjPoolTotalPages(®ion->mempools[pool].objpool) * RvObjPoolPageSize(®ion->mempools[pool].objpool));
meminfo->bytes_free_now += (RvObjPoolFreeItems(®ion->mempools[pool].objpool) * region->mempools[pool].realsize);
meminfo->allocs_free_now += RvObjPoolFreeItems(®ion->mempools[pool].objpool);
RvLockRelease(®ion->mempools[pool].lock);
}
}
/* Do the best we can at free totals */
meminfo->bytes_free_total = meminfo->bytes_free_now;
meminfo->allocs_free_total = meminfo->allocs_free_now;
if(rn_info(region->psos_region, &rbuf) == 0) {
/* Get info from pSOS region. Doesn't account for overhead or */
/* subdivision but its the best we can do for pSOS. */
meminfo->bytes_free_total += rbuf.free_bytes;
meminfo->allocs_free_total += (rbuf.free_bytes / rbuf.unit_size);
}
#endif /* pSOS */
#if (RV_OSMEM_TYPE == RV_OSMEM_NUCLEUS)
meminfo->bytes_total_inuse = meminfo->bytes_requested_total; /* we don't know internal overhead */
if(NU_Memory_Pool_Information(&System_Memory, name, &start_address, &pool_size, &min_allocation, &available, &suspend_type, &task_waiting, &first_task) == NU_SUCCESS) {
meminfo->bytes_free_now = available;
meminfo->allocs_free_now = available / (region->overhead + RV_OSMEM_STATS_OVERHEAD + RV_ALIGN_SIZE); /* best guess */
meminfo->bytes_free_total = available;
meminfo->allocs_free_total = meminfo->allocs_free_now;
}
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_OSE)
meminfo->bytes_total_inuse = meminfo->bytes_requested_total; /* we don't know internal overhead */
/* No current method for finding out heap statistics. */
#endif
RvLockRelease(®ion->lock);
#else
RV_UNUSED_ARG(driverRegion);
#endif /* KEEPSTATS */
return RV_OK;
}
#if (RV_OSMEM_TYPE == RV_OSMEM_PSOS)
/* pSOS additional functions */
/* Keep pool construction seperate to make things cleaner */
static RvStatus RvOsMemPsosConstructPools(RvOsMemData *region, unsigned long minbufsize)
{
RvStatus result;
RvObjPoolFuncs callbacks;
RvInt pool;
unsigned long bufsize;
RvOsMemPsosPoolElem tempobj;
#if (RV_MEMORY_KEEPSTATS == 1)
RvSize_t segmentadjust;
#endif
if(region->numpools == 0) {
region->mempools = NULL; /* No pools indicates to go to pSOS for everything */
return RV_OK; /* We don't need any pools so we're done. */
}
#if defined(RV_RANGECHECK)
if((sizeof(RvOsMemPsosPoolElem) > minbufsize) || (RV_PSOS_BLOCK_OVERHEAD >= minbufsize))
return(RV_ERROR_OUTOFRANGE);
#endif
/* Allocate memory for memory pool array */
if(rn_getseg(region->psos_region, region->numpools * sizeof(RvOsMemPsosPool), RN_NOWAIT, 0, (void **)®ion->mempools) != 0)
return RvOsMemErrorCode(RV_ERROR_OUTOFRESOURCES);
/* all pools use same callbacks */
callbacks.objconstruct = RvOsMemPsosBlockConstruct;
callbacks.objdestruct = NULL; /* Nothing to destruct */
callbacks.objdestructdata = NULL;
callbacks.pagealloc = RvOsMemPsosGetSeg;
callbacks.pageallocdata = (void *)®ion->psos_region;
callbacks.pagefree = RvOsMemPsosFreeSeg;
callbacks.pagefreedata = (void *)®ion->psos_region;
/* Construct object pools */
result = RV_OK;
bufsize = minbufsize;
pool = 0;
while((pool < region->numpools) && (result == RV_OK)) {
region->mempools[pool].realsize = (RvSize_t)bufsize - RV_PSOS_BLOCK_OVERHEAD;
callbacks.objconstructdata = (void *)®ion->mempools[pool]; /* construct needs proper pool pointer */
if(RvObjPoolConstruct(®ion->mempools[pool].objpool, &tempobj, &tempobj.poolelem, &callbacks, bufsize, 0,
(region->segment_size * PSOS_OBJPOOL_PAGESIZE), PSOS_OBJPOOL_TYPE, PSOS_OBJPOOL_SALVAGE,
PSOS_OBJPOOL_MAXITEMS, PSOS_OBJPOOL_MINITEMS, PSOS_OBJPOOL_FREELEVEL) != NULL) {
result = RvLockConstruct(®ion->mempools[pool].lock); /* Give each pool its own lock for speed. */
if(result != RV_OK)
RvObjPoolDestruct(®ion->mempools[pool].objpool); /* No lock, delete pool we just made */
} else result = RvOsMemErrorCode(RV_ERROR_UNKNOWN); /* PoolCOnstruct failed */
bufsize *= 2;
pool++;
}
if(result != RV_OK) {
/* Construction failed in middle, undo stuff already created */
while(pool > 0) {
pool--;
RvObjPoolDestruct(®ion->mempools[pool].objpool);
RvLockDestruct(®ion->mempools[pool].lock);
}
rn_retseg(region->psos_region, region->mempools);
}
#if (RV_MEMORY_KEEPSTATS == 1)
/* Remember how much region memory we're using. */
region->region_bytes_used = region->numpools * sizeof(RvOsMemPsosPool);
segmentadjust = region->region_bytes_used % (RvSize_t)region->segment_size;
if(segmentadjust > 0)
region->region_bytes_used += ((RvSize_t)region->segment_size - segmentadjust); /* Account for segment size */
#endif
return result;
}
/* ObjPool callbacks (3 of them) used by pSOS */
/* Each block needs to contain a pointer back to the pool it came from */
/* so we might as well do it when the items are constructed. The data */
/* parameter contains the pointer to the pool. */
static void *RvOsMemPsosBlockConstruct(void *item, void *data)
{
RvOsMemPsosPoolElem *block;
block = (RvOsMemPsosPoolElem *)item;
block->sourcepool = (RvOsMemPsosPool *)data;
}
/* Allocate regions from pSOS for pages, data = pointer to psos region id */
static void *RvOsMemPsosGetSeg(RvSize_t size, void *data)
{
void *result;
unsigned long *region_id;
region_id = (unsigned long *)data;
if(rn_getseg(*region_id, size, RN_NOWAIT, 0, &result) != 0)
result = NULL;
return result;
}
/* Free regions from pSOS, data = pointer to psos region id */
static void RvOsMemPsosFreeSeg(void *ptr, void *data)
{
unsigned long *region_id;
region_id = (unsigned long *)data;
rn_retseg(*region_id, ptr);
}
#endif /* pSOS */
#if defined(RV_TEST_CODE)
#include "rvstdio.h"
#include "rvsemaphore.h"
/* Define quick macro to make error output more readable */
#define RvOsMemPrintError(_r) RvPrintf("Error %d/%d/%d\n", RvErrorGetLib((_r)), RvErrorGetModule((_r)), RvErrorGetCode((_r)))
static void RvOsMemTestGetInfo(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(" Allocations 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(" Allocations immediately available = %u\n", meminfo.allocs_free_now);
RvPrintf(" Total number of allocations available = %u\n", meminfo.allocs_free_total);
} else RvOsMemPrintError(result);
}
void RvOsMemTest(void)
{
RvMemory region;
RvStatus result;
void *ptr1, *ptr2;
/* Initialize other needed modules */
RvSemaphoreInit();
RvLockInit();
RvMemoryInit(); /* Calls RvOsMemInit */
RvPrintf("Starting test of rvosmem.\n");
RvPrintf("RvMemoryConstruct: ");
/* No out-of-memory callback */
result = RvMemoryConstruct(®ion, RV_MEMORY_DRIVER_OSMEM, "osmem", NULL, 0, NULL, NULL, NULL);
if(result != RV_OK) {
RvOsMemPrintError(result);
RvPrintf("++++OsMem Test Aborted++++\n");
return;
} else RvPrintf("OK\n");
RvOsMemTestGetInfo(®ion);
RvPrintf("RvMemoryAlloc(1000): ");
result = RvMemoryAlloc(®ion, &ptr1, 1000);
if(result != RV_OK) {
RvOsMemPrintError(result);
ptr1 = NULL;
} else RvPrintf("OK. ptr = %p\n", ptr1);
RvOsMemTestGetInfo(®ion);
RvPrintf("RvMemoryAlloc(1): ");
result = RvMemoryAlloc(®ion, &ptr2, 1);
if(result != RV_OK) {
RvOsMemPrintError(result);
ptr2 = NULL;
} else RvPrintf("OK. ptr = %p\n", ptr2);
RvOsMemTestGetInfo(®ion);
if(ptr1 != NULL) {
RvPrintf("RvMemoryFree: ");
result = RvMemoryFree(ptr1);
if(result != RV_OK) {
RvOsMemPrintError(result);
} else RvPrintf("OK.\n");
RvOsMemTestGetInfo(®ion);
}
if(ptr2 != NULL) {
RvPrintf("RvMemoryFree: ");
result = RvMemoryFree(ptr2);
if(result != RV_OK) {
RvOsMemPrintError(result);
} else RvPrintf("OK.\n");
RvOsMemTestGetInfo(®ion);
}
RvPrintf("Destructing Memory Pool: ");
result = RvMemoryDestruct(®ion);
if(result != RV_OK) {
RvOsMemPrintError(result);
} else RvPrintf("OK.\n");
RvMemoryEnd(); /* calls RvOsMemEnd */
/* Shut down other needed modules */
RvLockEnd();
RvSemaphoreEnd();
}
#endif /* RV_TEST_CODE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -