📄 osapi_mempool.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 + -