You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
6.1 KiB
201 lines
6.1 KiB
#include <cache.hxx>
|
|
|
|
#ifdef TEST
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <windows.h>
|
|
#include "hndlmgr.hxx"
|
|
|
|
#define ALLOCATE_FIXED_MEMORY(size) malloc(size)
|
|
#define REALLOCATE_MEMORY(ptr, size, flags) realloc(ptr, size)
|
|
#define FREE_MEMORY(ptr) free(ptr)
|
|
|
|
int main ()
|
|
{
|
|
HNDLMGR HandleMgr;
|
|
HANDLE h[10];
|
|
HANDLE hBad = (HANDLE) 5150;
|
|
|
|
// Test alloc and realloc of handle heap.
|
|
for (int i=9; i>=0; i--)
|
|
{
|
|
h[i] = HandleMgr.Alloc (54);
|
|
printf ("Alloc h[%d] = %d\n", i, (DWORD) h[i]);
|
|
}
|
|
|
|
// Test invalid, valid, and double free.
|
|
printf ("Free(%d) returns %d\n", NULL, HandleMgr.Free(NULL));
|
|
printf ("Free(%d) returns %d\n", hBad, HandleMgr.Free(hBad));
|
|
printf ("Free(%d) returns %d\n", h[3], HandleMgr.Free(h[3]));
|
|
printf ("Free(%d) returns %d\n", h[3], HandleMgr.Free(h[3]));
|
|
printf ("Free(%d) returns %d\n", h[9], HandleMgr.Free(h[9]));
|
|
|
|
// Test mapping of invalid, free, and valid handles.
|
|
printf ("Map(%d) = %d\n", NULL, HandleMgr.Map(NULL));
|
|
printf ("Map(%d) = %d\n", hBad, HandleMgr.Map(hBad));
|
|
printf ("Map(%d) = %d\n", h[3], HandleMgr.Map(h[3]));
|
|
printf ("Map(%d) = %d\n", h[5], HandleMgr.Map(h[5]));
|
|
|
|
// Test recycling of handles from free list.
|
|
i = 3;
|
|
h[i] = HandleMgr.Alloc (42);
|
|
printf ("Alloc h[%d] = %d\n", i, (DWORD) h[i]);
|
|
i = 9;
|
|
h[i] = HandleMgr.Alloc (42);
|
|
printf ("Alloc h[%d] = %d\n", i, (DWORD) h[i]);
|
|
|
|
return 1;
|
|
}
|
|
|
|
#endif // TEST
|
|
|
|
#define INC_GROW 8
|
|
|
|
//=========================================================================
|
|
void HNDLMGR::Destroy (void)
|
|
{
|
|
if (pHeap)
|
|
{
|
|
for (DWORD iHandle=0; iHandle < pHeap->dwNumHandles; iHandle++)
|
|
{
|
|
if ((DWORD_PTR) pHeap->pvHandles[iHandle] >= pHeap->dwMaxHandles)
|
|
FREE_MEMORY (pHeap->pvHandles[iHandle]);
|
|
}
|
|
FREE_MEMORY (pHeap);
|
|
}
|
|
}
|
|
|
|
//=========================================================================
|
|
BOOL HNDLMGR::IsValidOffset (DWORD_PTR dwp)
|
|
{
|
|
return (pHeap && (dwp < pHeap->dwNumHandles) &&
|
|
((DWORD_PTR) pHeap->pvHandles[dwp]) >= pHeap->dwMaxHandles);
|
|
}
|
|
|
|
//=========================================================================
|
|
HANDLE HNDLMGR::Alloc (DWORD cbAlloc)
|
|
{
|
|
PVOID pTemp;
|
|
|
|
if (!pHeap)
|
|
{
|
|
// Allocate the heap.
|
|
pHeap = (HNDLHEAP*) ALLOCATE_FIXED_MEMORY
|
|
(sizeof(HNDLHEAP) + INC_GROW * sizeof(LPVOID));
|
|
if (!pHeap)
|
|
return NULL;
|
|
|
|
// Initialize the heap.
|
|
pHeap->dwNumHandles = 0;
|
|
pHeap->dwNumInUse = 0;
|
|
pHeap->dwMaxHandles = 0xFFFFFFFF;
|
|
pHeap->dwFirstFree = 0;
|
|
for (DWORD iHandle = 0; iHandle < INC_GROW; iHandle++)
|
|
{
|
|
pHeap->pvHandles[pHeap->dwNumHandles] =
|
|
(HANDLE) (pHeap->dwNumHandles + 1);
|
|
pHeap->dwNumHandles++;
|
|
}
|
|
}
|
|
|
|
else if (pHeap->dwFirstFree == pHeap->dwNumHandles)
|
|
{
|
|
// Reallocate the heap.
|
|
if (pHeap->dwNumHandles + INC_GROW >= pHeap->dwMaxHandles)
|
|
{
|
|
// Uh oh, heap is hit the lower bound set by the allocator.
|
|
return NULL;
|
|
}
|
|
pTemp = REALLOCATE_MEMORY (pHeap, sizeof(HNDLHEAP)
|
|
+ (pHeap->dwNumHandles + INC_GROW) * sizeof(LPVOID), LMEM_MOVEABLE);
|
|
if (!pTemp)
|
|
return NULL;
|
|
pHeap = (HNDLHEAP*) pTemp;
|
|
|
|
// Extend the free list.
|
|
for (DWORD iHandle = 0; iHandle < INC_GROW; iHandle++)
|
|
{
|
|
pHeap->pvHandles[pHeap->dwNumHandles] =
|
|
(HANDLE) (pHeap->dwNumHandles + 1);
|
|
pHeap->dwNumHandles++;
|
|
}
|
|
}
|
|
|
|
// Allocate a handle.
|
|
pTemp = ALLOCATE_FIXED_MEMORY (cbAlloc);
|
|
if (!pTemp)
|
|
return NULL;
|
|
if ((DWORD_PTR) pTemp < pHeap->dwNumHandles)
|
|
{
|
|
// Uh oh, allocator returned a low value!
|
|
FREE_MEMORY (pTemp);
|
|
return NULL;
|
|
}
|
|
if (pHeap->dwMaxHandles >= ((DWORD_PTR) pTemp))
|
|
pHeap->dwMaxHandles = ((DWORD_PTR) pTemp);
|
|
|
|
INET_ASSERT(pHeap->dwFirstFree < pHeap->dwNumHandles);
|
|
// Pop the handle off the top of the free list.
|
|
DWORD_PTR dwOffset = pHeap->dwFirstFree;
|
|
pHeap->dwFirstFree = (DWORD_PTR) pHeap->pvHandles[pHeap->dwFirstFree];
|
|
pHeap->pvHandles[dwOffset] = pTemp;
|
|
pHeap->dwNumInUse++;
|
|
return (HANDLE) (dwOffset + 1);
|
|
}
|
|
|
|
//=========================================================================
|
|
LPVOID HNDLMGR::Map (HANDLE h)
|
|
{
|
|
// Subtract one from handle to get offset.
|
|
DWORD_PTR dwOffset = (DWORD_PTR)h - 1;
|
|
if (!IsValidOffset (dwOffset) || (((DWORD_PTR) pHeap->pvHandles[dwOffset]) == -1))
|
|
{
|
|
return NULL;
|
|
}
|
|
else
|
|
return pHeap->pvHandles[dwOffset];
|
|
}
|
|
|
|
//=========================================================================
|
|
BOOL HNDLMGR::Free (HANDLE h)
|
|
{
|
|
// Subtract one from handle to get offset.
|
|
DWORD_PTR dwOffset = (DWORD_PTR)h - 1;
|
|
|
|
if (!IsValidOffset (dwOffset))
|
|
return FALSE;
|
|
|
|
if (((DWORD_PTR) pHeap->pvHandles[dwOffset]) != -1)
|
|
{
|
|
// Push the handle on the top of the free list.
|
|
FREE_MEMORY (pHeap->pvHandles[dwOffset]);
|
|
}
|
|
|
|
INET_ASSERT(pHeap->dwFirstFree <= pHeap->dwNumHandles);
|
|
pHeap->pvHandles[dwOffset] = (LPVOID) pHeap->dwFirstFree;
|
|
pHeap->dwFirstFree = dwOffset;
|
|
pHeap->dwNumInUse--;
|
|
return TRUE;
|
|
}
|
|
|
|
//=========================================================================
|
|
VOID HNDLMGR::InvalidateAll()
|
|
{
|
|
// We're in the process of switching identities; all cache handles
|
|
// should be invalidated so that they can no longer be used.
|
|
|
|
if (pHeap)
|
|
{
|
|
for (DWORD iHandle=0; iHandle < pHeap->dwNumHandles; iHandle++)
|
|
{
|
|
if (((DWORD_PTR) pHeap->pvHandles[iHandle] > pHeap->dwNumHandles)
|
|
&& ((DWORD_PTR) pHeap->pvHandles[iHandle] != -1))
|
|
{
|
|
FREE_MEMORY (pHeap->pvHandles[iHandle]);
|
|
pHeap->pvHandles[iHandle] = (HANDLE)-1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|