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

📄 rvmemory.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 2 页
字号:
    }

#if (RV_MEMORY_DEBUGINFO == 1)
    if(result == RV_OK) {
        /* If we sucessfully destructed, destroy the allocated block list and its lock. */
        RvLockGet(&region->listlock);
        RvObjListDestruct(&region->alloclist);
        RvLockDestruct(&region->listlock);
    }
#endif

    return result;
}

#if (RV_MEMORY_DEBUGINFO != 1)
RVCOREAPI RvStatus RVCALLCONV RvMemoryAlloc(RvMemory *reqregion, void **resultptr, RvSize_t size)
#else
/* Special Alloc for debugging */
RVCOREAPI RvStatus RVCALLCONV RvMemoryAllocDbg(RvMemory *reqregion, void **resultptr, RvSize_t size, RvInt line, RvChar *filename)
#endif
{
    RvStatus result;
    RvMemory *region;
    RvSize_t realsize;
    RvMemoryAllocHead *allochead;
#if (RV_MEMORY_DEBUGCHECK == 1)
    RvUint8 *allocend;
#endif

    /* To save time we don't lock region and assume the driver will */
    /* do any needed locking. This does imply that RvMemoryDestruct */
    /* can not be called until it is known that no other calls will */
    /* be made on that region. */

    /* If requested region is NULL, use the default region */
    region = reqregion;
    if(region == NULL)
        region = &RvDefaultRegion;

#if defined(RV_NULLCHECK)
    if(resultptr == NULL)
        return RvMemoryErrorCode(RV_ERROR_NULLPTR);
#endif
#if defined(RV_OTHERCHECK)
    if(region->drivernum < 0)
        return RvMemoryErrorCode(RV_ERROR_DESTRUCTED);
    if(RvDriverStatus[region->drivernum] != RV_OK)
        return RvMemoryErrorCode(RV_MEMORY_ERROR_DRIVERFAILED);
#endif

    /* Add overhead to needed size */
    realsize = size + RV_MEMORY_ALLOC_OVERHEAD;

#if defined(RV_RANGECHECK)
    if(realsize < size) /* overhead caused us to wrap */
        return RvMemoryErrorCode(RV_ERROR_OUTOFRANGE);
#endif

    /* Call driver to allocate space and deal with out-of-memory callback */
    for(;;) {
        result = region->drivercalls->alloc(region->driverRegion, resultptr, realsize);

        /* Don't retry if we didn't run out of memory or the user callback doesn't return RV_OK */
        if((RvErrorGetCode(result) != RV_ERROR_OUTOFRESOURCES) || (region->nomem == NULL) || (region->nomem(realsize) != RV_OK))
            break;
    }

    if(result == RV_OK) {
        /* Store pointer back to region along with any other info */
        /* and bump resultptr to proper position. */
        allochead = (RvMemoryAllocHead *)*resultptr;
        *resultptr = (void *)((RvInt8 *)*resultptr + RV_MEMORY_ALLOC_HEAD_OVERHEAD);
        allochead->region = region;

#if (RV_MEMORY_DEBUGINFO == 1)
        /* Include additional debugging information */
        allochead->line = line;
        allochead->filename = filename;
        allochead->thread = RvThreadCurrent();
        allochead->id = RvThreadCurrentId();

        /* Add block to end of allocated blocks list. */
        if(RvLockGet(&region->listlock) == RV_OK) {
            RvObjListInsertBefore(&region->alloclist, NULL, allochead);
            RvLockRelease(&region->listlock);
        }
#endif

#if (RV_MEMORY_DEBUGCHECK == 1)
        allochead->freed = RV_FALSE; /* Used to check for memory freed multiple times */

        /* Set boundry at head and at the end. The one at the head */
        /* be bigger than the request size because it goes to the */
        /* pointer to be returned, which is aligned. */
        allochead->reqsize = size;
        memset(&allochead->boundry[0], RV_MEMORY_HEAD_FILL, (RvSize_t)((RvUint8 *)*resultptr - (RvUint8 *)&allochead->boundry[0]));
        allocend = (RvUint8 *)*resultptr + size;
        memset(allocend, RV_MEMORY_TAIL_FILL, RV_MEMORY_BOUNDRY_SIZE);

        /* Set memory to make sure 0 isn't assumed. */
        memset(*resultptr, RV_MEMORY_ALLOC_FILL, size);
#endif
    }

    return result;
}

