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

📄 rvosmem.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.
***********************************************************************/

/* Basic dynamic memory allocation via OS standard calls. Regions and */
/* attributes are ignored. */

#include "rvosmem.h"

#if (RV_OSMEM_TYPE == RV_OSMEM_MALLOC)
#include <stdlib.h>
#endif

#if (RV_OSMEM_TYPE == RV_OSMEM_VXWORKS)
#include <memLib.h>
#endif

#if (RV_OSMEM_TYPE == RV_OSMEM_OSE)
#include "heapapi.h"
#endif

#if (RV_OSMEM_TYPE == RV_OSMEM_NUCLEUS)
#include <nucleus.h>
/* In the Nucleus environment, System_Memory is expected to have been */
/* created for us and be the default memory pool. */
extern NU_MEMORY_POOL System_Memory;
#endif

#if (RV_OSMEM_TYPE == RV_OSMEM_PSOS)
#include "rvobjpool.h"

/* pSOS malloc is thread specific so we have to allocate memory */
/* segments directly. Since these segments are only available in large */
/* blocks we maintain pools of smallers blocks (power of 2 up to segment */
/* size) and allocate from the appropriate pool. Large blocks are just */
/* passed directly to pSOS. */

/* Configuration is via the following hardcoded definitions but could */
/* be extended to pass the values in during construction to allow for */
/* different pools in different pSOS memory regions. */

/* Which psos memory region to allocate segments from. */
#define PSOS_MEM_REGION 0

/* Smallest sub-allocation buffer pool to create. Must be a power */
/* of 2 and >= sizeof(RvOsMemPsosPoolElem). Also look at the size */
/* of RV_PSOS_BLOCK_OVERHEAD to see how much of the block is used */
/* for overhead. */
#define PSOS_MEM_MINBUFSIZE 32

/* Indicate what type of Object Pools and options to use (see rvobjpool.h). */
/* Also indicate how pool pages should relate to pSOS segments. Its a good */
/* idea to make (segmentsize * PAGESIZE) >= (MINBUFSIZE * 8) where segmentsize */
/* is the segment size of the pSOS region being used. */
#define PSOS_OBJPOOL_TYPE RV_OBJPOOL_TYPE_EXPANDING
#define PSOS_OBJPOOL_SALVAGE RV_OBJPOOL_SALVAGE_NEVER  /* Uses less overhead */
#define PSOS_OBJPOOL_MAXITEMS 0 /* Use all available memory */
#define PSOS_OBJPOOL_MINITEMS 0 /* No minimum level */
#define PSOS_OBJPOOL_FREELEVEL 0 /* not used unless pool is DYNAMIC */
#define PSOS_OBJPOOL_PAGESIZE 2 /* number of pSOS segments to use for each page */

/* Overhead of objpool pointer (sourcepool in RvOsMemPsosPoolElem) that needs to */
/* be stored with each block to know which pool to return it to. The OVERHEAD size */
/* must account for the alignment of the ptr that will be returned to the user. */
#define RV_PSOS_BLOCK_OVERHEAD RV_ALIGN_SIZE

/* Item that is put into the pool, only the sourcepool part of the */
/* structure is "overhead" unless the item is smaller than poolelem. */
typedef struct {
    RvOsMemPsosPool *sourcepool; /* ptr to pool block came from */
    RvObjPoolElement poolelem;   /* pool element */
} RvOsMemPsosPoolElem;

/* Info about each pool to be kept in the array. Typedef RvOsMemPsosPool is in header. */
struct RvOsMemPsosPool_s {
    RvLock lock;
    RvSize_t realsize; /* requested size being stored in this pool */
    RvObjPool objpool; /* object pool iteself */
};

static void *RvOsMemPsosBlockConstruct(void *objpool, void *data);
static void *RvOsMemPsosGetSeg(RvSize_t size, void *data);
static void RvOsMemPsosFreeSeg(void *ptr, void *data);
static RvStatus RvOsMemPsosConstructPools(RvOsMemData *region, unsigned long minbufsize);
#endif /* pSOS */

/* Size of overhead on each block needed to keep stats. Must be aligned. */
#define RV_OSMEM_STATS_OVERHEAD RV_ALIGN_SIZE

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

RvStatus RvOsMemInit(void)
{
    return RV_OK;
}

RvStatus RvOsMemEnd(void)
{
    return RV_OK;
}

/* start, size, moremem, and attr not used, overhead used only for stats. */
RvStatus RvOsMemConstruct(void *driverRegion, void *start, RvSize_t size, RvSize_t overhead, RvMemory *moremem, void *attr)
{
    RvStatus result;
#if (RV_MEMORY_KEEPSTATS == 1) || (RV_OSMEM_TYPE == RV_OSMEM_PSOS) /* prevent warnings */
    RvOsMemData *region;
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_PSOS)
    struct rninfo rbuf;
    unsigned long bufsize;
