NT4/private/windows/rover/filesync/syncui/mem.c
2020-09-30 17:12:29 +02:00

512 lines
10 KiB
C

#include "brfprv.h"
//========== Memory Management =============================================
#ifndef WIN32
#define MAX_WORD 0xffff
DECLARE_HANDLE(HHEAP);
typedef struct { // maps to the bottom of a 16bit DS
WORD reserved[8];
WORD cAlloc;
WORD cbAllocFailed;
HHEAP hhpFirst;
HHEAP hhpNext;
} HEAP;
#define PHEAP(hhp) ((HEAP *)MAKELP(hhp, 0))
#define MAKEHP(sel, off) ((void _huge*)MAKELP((sel), (off)))
#define CBSUBALLOCMAX 0x0000f000L
HHEAP g_hhpFirst = NULL;
BOOL DestroyHeap(HHEAP hhp);
void Mem_Terminate()
{
while (g_hhpFirst)
DestroyHeap(g_hhpFirst);
}
BOOL CreateHeap(WORD cbInitial)
{
HHEAP hhp;
if (cbInitial < 1024)
cbInitial = 1024;
hhp = (HHEAP)GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_SHARE, cbInitial);
if (!hhp)
return FALSE;
if (!LocalInit((WORD)hhp, sizeof(HEAP), cbInitial - 1))
{
GlobalFree(hhp);
return FALSE;
}
PHEAP(hhp)->cAlloc = 0;
PHEAP(hhp)->cbAllocFailed = MAX_WORD;
PHEAP(hhp)->hhpNext = g_hhpFirst;
g_hhpFirst = hhp;
DebugMsg(DM_TRACE, TEXT("CreateHeap: added new local heap %x"), hhp);
return TRUE;
}
#pragma optimize("o", off) // linked list removals don't optimize correctly
BOOL DestroyHeap(HHEAP hhp)
{
ASSERT(hhp);
ASSERT(g_hhpFirst);
if (g_hhpFirst == hhp)
{
g_hhpFirst = PHEAP(hhp)->hhpNext;
}
else
{
HHEAP hhpT = g_hhpFirst;
while (PHEAP(hhpT)->hhpNext != hhp)
{
hhpT = PHEAP(hhpT)->hhpNext;
if (!hhpT)
return FALSE;
}
PHEAP(hhpT)->hhpNext = PHEAP(hhp)->hhpNext;
}
if (GlobalFree((HGLOBAL)hhp) != NULL)
return FALSE;
return TRUE;
}
#pragma optimize("", on) // back to default optimizations
#pragma optimize("lge", off) // Suppress warnings associated with use of _asm...
void * HeapAlloc(HHEAP hhp, WORD cb)
{
void * pb;
_asm {
push ds
mov ds,hhp
}
pb = (void *)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, cb);
if (pb)
((HEAP *)0)->cAlloc++;
_asm {
pop ds
}
return pb;
}
#pragma optimize("o", off) // linked list removals don't optimize correctly
void _huge* WINAPI SharedAlloc(long cb)
{
void * pb;
HHEAP hhp;
HHEAP hhpPrev;
// If this is a big allocation, just do a global alloc.
//
if (cb > CBSUBALLOCMAX)
{
void * lpb = MAKEHP(GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_SHARE, cb), 0);
if (!lpb)
DebugMsg(DM_ERROR, TEXT("Alloc: out of memory"));
return lpb;
}
hhp = g_hhpFirst;
while (TRUE)
{
if (hhp == NULL)
{
if (!CreateHeap(0))
{
DebugMsg(DM_ERROR, TEXT("Alloc: out of memory"));
return NULL;
}
hhp = g_hhpFirst;
}
pb = HeapAlloc(hhp, (WORD)cb);
if (pb)
return MAKEHP(hhp, pb);
// Record the size of the allocation that failed.
// Later attempts to allocate more than this amount
// will not succeed. This gets reset anytime anything
// is freed in the heap.
//
PHEAP(hhp)->cbAllocFailed = (WORD)cb;
// First heap is full... see if there's room in any other heap...
//
for (hhpPrev = hhp; hhp = PHEAP(hhp)->hhpNext; hhpPrev = hhp)
{
// If the last allocation to fail in this heap
// is not larger than cb, don't even try an allocation.
//
if ((WORD)cb >= PHEAP(hhp)->cbAllocFailed)
continue;
pb = HeapAlloc(hhp, (WORD)cb);
if (pb)
{
// This heap had room: move it to the front...
//
PHEAP(hhpPrev)->hhpNext = PHEAP(hhp)->hhpNext;
PHEAP(hhp)->hhpNext = g_hhpFirst;
g_hhpFirst = hhp;
return MAKEHP(hhp, pb);
}
else
{
// The alloc failed. Set cbAllocFailed...
//
PHEAP(hhp)->cbAllocFailed = (WORD)cb;
}
}
}
}
#pragma optimize("", on) // back to default optimizations
#pragma optimize("lge", off) // Suppress warnings associated with use of _asm...
void _huge* WINAPI SharedReAlloc(void _huge* pb, long cb)
{
void * pbNew;
void _huge* lpbNew;
UINT cbOld;
// BUGBUG, does not work with cb > 64k
if (!pb)
return SharedAlloc(cb);
if (OFFSETOF(pb) == 0)
return MAKEHP(GlobalReAlloc((HGLOBAL)SELECTOROF(pb), cb, GMEM_MOVEABLE | GMEM_ZEROINIT), 0);
_asm {
push ds
mov ds,word ptr [pb+2]
}
pbNew = (void *)LocalReAlloc((HLOCAL)OFFSETOF(pb), (int)cb, LMEM_MOVEABLE | LMEM_ZEROINIT);
if (!pbNew)
cbOld = LocalSize((HLOCAL)OFFSETOF(pb));
_asm {
pop ds
}
if (pbNew)
return MAKEHP(SELECTOROF(pb), pbNew);
lpbNew = SharedAlloc(cb);
if (lpbNew)
{
hmemcpy((void *)lpbNew, (void *)pb, cbOld);
Free(pb);
}
else
{
DebugMsg(DM_ERROR, TEXT("ReAlloc: out of memory"));
}
return lpbNew;
}
BOOL WINAPI SharedFree(void _huge* * ppb)
{
BOOL fSuccess;
UINT cAlloc;
void _huge * pb = *ppb;
if (!pb)
return FALSE;
*ppb = 0;
if (OFFSETOF(pb) == 0)
return (GlobalFree((HGLOBAL)SELECTOROF(pb)) == NULL);
_asm {
push ds
mov ds,word ptr [pb+2]
}
fSuccess = (LocalFree((HLOCAL)OFFSETOF(pb)) ? FALSE : TRUE);
cAlloc = 1;
if (fSuccess)
{
cAlloc = --((HEAP *)0)->cAlloc;
((HEAP *)0)->cbAllocFailed = MAX_WORD;
}
_asm {
pop ds
}
if (cAlloc == 0)
DestroyHeap((HHEAP)SELECTOROF(pb));
return fSuccess;
}
DWORD WINAPI SharedGetSize(void _huge* pb)
{
WORD wSize;
if (OFFSETOF(pb) == 0)
return GlobalSize((HGLOBAL)SELECTOROF(pb));
_asm {
push ds
mov ds,word ptr [pb+2]
}
wSize = LocalSize((HLOCAL)OFFSETOF(pb));
_asm {
pop ds
}
return (DWORD)wSize;
}
#if 0
// hmemcpy() is faster (says davidds)
void WINAPI MemCopy(void * pTo, const void * pFrom, UINT cb)
{
_asm {
mov cx,cb
jcxz mcexit
;; push si
;; push di
mov dx,ds
lds si,pFrom
les di,pTo
cmp si,di
jae mccopyup
mov ax,cx
dec ax
dec ax
add si,ax
add di,ax
std
shr cx,1
rep movsw
jnc mc100
inc si
inc di
movsb
mc100:
cld
jmp short mcexit
mccopyup:
cld
shr cx,1
rep movsw
jnc mc200
movsb
mc200:
mcexit:
mov ds,dx
;; pop di
;; pop si
}
}
#endif
#pragma optimize("", on)
#else // WIN32
// Define a Global Shared Heap that we use allocate memory out of that we
// Need to share between multiple instances.
HANDLE g_hSharedHeap = NULL;
#define MAXHEAPSIZE 2097152
#define HEAP_SHARED 0x04000000 /* put heap in shared memory */
//----------------------------------------------------------------------------
void PUBLIC Mem_Terminate()
{
// Assuming that everything else has exited
//
if (g_hSharedHeap != NULL)
HeapDestroy(g_hSharedHeap);
g_hSharedHeap = NULL;
}
//----------------------------------------------------------------------------
void * WINAPI SharedAlloc(long cb)
{
// I will assume that this is the only one that needs the checks to
// see if the heap has been previously created or not
if (g_hSharedHeap == NULL)
{
ENTEREXCLUSIVE()
if (g_hSharedHeap == NULL)
{
#ifdef WINNT
g_hSharedHeap = HeapCreate(0, 1, MAXHEAPSIZE);
#else
g_hSharedHeap = HeapCreate(HEAP_SHARED, 1, MAXHEAPSIZE);
#endif
}
LEAVEEXCLUSIVE()
// If still NULL we have problems!
if (g_hSharedHeap == NULL)
return(NULL);
}
return HeapAlloc(g_hSharedHeap, HEAP_ZERO_MEMORY, cb);
}
//----------------------------------------------------------------------------
void * WINAPI SharedReAlloc(void * pb, long cb)
{
if (pb==NULL)
{
return SharedAlloc(cb);
}
return HeapReAlloc(g_hSharedHeap, HEAP_ZERO_MEMORY, pb, cb);
}
//----------------------------------------------------------------------------
BOOL WINAPI SharedFree(void ** ppb)
{
void * pb = *ppb;
if (!pb)
return FALSE;
*ppb = 0;
return HeapFree(g_hSharedHeap, 0, pb);
}
//----------------------------------------------------------------------------
DWORD WINAPI SharedGetSize(void * pb)
{
return HeapSize(g_hSharedHeap, 0, pb);
}
//----------------------------------------------------------------------------
// The following functions are for debug only and are used to try to
// calculate memory usage.
//
#ifdef DEBUG
typedef struct _HEAPTRACE
{
DWORD cAlloc;
DWORD cFailure;
DWORD cReAlloc;
DWORD cbMaxTotal;
DWORD cCurAlloc;
DWORD cbCurTotal;
} HEAPTRACE;
HEAPTRACE g_htSync = {0}; // Start of zero...
LPVOID WINAPI MemAlloc(HANDLE hheap, DWORD cb)
{
LPVOID lp;
lp = HeapAlloc(hheap, HEAP_ZERO_MEMORY, cb);
if (lp == NULL)
{
g_htSync.cFailure++;
return NULL;
}
// Update counts.
g_htSync.cAlloc++;
g_htSync.cCurAlloc++;
g_htSync.cbCurTotal += cb;
if (g_htSync.cbCurTotal > g_htSync.cbMaxTotal)
g_htSync.cbMaxTotal = g_htSync.cbCurTotal;
return lp;
}
LPVOID WINAPI MemReAlloc(HANDLE hheap, LPVOID pb, DWORD cb)
{
LPVOID lp;
DWORD cbOld;
cbOld = HeapSize(hheap, 0, pb);
lp = HeapReAlloc(hheap, HEAP_ZERO_MEMORY, pb,cb);
if (lp == NULL)
{
g_htSync.cFailure++;
return NULL;
}
// Update counts.
g_htSync.cReAlloc++;
g_htSync.cbCurTotal += cb - cbOld;
if (g_htSync.cbCurTotal > g_htSync.cbMaxTotal)
g_htSync.cbMaxTotal = g_htSync.cbCurTotal;
return lp;
}
BOOL WINAPI MemFree(HANDLE hheap, LPVOID pb)
{
BOOL fRet;
DWORD cbOld;
cbOld = HeapSize(hheap, 0, pb);
fRet = HeapFree(hheap, 0, pb);
if (fRet)
{
// Update counts.
g_htSync.cCurAlloc--;
g_htSync.cbCurTotal -= cbOld;
}
return(fRet);
}
DWORD WINAPI MemSize(HANDLE hheap, LPVOID pb)
{
return HeapSize(hheap, 0, pb);
}
#endif
#endif // WIN32