RVCOREAPI RvStatus RVCALLCONV RvMemoryFree(void *ptr)
{
    RvStatus result;
    RvMemoryAllocHead *allochead;
#if (RV_MEMORY_DEBUGCHECK == 1)
    RvUint8 *tmpptr;
    size_t i;
#endif

    /* To save time we don't lock region (see note in RvMemoryAlloc) */

#if defined(RV_NULLCHECK)
    if(ptr == NULL)
        return RvMemoryErrorCode(RV_ERROR_NULLPTR);
#endif

    /* Region pointer should be stored right before ptr */
    allochead = (RvMemoryAllocHead *)((RvInt8 *)ptr - RV_MEMORY_ALLOC_HEAD_OVERHEAD);

    /* Do boundry and sanity checking. */
#if (RV_MEMORY_DEBUGCHECK == 1)
    /* Check to make sure block hasn't already been freed. */
    if(allochead->freed != RV_FALSE)
        return RvMemoryErrorCode(RV_ERROR_UNKNOWN);
    allochead->freed = RV_TRUE; /* Mark as freed */

    /* Check header boundry (variable size). */
    tmpptr = (RvUint8 *)&allochead->boundry[0];
    while(tmpptr != (RvUint8 *)ptr) {
        if(*tmpptr != RV_MEMORY_HEAD_FILL)
            return RvMemoryErrorCode(RV_MEMORY_ERROR_OVERRUN);
        tmpptr += 1;
    }

    /* Check boundry at end (always requested size). */
    tmpptr = (RvUint8 *)ptr + allochead->reqsize;
    for(i = 0; i < RV_MEMORY_BOUNDRY_SIZE; i++) {
        if(*tmpptr != RV_MEMORY_TAIL_FILL)
            return RvMemoryErrorCode(RV_MEMORY_ERROR_OVERRUN);
        tmpptr += 1;
    }

    /* Overwrite free memory to insure its not still being used. */
    memset(ptr, RV_MEMORY_FREE_FILL, allochead->reqsize);
#endif

#if defined(RV_OTHERCHECK)
    if(allochead->region->drivernum < 0)
        return RvMemoryErrorCode(RV_ERROR_DESTRUCTED);
    if(RvDriverStatus[allochead->region->drivernum] != RV_OK)
        return RvMemoryErrorCode(RV_MEMORY_ERROR_DRIVERFAILED);
#endif

#if (RV_MEMORY_DEBUGINFO == 1)
    /* Remove block from allocated block list */
    if(RvLockGet(&allochead->region->listlock) == RV_OK) {
        RvObjListRemoveItem(&allochead->region->alloclist, allochead);
        RvLockRelease(&allochead->region->listlock);
    }
#endif

    result = allochead->region->drivercalls->free(allochead->region->driverRegion, allochead);

    return result;
}

RVCOREAPI RvStatus RVCALLCONV RvMemoryGetInfo(RvMemory *reqregion, RvMemoryInfo *meminfo)
{
    RvMemory *region;

    /* If requested region is NULL, use the default region */
    region = reqregion;
    if(region == NULL)
        region = &RvDefaultRegion;

#if defined(RV_NULLCHECK)
    if(meminfo == NULL)
        return RvMemoryErrorCode(RV_ERROR_NULLPTR);
#endif
#if defined(RV_OTHERCHECK)
    if(region->drivernum < 0)
        return RvMemoryErrorCode(RV_ERROR_DESTRUCTED);
    if(RvDriverStatus[region->drivernum] != RV_OK)
        return RvMemoryErrorCode(RV_MEMORY_ERROR_DRIVERFAILED);
#endif

    /* We fill in the first 2 fields and pass the rest into the driver */
    strcpy(meminfo->name, region->name);
    meminfo->drivernum = region->drivernum;

    return region->drivercalls->info(region->driverRegion, meminfo);

}

RvStatus RvMemorySetDefaultMemCB(RvMemoryFunc func)
{
    RvStatus result;

    result = RvLockGet(&RvUserDefaultLock);
    if(result == RV_OK) {
        RvUserDefaultCB = func;
        RvLockRelease(&RvUserDefaultLock);
    }
    return result;
}

RvStatus RvMemoryGetDefaultMemCB(RvMemoryFunc *func)
{
    RvStatus result;

    result = RvLockGet(&RvUserDefaultLock);
    if(result == RV_OK) {
        *func = RvUserDefaultCB;
        RvLockRelease(&RvUserDefaultLock);
    }
    return result;
}


/* Out-of-memory callback for default memory region. Returns */
/* RV_OK if memory allocation should be tried again. It calls */
/* the function set by the user. */
static RvStatus RvMemoryDefaultMemCB(RvSize_t size)
{
    RvStatus result;

    result = RvLockGet(&RvUserDefaultLock);
    if(result == RV_OK) {
        if(RvUserDefaultCB != NULL) {
            result = RvUserDefaultCB(size);
        } else result = RvMemoryErrorCode(RV_ERROR_OUTOFRESOURCES);
        RvLockRelease(&RvUserDefaultLock);
    }
    return result;
}

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

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

/* Just test init/end and default region here. Let individual driver */
/* test deal with tests for those drivers. */
void RvMemoryTest(void)
{
    RvStatus result;
    void *memptr;

    /* Initialize other needed modules */
    RvSemaphoreInit();
    RvLockInit();

    RvPrintf("RvMemoryInit: ");
    result = RvMemoryInit();
    if(result != RV_OK) {
        RvMemoryPrintError(result);
    } else RvPrintf("OK\n");

    /* Allocate and free from default region */
    RvPrintf("RvMemoryAlloc (NULL): ");
    result = RvMemoryAlloc(NULL, &memptr, 1000);
    if(result != RV_OK) {
        RvMemoryPrintError(result);
    } else RvPrintf("OK (%p)\n", memptr);

    RvPrintf("RvMemoryFree: ");
    result = RvMemoryFree(memptr);
    if(result != RV_OK) {
        RvMemoryPrintError(result);
    } else RvPrintf("OK\n");

    /* Clean up */
    RvPrintf("RvMemoryEnd: ");
    result = RvMemoryEnd();
    if(result != RV_OK) {
        RvMemoryPrintError(result);
    } else RvPrintf("OK\n");

    /* Shut down other needed modules */
    RvLockEnd();
    RvSemaphoreEnd();
}

#endif /* RV_TEST_CODE */

⌨️ 快捷键说明

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