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

📄 osapi_mempool.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
字号:
/*****************************************************************************
******************************************************************************
**                                                                          **
**  Copyright (c) 2006 Videon Central, Inc.                                 **
**  All rights reserved.                                                    **
**                                                                          **
**  The computer program contained herein contains proprietary information  **
**  which is the property of Videon Central, Inc.  The program may be used  **
**  and/or copied only with the written permission of Videon Central, Inc.  **
**  or in accordance with the terms and conditions stipulated in the        **
**  agreement/contract under which the programs have been supplied.         **
**                                                                          **
******************************************************************************
*****************************************************************************/
/**
 * @file osapi_mempool.cpp
 *
 * $Revision: 1.5 $ 
 *
 * Operating System API (OSAPI) source file. Provides an abstraction from the
 * operating system.
 *
 * This is the implementation for win32
 *
 */

#include "osapi.h"
#include "dbgprint.h"
#include <stdlib.h>


/*
 * Memory Pool ID record
 */
typedef struct tagMemPoolRecord
{
    ULONG          ulPgSize;           /* Size of each page of memory */
    ULONG          ulNumPages;         /* Number of memory pages */
    struct Page                        /* A page from a memory pool */
    {
        PVOID      pvPgAddr;           /* Pointer to memory address */
        LONG       lAttached;          /* Number of pages attached with page *
                                        * (including itself)                 */
    } *memPage;
} OS_MEMPOOL;






/**
 * OS memory pool Information function. Prints out information about
 * the specified memory pool.  This information includes the number of
 * pages in the memory pool, the page size, the address of each memory
 * page, and if each page is allocated or not.
 *
 * @param pool   - The memory pool ID
 *
 * @retval
 *    None.
 *
 * @remark
 *    None.
 *
 * @verified
 *    No.
 */
void OS_MemoryInfo(OS_MEMPOOL_ID pool)
{
    ULONG i;
    if (pool == NULL)
    {
#ifdef __CALC_PEAK_ALLOCATION
        DBGPRINT(1, ("OS_MemoryInfo:\n"));
        DBGPRINT(1, ("/tPeak Allocations    = %d Bytes\n", ulPeakAllocations));
        DBGPRINT(1, ("/tCurrent Allocations = %d Bytes\n", ulCurrentAllocations));
#endif
    }
    else
    {
        OS_MEMPOOL *tmpPool = (OS_MEMPOOL *)pool;  /* Pointer to memory pool */
        CHAR       cUsed;                          /* Indicates if page allocated */
        LONG       lAtt;                           /* Indicates # pages attached */

        DbgPrint( ("\n----- Memory Pool Information -----\n") );
        DbgPrint( ("Number of Pages: %d\n", tmpPool->ulNumPages) );
        DbgPrint( ("Page Size:       %d\n", tmpPool->ulPgSize) );
        DbgPrint( ("Memory Pages:\n") );
        DbgPrint( ("\tPage\tAddress\t\tAllocated?\n") );
        for ( i = 0; i < tmpPool->ulNumPages; i++)
        {
            if (tmpPool->memPage[i].lAttached < 0)
            {
                lAtt  =  -1 * tmpPool->memPage[i].lAttached;
                cUsed = 'Y';
            }
            else
            {
                lAtt  = tmpPool->memPage[i].lAttached;
                cUsed = 'N';
            }
            DbgPrint( ("\t%d:\t%x\t\t%c\n", i + 1, (ULONG)tmpPool->memPage[i].pvPgAddr, cUsed) );
        }
    }

    return;
}






/**
 * Creates a memory pool with the specified page size. This function does not
 * allocate the memory for the pool. The memory address is provided as an input.
 *
 * @param pAddr      - pointer to allocated memory buffer
 * @param ulSize     - Size of the memory pool
 * @param ulPageSize - Page size of allocations from the pool. All allocations
 *                     will be a multiple of this size.
 *
 * @retval non-negative memPoolID if success, NULL otherwise.
 *
 * @remark
 *    If ulSize is not a multiple of ulPageSize, then the memory pool
 *    will only contain the number of whole pages that fit in the size
 *    ulSize.
 *
 * @verified
 *    No.
 */
