windows-nt/Source/XPSP1/NT/net/upnp/host/upnphost/udhhttp/utilmemf.cpp
2020-09-26 16:20:57 +08:00

230 lines
5.3 KiB
C++

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
utilmemf.cxx
Abstract:
Miscellaneous useful utilities
Author:
Sergey Solyanik (SergeyS)
--*/
#include "pch.h"
#pragma hdrstop
#include <svsutil.hxx>
//
// Fixed memory sector
//
struct FixedMemList
{
union
{
unsigned char ucaPlaceholder[SVSUTIL_MAX_ALIGNMENT];
struct FixedMemList *pfmlNext;
} u;
unsigned char bData[1];
};
struct FixedMemDescr
{
void **ppvFreeList;
FixedMemList *pfml;
CRITICAL_SECTION *pcs;
unsigned int uiBlockSize;
unsigned int uiBlockIncr;
unsigned int uiListSize;
};
FixedMemDescr *svsutil_AllocFixedMemDescr (unsigned int a_uiBlockSize, unsigned int a_uiBlockIncr) {
SVSUTIL_ASSERT (a_uiBlockSize);
SVSUTIL_ASSERT (a_uiBlockIncr);
if (a_uiBlockSize < sizeof(void *))
a_uiBlockSize = sizeof (void *);
FixedMemDescr *pfmd = (FixedMemDescr *)g_funcAlloc (sizeof(FixedMemDescr), g_pvAllocData);
if (! pfmd)
return NULL;
pfmd->ppvFreeList = NULL;
pfmd->pfml = NULL;
pfmd->pcs = NULL;
pfmd->uiBlockSize = a_uiBlockSize;
pfmd->uiBlockIncr = a_uiBlockIncr;
pfmd->uiListSize = offsetof (FixedMemList, bData) + a_uiBlockSize * a_uiBlockIncr;
return pfmd;
}
FixedMemDescr *svsutil_AllocFixedMemDescrSynch (unsigned int a_uiBlockSize, unsigned int a_uiBlockIncr, CRITICAL_SECTION *a_pcs) {
SVSUTIL_ASSERT (a_uiBlockSize);
SVSUTIL_ASSERT (a_uiBlockIncr);
SVSUTIL_ASSERT (a_pcs);
if (a_uiBlockSize < sizeof(void *))
a_uiBlockSize = sizeof (void *);
FixedMemDescr *pfmd = (FixedMemDescr *)g_funcAlloc (sizeof(FixedMemDescr), g_pvAllocData);
if (! pfmd)
return NULL;
pfmd->ppvFreeList = NULL;
pfmd->pfml = NULL;
pfmd->pcs = a_pcs;
pfmd->uiBlockSize = a_uiBlockSize;
pfmd->uiBlockIncr = a_uiBlockIncr;
pfmd->uiListSize = offsetof (FixedMemList, bData) + a_uiBlockSize * a_uiBlockIncr;
return pfmd;
}
int svsutil_IsFixedEmpty (FixedMemDescr *a_pfmd) {
return a_pfmd->pfml == NULL;
}
int svsutil_FixedBlockSize (FixedMemDescr *a_pfmd) {
return a_pfmd->uiBlockSize;
}
void *svsutil_GetFixed (FixedMemDescr *a_pfmd) {
if (a_pfmd->pcs)
EnterCriticalSection (a_pfmd->pcs);
if (! a_pfmd->ppvFreeList)
{
FixedMemList *pfml = (FixedMemList *)g_funcAlloc (a_pfmd->uiListSize, g_pvAllocData);
pfml->u.pfmlNext = a_pfmd->pfml;
a_pfmd->pfml = pfml;
a_pfmd->ppvFreeList = (void **)&pfml->bData[0];
unsigned char *pucRunner = (unsigned char *)a_pfmd->ppvFreeList;
unsigned char *pucEndRun = ((unsigned char *)pfml) + a_pfmd->uiListSize;
for ( ; ; )
{
unsigned char *pucRunnerNext = pucRunner + a_pfmd->uiBlockSize;
if (pucRunnerNext >= pucEndRun)
{
*(void **)pucRunner = NULL;
break;
}
*(void **)pucRunner = (void *)pucRunnerNext;
pucRunner = pucRunnerNext;
}
}
void *pvPtr = (void *)a_pfmd->ppvFreeList;
a_pfmd->ppvFreeList = (void **)*a_pfmd->ppvFreeList;
if (a_pfmd->pcs)
LeaveCriticalSection (a_pfmd->pcs);
return pvPtr;
}
void svsutil_FreeFixed (void *pvData, FixedMemDescr *a_pfmd) {
if (a_pfmd->pcs)
EnterCriticalSection (a_pfmd->pcs);
#if defined (SVSUTIL_DEBUG_HEAP)
void **ppvFreeList = a_pfmd->ppvFreeList;
while (ppvFreeList)
{
SVSUTIL_ASSERT(pvData != ppvFreeList); // Otherwise has already been freed
ppvFreeList = (void **)*ppvFreeList;
}
FixedMemList *pfml = a_pfmd->pfml;
while (pfml)
{
if ((pvData > pfml) && (pvData < ((unsigned char *)pfml + a_pfmd->uiListSize)))
break;
pfml = pfml->u.pfmlNext;
}
SVSUTIL_ASSERT (pfml); // Otherwise not part of any block!
memset (pvData, 0xff, a_pfmd->uiBlockSize);
#endif
*(void **)pvData = (void *)a_pfmd->ppvFreeList;
a_pfmd->ppvFreeList = (void **)pvData;
if (a_pfmd->pcs)
LeaveCriticalSection (a_pfmd->pcs);
}
void svsutil_ReleaseFixedNonEmpty (FixedMemDescr *a_pfmd) {
if (a_pfmd->pcs)
EnterCriticalSection (a_pfmd->pcs);
FixedMemList *pfml = a_pfmd->pfml;
while (pfml)
{
FixedMemList *pfmlNext = pfml->u.pfmlNext;
g_funcFree (pfml, g_pvFreeData);
pfml = pfmlNext;
}
if (a_pfmd->pcs)
LeaveCriticalSection (a_pfmd->pcs);
g_funcFree (a_pfmd, g_pvFreeData);
}
void svsutil_ReleaseFixedEmpty (FixedMemDescr *a_pfmd) {
if (a_pfmd->pcs)
EnterCriticalSection (a_pfmd->pcs);
#if defined (SVSUTIL_DEBUG_HEAP)
unsigned int uiBlockCount = 0;
void **ppvRunner = a_pfmd->ppvFreeList;
while (ppvRunner)
{
++uiBlockCount;
ppvRunner = (void **)*ppvRunner;
}
unsigned int uiBlockCount2 = 0;
FixedMemList *pfmlRunner = a_pfmd->pfml;
while (pfmlRunner)
{
uiBlockCount2 += a_pfmd->uiBlockIncr;
pfmlRunner = pfmlRunner->u.pfmlNext;
}
SVSUTIL_ASSERT (uiBlockCount == uiBlockCount2);
#endif
if (a_pfmd->pcs)
LeaveCriticalSection (a_pfmd->pcs);
svsutil_ReleaseFixedNonEmpty (a_pfmd);
}