#endif

    RV_UNUSED_ARG(attr);
    RV_UNUSED_ARG(moremem);
    RV_UNUSED_ARG(size);
    RV_UNUSED_ARG(start);
#if (RV_MEMORY_KEEPSTATS == 0)
    RV_UNUSED_ARG(overhead);
#endif

    result = RV_OK;
#if (RV_MEMORY_KEEPSTATS == 1) || (RV_OSMEM_TYPE == RV_OSMEM_PSOS) /* prevent warnings */
    region = (RvOsMemData *)driverRegion;
#else
    RV_UNUSED_ARG(driverRegion);
#endif

    /* Most OS's have just one big heap but we'll maintain stats */
    /* for each logical region. */
#if (RV_MEMORY_KEEPSTATS == 1)
    result = RvLockConstruct(&region->lock);
    if(result != RV_OK)
        return result;
    region->overhead = overhead;
    region->allocs_requested = 0;
    region->bytes_requested = 0;
    region->bytes_used = 0;
#endif

    /* Since we're doing our own management for pSOS, we'll keep */
    /* a seperate set of pools for each region. */
#if (RV_OSMEM_TYPE == RV_OSMEM_PSOS)
    region->psos_region = PSOS_MEM_REGION;

    /* Ask pSOS to find out segment size of region. */
    if(rn_info(region->psos_region, &rbuf) == 0) {
        region->segment_size = rbuf.unit_size;

        /* figure out number of buffer pools to use */
        region->numpools = 0;
        for(bufsize = PSOS_MEM_MINBUFSIZE; bufsize < region->segment_size; bufsize *= 2)
            region->numpools++;

        /* Construct the pools */
        result = RvOsMemPsosConstructPools(region, PSOS_MEM_MINBUFSIZE);
        if(result != RV_OK) {
            region->mempools = NULL;
            region->numpools = 0;
        }
    } else result = RvOsMemErrorCode(RV_ERROR_UNKNOWN); /* rn_info failed */
#endif/* pSOS */

#if (RV_MEMORY_KEEPSTATS == 1)
    if(result != RV_OK)
        RvLockDestruct(&region->lock);
#endif
    return result;
}

RvStatus RvOsMemDestruct(void *driverRegion)
{
    RvStatus result;
#if (RV_MEMORY_KEEPSTATS == 1) || (RV_OSMEM_TYPE == RV_OSMEM_PSOS) /* prevent warnings */
    RvOsMemData *region;
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_PSOS)
    RvInt pool;
#endif

    result = RV_OK;
#if (RV_MEMORY_KEEPSTATS == 1) || (RV_OSMEM_TYPE == RV_OSMEM_PSOS) /* prevent warnings */
    region = (RvOsMemData *)driverRegion;
#else
    RV_UNUSED_ARG(driverRegion);
#endif

#if (RV_MEMORY_KEEPSTATS == 1)
    result = RvLockGet(&region->lock);
    if(result == RV_OK)
        result = RvLockDestruct(&region->lock);
#endif

#if (RV_OSMEM_TYPE == RV_OSMEM_PSOS)
    if(region->mempools != NULL) {
        for(pool = 0; pool < region->numpools; pool++)
            if(RvObjPoolDestruct(&region->mempools[pool].objpool) == RV_FALSE)
                result = RvOsMemErrorCode(RV_ERROR_UNKNOWN); /* Just report it. */
        rn_retseg(region->psos_region, region->mempools);
        region->numpools = 0;
        region->mempools = NULL;
    }
#endif /* pSOS */

    return result;
}

RvStatus RvOsMemAlloc(void *driverRegion, void **result, RvSize_t size)
{
    void *ptr;
    RvSize_t memsize;
#if (RV_MEMORY_KEEPSTATS == 1) || (RV_OSMEM_TYPE == RV_OSMEM_PSOS) /* prevent warnings */
    RvOsMemData *region;
#endif

#if (RV_MEMORY_KEEPSTATS == 1)
    RvSize_t bytesused;
    RvSize_t *blocksize;
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_NUCLEUS)
    int status;
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_PSOS)
    RvInt pool;
    RvOsMemPsosPoolElem *block;
#if (RV_MEMORY_KEEPSTATS == 1)
    RvSize_t segmentadjust;
#endif
#endif

    /* rvmemory does basic error checking for us */

#if (RV_MEMORY_KEEPSTATS == 1) || (RV_OSMEM_TYPE == RV_OSMEM_PSOS) /* prevent warnings */
    region = (RvOsMemData *)driverRegion;