OS_MEMPOOL_ID OS_CreateMemPool(PVOID pvAddr, ULONG ulSize, ULONG ulPageSize)
{
    PVOID          pvTmpAddr;           /* Address of a page in memory pool */
    OS_MEMPOOL     *tmpPool = NULL;     /* Pointer to memory pool */
    ULONG          ulArraySize;         /* Size of array to hold memory pool */

    if ( (pvAddr == NULL) || (ulPageSize == 0) )
    {
        return (NULL);
    }

    /*
     * Allocate memory for the memory pool.
     */
    tmpPool = (OS_MEMPOOL *)OS_MemAlloc(sizeof(OS_MEMPOOL) );
    if (tmpPool == NULL)
    {
        return (NULL);
    }

    /*
     * Set value for memory pool page size and the number of pages.
     */
    tmpPool->ulPgSize   = ulPageSize;
    tmpPool->ulNumPages = ulSize / ulPageSize;

    /*
     * Allocate an array large enough to hold the memory pool.
     */
    ulArraySize         = sizeof(OS_MEMPOOL::Page) * tmpPool->ulNumPages;
    tmpPool->memPage    = (OS_MEMPOOL::Page *)OS_MemAlloc(ulArraySize);
    if (tmpPool->memPage == NULL)
    {
        (void)OS_MemFree(tmpPool);
        return (NULL);
    }

    /*
     * Give a memory address to each page in the memory pool.  Also,
     * each page is given a value of the number of pages attached to
     * it, including itself.
     */
    pvTmpAddr = pvAddr;
    for (ULONG i = 0; i < tmpPool->ulNumPages; i++)
    {
        tmpPool->memPage[i].pvPgAddr   = pvTmpAddr;
        tmpPool->memPage[i].lAttached  = tmpPool->ulNumPages - i;
        pvTmpAddr                      = (BYTE *)pvTmpAddr + ulPageSize;
    }

    return ( (OS_MEMPOOL_ID)tmpPool);

}






/**
 * Deletes a memory pool created by OS_CreateMemPool. This does not release the memory
 * buffer used by the pool. This memory should be released by the application.
 *
 * @param pool   - The memory pool ID
 *
 * @retval OS_OK if successful, an osapi error code otherwise.
 *
 * @remark
 *    None.
 *
 * @verified
 *    No.
 */
OS_STATUS OS_DeleteMemPool(OS_MEMPOOL_ID pool)
{
    OS_MEMPOOL *tmpPool = (OS_MEMPOOL *)pool;   /* Pointer to memory pool */

    /*
     * If memory pool ID is NULL, then return.
     */
    if (pool == NULL)
    {
        return (OS_INVALID_MEMPOOL);
    }

    /*
     * Free any memory used by memory pool.
     */
    OS_MemFree(tmpPool->memPage);
    OS_MemFree(pool);

    return (OS_OK);
}






/**
 * Allocates a block of memory from the specified memory pool.
 *
 * @param pool   - The memory pool ID
 * @param ulSize - Size of memory block to allocate.
 *
 * @retval - pointer to allocated memory if successful, NULL if not successful
 *
 * @remark
 *    None.
 *
 * @verified
 *    No.
 */
PVOID OS_MemPoolAlloc(OS_MEMPOOL_ID pool, ULONG ulSize)
{
    LONG        lPgNeeded;                     /* Number of pages needed to allocate the *
                                                * requested block of memory.             */
    OS_MEMPOOL  *tmpPool = (OS_MEMPOOL *)pool; /* Pointer to memory pool */
    ULONG i;                                   /* Loop iterator */

    /*
     * If invalid memory pool, return.
     */
    if (pool == NULL)
    {
        return NULL;
    }

    /*
     * Determine how many pages are needed for the requested amount
     * of memory.
     */
    lPgNeeded = (ulSize / tmpPool->ulPgSize);
    if (ulSize % tmpPool->ulPgSize != 0)
    {
        ++lPgNeeded;
    }

    /* Search for a block of pages that have at least the number
     * of pages needed consecutively.  Once a block is found, return
     * the address of the first page of this block. If no blocks large
     * enough are found, then return NULL.
     */
    i = 0;
    while (i < tmpPool->ulNumPages)
    {
        /*
         * Look at the number of pages attached to the current page to
         * determine if the block of pages is large enough to use.  If
         * the number of pages attached is a negative value, then move ahead
         * that number of pages (positive value) because those pages are allocated.
         * If the number of pages attached is less than the number of pages
         * needed, then move ahead that number of pages because the block of
         * pages is not large enough.  Otherwise, the block is large enough,
         * so allocate a block starting at current page.
         */
        if (tmpPool->memPage[i].lAttached < 0)
        {
            i = i + (-1 * tmpPool->memPage[i].lAttached);
        }
        else if (tmpPool->memPage[i].lAttached < lPgNeeded)
        {
            i = i + tmpPool->memPage[i].lAttached;
        }
        else
        {
            /*
             * Adjust the number of pages attached to the allocated pages.
             * Simply change number to negative.
             */
            LONG lPages = lPgNeeded;
            for (ULONG j = i; j < (i + lPgNeeded); j++)
            {
                tmpPool->memPage[j].lAttached = -1 * lPages;
                lPages = lPages - 1;
            }

            return (tmpPool->memPage[i].pvPgAddr);
        }
    }

    return (NULL);
}






