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

📄 rvosmem.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 2 页
字号:
    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(&region->lock) == RV_OK) {
        region->allocs_requested--;
        region->bytes_requested -= bytesrequested;
        region->bytes_used -= bytesused;
        RvLockRelease(&region->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(&region->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(&region->mempools[pool].lock) == RV_OK) {
            meminfo->bytes_total_inuse += (RvObjPoolTotalPages(&region->mempools[pool].objpool) * RvObjPoolPageSize(&region->mempools[pool].objpool));
            meminfo->bytes_free_now += (RvObjPoolFreeItems(&region->mempools[pool].objpool) * region->mempools[pool].realsize);
            meminfo->allocs_free_now += RvObjPoolFreeItems(&region->mempools[pool].objpool);
            RvLockRelease(&region->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(&region->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 **)&region->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 *)&region->psos_region;
    callbacks.pagefree = RvOsMemPsosFreeSeg;
    callbacks.pagefreedata = (void *)&region->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 *)&region->mempools[pool]; /* construct needs proper pool pointer */
        if(RvObjPoolConstruct(&region->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(&region->mempools[pool].lock); /* Give each pool its own lock for speed. */
            if(result != RV_OK)
                RvObjPoolDestruct(&region->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(&region->mempools[pool].objpool);
            RvLockDestruct(&region->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(&region, 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(&region);


    RvPrintf("RvMemoryAlloc(1000): ");
    result = RvMemoryAlloc(&region, &ptr1, 1000);
    if(result != RV_OK) {
        RvOsMemPrintError(result);
        ptr1 = NULL;
    } else RvPrintf("OK. ptr = %p\n", ptr1);
    RvOsMemTestGetInfo(&region);

    RvPrintf("RvMemoryAlloc(1): ");
    result = RvMemoryAlloc(&region, &ptr2, 1);
    if(result != RV_OK) {
        RvOsMemPrintError(result);
        ptr2 = NULL;
    } else RvPrintf("OK. ptr = %p\n", ptr2);
    RvOsMemTestGetInfo(&region);

    if(ptr1 != NULL) {
        RvPrintf("RvMemoryFree: ");
        result = RvMemoryFree(ptr1);
        if(result != RV_OK) {
            RvOsMemPrintError(result);
        } else RvPrintf("OK.\n");
        RvOsMemTestGetInfo(&region);
    }

    if(ptr2 != NULL) {
        RvPrintf("RvMemoryFree: ");
        result = RvMemoryFree(ptr2);
        if(result != RV_OK) {
            RvOsMemPrintError(result);
        } else RvPrintf("OK.\n");
        RvOsMemTestGetInfo(&region);
    }

    RvPrintf("Destructing Memory Pool: ");
    result = RvMemoryDestruct(&region);
    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 + -