#else
    RV_UNUSED_ARG(driverRegion);
#endif
    memsize = size;

#if (RV_MEMORY_KEEPSTATS == 1)
    memsize += RV_OSMEM_STATS_OVERHEAD;
    bytesused = memsize;
#endif

    /* Call the OS to allocate the memory and set ptr to the allocated block. */
    /* Also, for statistics, set bytesused to actual amount of memory used. */
#if (RV_OSMEM_TYPE == RV_OSMEM_MALLOC) || (RV_OSMEM_TYPE == RV_OSMEM_VXWORKS)
    ptr = (void *)malloc(memsize);
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_OSE)
    /* For OSE we need to use memory shareable across processes. */
    ptr = heap_alloc_shared(memsize, (__FILE__), (__LINE__));
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_NUCLEUS)
    status = NU_Allocate_Memory(&System_Memory, &ptr, memsize, NU_NO_SUSPEND);
    if(status != NU_SUCCESS)
        ptr = NULL;
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_PSOS)
    ptr = NULL;

    /* Try from smallest possible block size and go up */
    for(pool = 0; pool < region->numpools; pool++) {
        if(memsize <= region->mempools[pool].realsize) {
            if(RvLockGet(&region->mempools[pool].lock) == RV_OK) {
                ptr = RvObjPoolGetItem(&region->mempools[pool].objpool);
                if(ptr != NULL) {
                    ptr = (void *)((RvInt8 *)ptr + RV_PSOS_BLOCK_OVERHEAD); /* Adjust past pool pointer */
#if (RV_MEMORY_KEEPSTATS == 1)
                    bytesused = RvObjPoolItemBlockSize(&region->mempools[pool].objpool); /* use real size */
#endif
                    RvLockRelease(&region->mempools[pool].lock);
                    break;
                }
                RvLockRelease(&region->mempools[pool].lock);
            }
        }
    }

    /* Last resort, go directly to pSOS region */
    if(ptr == NULL) {
        memsize += RV_PSOS_BLOCK_OVERHEAD;
        if(rn_getseg(region->psos_region, memsize, RN_NOWAIT, 0, &ptr) == 0) {
            /* Set the pool pointer to NULL to indicate pSOS direct */
            block = (RvOsMemPsosPoolElem *)ptr;
            block->sourcepool = NULL;
            ptr = (void *)((RvInt8 *)ptr + RV_PSOS_BLOCK_OVERHEAD);
#if (RV_MEMORY_KEEPSTATS == 1)
            /* Account for an entire segment being allocated */
            bytesused = memsize;
            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
        } else ptr = NULL; /* rn_getseg failed */
    }
#endif /* pSOS */

    /* Check for alloc failure */
    if(ptr == NULL)
        return RvOsMemErrorCode(RV_ERROR_OUTOFRESOURCES);

#if (RV_MEMORY_KEEPSTATS == 1)
    /* Save size in block so free can subtract it */
    blocksize = ptr;
    ptr = (void *)((RvInt8 *)ptr + RV_OSMEM_STATS_OVERHEAD);
    *blocksize = size;

    /* Statistics calculations */
    if(RvLockGet(&region->lock) == RV_OK) {
        region->allocs_requested++;
        region->bytes_requested += size;
        region->bytes_used += bytesused;
        RvLockRelease(&region->lock);
    }
#endif

    *result = ptr;
    return RV_OK;
}

RvStatus RvOsMemFree(void *driverRegion, void *ptr)
{
    void * memptr;
#if (RV_MEMORY_KEEPSTATS == 1) || (RV_OSMEM_TYPE == RV_OSMEM_PSOS) /* prevent warnings */
    RvOsMemData *region;
#endif

#if (RV_MEMORY_KEEPSTATS == 1)
    RvSize_t *blocksize;
    RvSize_t bytesrequested, bytesused;
#endif
#if (RV_OSMEM_TYPE == RV_OSMEM_PSOS)
    RvOsMemPsosPoolElem *block;
#if (RV_MEMORY_KEEPSTATS == 1)
    RvSize_t segmentadjust;
#endif
#endif

    /* rvmemory does base error checking for us. */

#if (RV_MEMORY_KEEPSTATS == 1) || (RV_OSMEM_TYPE == RV_OSMEM_PSOS) /* prevent warnings */
    region = (RvOsMemData *)driverRegion;
#else
    RV_UNUSED_ARG(driverRegion);
#endif
    memptr = ptr;

#if (RV_MEMORY_KEEPSTATS == 1)
    /* Move pointer and get saved copy of requested size */
    memptr = (void *)((RvInt8 *)memptr - RV_OSMEM_STATS_OVERHEAD);
    blocksize = memptr;

⌨️ 快捷键说明

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