/**
 * Frees the given memory block back to the specified memory pool
 *
 * @param pool   - The memory pool ID
 * @param pvMemory - The address
 *
 * @retval - OS_OK if sucessful, an osapi error code otherwise.
 *
 * @remark
 *    None.
 *
 * @verified
 *    No.
 */
OS_STATUS OS_MemPoolFree(OS_MEMPOOL_ID pool, PVOID pvMemory)
{
   LONG        lIndex,                          /* Page number in memory pool */
                lNextIndex;                      /* Page number of next block  */
    OS_MEMPOOL  *tmpPool = (OS_MEMPOOL *)pool;   /* Pointer to memory pool */
    ULONG       ulFront,                         /* Beginning and end address of */
                ulEnd;                           /* memory pool.                 */
    /*
     * If null pointer was passed, return.
     */
    if (pvMemory == NULL)
    {
        return (OS_NULL_POINTER);
    }

    /*
     * Check that memory is in the specified memory pool. If it's not
     * then do not free the memory.
     */
    ulFront = (ULONG)tmpPool->memPage[0].pvPgAddr;
    ulEnd   = (ULONG)tmpPool->memPage[tmpPool->ulNumPages - 1].pvPgAddr +
              tmpPool->ulPgSize;
    if ( ( (ULONG)pvMemory < ulFront) || ( (ULONG)pvMemory >= ulEnd) ||
         (pool == NULL) )
    {
        return (OS_INVALID_MEMPOOL);
    }

    /*
     * Determine, from the address, which page(s) to free.  If address
     * is not a page address, then return.
     */
    lIndex     = (BYTE *)pvMemory - (BYTE *)tmpPool->memPage[0].pvPgAddr;
    if (lIndex % tmpPool->ulPgSize != 0)
    {
        return (OS_FAILURE);
    }
    lIndex     = lIndex / tmpPool->ulPgSize;

    /*
     * Make sure that the memory address given is not already free.
     */
    if (tmpPool->memPage[lIndex].lAttached >= 0)
    {
        return (OS_FAILURE);
    }

    /*
     * Adjust the number of pages attached to the freed page(s).
     */
    lNextIndex = lIndex + (-1 * tmpPool->memPage[lIndex].lAttached);
    LONG i;
    if (tmpPool->memPage[lNextIndex].lAttached > 0)
    {
        /*
         * Need to add the number of pages attached to the pages
         * following the freed pages.
         */
        for (i = lIndex; i < lNextIndex; i++)
        {
            tmpPool->memPage[i].lAttached =
                    (-1 * tmpPool->memPage[i].lAttached) +
                    tmpPool->memPage[lNextIndex].lAttached;
        }
    }
    else
    {
        /*
         * No non-allocated pages following the freed pages.
         */
        for (i = lIndex; i < lNextIndex; i++)
        {
            tmpPool->memPage[i].lAttached =
                    (-1 * tmpPool->memPage[i].lAttached);
        }
    }

    /*
     * Adjust the number of pages attached to any pages preceding the
     * freed pages.
     */
    i = lIndex - 1;
    while ( (tmpPool->memPage[i].lAttached >= 0) && (i >= 0) )
    {
        tmpPool->memPage[i].lAttached += tmpPool->memPage[lIndex].lAttached;
        i = i - 1;
    }

    return (OS_OK);
}






/**
 * Frees all memory blocks back to the specified memory pool
 *
 * @param pool   - The memory pool ID
 *
 * @retval - OS_OK if sucessful, an osapi error code otherwise.
 *
 * @remark
 *    None.
 *
 * @verified
 *    No.
 */
OS_STATUS OS_MemPoolReset(OS_MEMPOOL_ID pool)
{
    OS_MEMPOOL *pMemPool = (OS_MEMPOOL *)pool;

    if (pool == NULL)
    {
        DbgPrint(("OS_MemPoolReset: NULL pointer!\n"));
        return (OS_NULL_POINTER);
    }

    /* Free all pages of mempool */
    for (ULONG i = 0; i < pMemPool->ulNumPages; i++)
    {
        pMemPool->memPage[i].lAttached  = pMemPool->ulNumPages - i;
    }

    return (OS_OK);
}


⌨️ 快捷键说明

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