123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097 |
- //---------------------------------------------------------------------------
- //
- // Heap.cpp -- This file contains the definition for the Base HEAP
- // Manager Class. The Base HEAP manager creates,
- // manages and destroys block of memory using Win32
- // Virtual memory calls.h
- //
- //---------------------------------------------------------------------------//
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- //===========================================================================//
- //---------------------------------------------------------------------------
- // Include Files
- #ifndef HEAP_H
- #include "heap.h"
- #endif
- #ifndef FILE_H
- #include "file.h"
- #endif
- #include <windows.h>
- #include <imagehlp.h>
- #include <gameos.hpp>
- #include <tchar.h>
- #include <stdio.h> // For sprintf
- #include <string.h> // For strchr
- //---------------------------------------------------------------------------
- // Static Globals
- static char CorruptMsg[] = "Heap check failed.\n";
- static char pformat[] = "%s %s\n";
- GlobalHeapRec HeapList::heapRecords[MAX_HEAPS];
- HeapListPtr globalHeapList = NULL;
- unsigned long memCoreLeft = 0;
- unsigned long memTotalLeft = 0;
- unsigned long totalSize = 0;
- unsigned long totalCoreLeft = 0;
- unsigned long totalLeft = 0;
- bool HeapList::heapInstrumented = 0;
- //
- // Returns a context ready for stack walking from current address
- //
- void GetCurrentContext( CONTEXT* Context )
- {
- memset( Context, 0, sizeof(CONTEXT) );
- _asm
- {
- mov ebx,Context
- mov [ebx]+CONTEXT.Ebp,ebp
- mov [ebx]+CONTEXT.Esp,esp
- call GetEIP
- mov [ebx]+CONTEXT.Eip,eax
- jmp Exit
- GetEIP:
- pop eax
- push eax
- ret
- Exit:
- }
- }
- void InitStackWalk(STACKFRAME *sf, CONTEXT *Context);
- int WalkStack(STACKFRAME *sf);
- char* DecodeAddress( DWORD Address , bool brief);
- //---------------------------------------------------------------------------
- // Macro definitions
- #define USE_BEST_FIT
- #ifdef _DEBUG
- #define SAFE_HEAP
- #endif
- #ifdef _DEBUG
- #define CHECK_HEAP
- #endif
- #ifdef LAB_ONLY
- #define CHECK_HEAP
- #endif
- //---------------------------------------------------------------------------
- // Class HeapManager Member Functions
- HeapManager::~HeapManager (void)
- {
- destroy();
- }
-
- //---------------------------------------------------------------------------
- void HeapManager::destroy (void)
- {
- long result = 0;
-
- //-----------------------------
- // Remove this from the UEBER HEAP
- #ifdef CHECK_HEAP
- globalHeapList->removeHeap(this);
- #endif
-
- if (committedSize)
- {
- result = VirtualFree(heap,totalSize,MEM_DECOMMIT);
- if (result == FALSE)
- result = GetLastError();
- }
- if (totalSize && memReserved && heap)
- {
- result = VirtualFree(heap,0,MEM_RELEASE);
- if (result == FALSE)
- result = GetLastError();
- }
- init();
- }
-
- //---------------------------------------------------------------------------
- HeapManager::HeapManager (void)
- {
- init();
- }
-
- //---------------------------------------------------------------------------
- void HeapManager::init (void)
- {
- heap = NULL;
- memReserved = FALSE;
- totalSize = 0;
- committedSize = 0;
- nxt = NULL;
- }
-
- //---------------------------------------------------------------------------
- HeapManager::operator MemoryPtr (void)
- {
- return getHeapPtr();
- }
-
- //---------------------------------------------------------------------------
- MemoryPtr HeapManager::getHeapPtr (void)
- {
- if (memReserved && totalSize && committedSize && heap)
- return heap;
- return NULL;
- }
- //---------------------------------------------------------------------------
- long HeapManager::createHeap (unsigned long memSize)
- {
- heap = (MemoryPtr)VirtualAlloc(NULL,memSize,MEM_RESERVE,PAGE_READWRITE);
- if (heap)
- {
- memReserved = TRUE;
- totalSize = memSize;
- return NO_ERR;
- }
- return COULDNT_CREATE;
- }
- //---------------------------------------------------------------------------
- long HeapManager::commitHeap (unsigned long commitSize)
- {
- if (commitSize == 0)
- commitSize = totalSize;
-
- if (commitSize > totalSize)
- return ALLOC_TOO_BIG;
- if (commitSize < totalSize)
- return COULDNT_COMMIT;
- unsigned long memLeft = totalSize - committedSize;
-
- if (!memLeft)
- {
- return OUT_OF_MEMORY;
- }
- if (memLeft < commitSize)
- {
- commitSize = memLeft;
- }
- MemoryPtr result = (MemoryPtr)VirtualAlloc(heap,commitSize,MEM_COMMIT,PAGE_READWRITE);
- if (result == heap)
- {
- long actualSize = commitSize;
- committedSize += actualSize;
- #ifdef CHECK_HEAP
- //-----------------------------
- // Add this to the UEBER HEAP
- globalHeapList->addHeap(this);
- #endif
-
- //------------------------------
- // Store off who called this.
- // If this was a UserHeap,
- // the UserHeap class will
- // do its own unwind.
- unsigned long currentEbp;
- unsigned long prevEbp;
- unsigned long retAddr;
-
- __asm
- {
- mov currentEbp,esp
- }
-
- prevEbp = *((unsigned long *)currentEbp);
- retAddr = *((unsigned long *)(currentEbp+4));
- whoMadeMe = retAddr;
- return NO_ERR;
- }
- gosASSERT(false);
- return COULDNT_COMMIT;
- }
-
- //---------------------------------------------------------------------------
- long HeapManager::decommitHeap (unsigned long decommitSize)
- {
- long result = 0;
-
- if (decommitSize == 0)
- decommitSize = totalSize;
-
- if (decommitSize > committedSize)
- decommitSize = committedSize;
- if (decommitSize < committedSize)
- decommitSize = totalSize;
- unsigned long decommitAddress = decommitSize;
- committedSize -= decommitAddress;
- result = VirtualFree((void *)committedSize,decommitSize,MEM_DECOMMIT);
- if (result == FALSE)
- result = GetLastError();
-
- return NO_ERR;
- }
- /////////////////////////////////////////////////////////////
- //---------------------------------------------------------------------------
- // Class UserHeap Member Functions
- UserHeap::UserHeap (void) : HeapManager()
- {
- heapStart = NULL;
- heapEnd = NULL;
- firstNearBlock = NULL;
- heapSize = 0;
-
- #ifdef CHECK_HEAP
- mallocFatals = TRUE;
- #else
- mallocFatals = FALSE;
- #endif
-
- heapState = NO_ERR;
- }
- //---------------------------------------------------------------------------
- long UserHeap::init (unsigned long memSize, char *heapId, bool useGOS)
- {
- if (heapId)
- {
- heapName = (char *)::gos_Malloc(strlen(heapId)+1);
- strcpy(heapName,heapId);
- }
- else
- heapName = NULL;
- if (!useGOS)
- {
- long result = createHeap(memSize);
-
- if (result)
- STOP(("Could not create Heap %s. Error:%x",heapId,result));
-
- result = commitHeap(memSize);
-
- if (result)
- STOP(("Could not create Heap %s. Error:%x",heapId,result));
-
- //------------------------------
- // Store off who called this.
- // If this was a UserHeap,
- // the UserHeap class will
- // do its own unwind.
- unsigned long currentEbp;
- unsigned long prevEbp;
- unsigned long retAddr;
-
- __asm
- {
- mov currentEbp,esp
- }
-
- prevEbp = *((unsigned long *)currentEbp);
- retAddr = *((unsigned long *)(currentEbp+4));
- whoMadeMe = retAddr;
-
- //------------------------------------------------------------------------
- // Now that we have a pointer to the memory, setup the HEAP.
- unsigned long heapTop = (unsigned long)heap;
- heapTop += memSize;
- heapTop -= 16;
- heapTop &= ~3; //Force top to be DWORD boundary.
-
- unsigned long heapBottom = (unsigned long)heap;
-
- heapStart = (HeapBlockPtr)heapBottom;
- heapEnd = (HeapBlockPtr)heapTop;
-
- heapStart->blockSize = heapTop - heapBottom;
- heapStart->upperBlock = 0; //Nothing above this in memory.
-
- heapEnd->blockSize = 1; //Mark as last block.
- heapEnd->previous = (HeapBlockPtr)0x1572; //Mark as last block.
- heapEnd->upperBlock = (HeapBlockPtr)heapBottom;
-
- //--------------------------------
- // Set all free memory to -1.
- // Any access before ready and Exception city.
- MemoryPtr start = (MemoryPtr)heapBottom;
- start += sizeof(HeapBlock);
-
- unsigned long length = heapTop-heapBottom;
- length -= sizeof(HeapBlock);
-
- FillMemory(start,length,0xff);
-
- //----------------------------------
- // linkup heap blocks
- firstNearBlock = NULL;
- relink(heapStart);
-
- heapSize = memSize;
-
- #ifdef _DEBUG
- recordArray = NULL;
- recordCount = 0;
- logMallocs = FALSE;
- #endif;
-
- gosHeap = 0;
- }
- else
- {
- gosHeap = gos_CreateMemoryHeap(heapId,memSize);
- useGOSGuardPage = true;
- heapStart = NULL;
- heapEnd = NULL;
- firstNearBlock = NULL;
- heapSize = 0;
- heapName = NULL;
- heapState = NO_ERR;
- #ifdef _DEBUG
- recordArray = NULL;
- #endif
- }
-
- return NO_ERR;
- }
-
- #ifdef _DEBUG
- //---------------------------------------------------------------------------
- void UserHeap::startHeapMallocLog (void)
- {
- if (!recordArray)
- {
- recordArray = new memRecord[NUMMEMRECORDS];
- memset(recordArray, 0, sizeof(memRecord) * NUMMEMRECORDS);
- recordCount = 0;
- }
-
- logMallocs = TRUE;
- }
- //---------------------------------------------------------------------------
- void UserHeap::stopHeapMallocLog (void)
- {
- logMallocs = FALSE;
- }
- //---------------------------------------------------------------------------
- void UserHeap::dumpRecordLog (void)
- {
- if (recordArray)
- {
- File log;
- char msg[256];
- sprintf(msg,"heapdump.%s.log",heapName);
- log.create(msg);
- for (int i=0; i<NUMMEMRECORDS; i++)
- {
- if (recordArray[i].ptr)
- {
- sprintf(msg, "Allocated block at DS:%08X, size = %u\n", recordArray[i].ptr, recordArray[i].size);
- log.writeLine(msg);
- char* addressName = DecodeAddress(recordArray[i].stack[0],false);
- sprintf(msg, "Call stack: %08X : %s", recordArray[i].stack[0],addressName);
- log.writeLine(msg);
- for (int j=1; j<12; j++)
- {
-
- if (recordArray[i].stack[j] == 0x0)
- break;
- char* addressName = DecodeAddress(recordArray[i].stack[j],false);
- sprintf(msg, " %08X : %s", recordArray[i].stack[j],addressName);
- log.writeLine(msg);
- }
- log.writeByte('\n');
- }
- }
- log.close();
- }
- }
- #endif
-
- //---------------------------------------------------------------------------
- UserHeap::~UserHeap (void)
- {
- destroy();
- }
- //---------------------------------------------------------------------------
- void UserHeap::destroy (void)
- {
- HeapManager::destroy();
-
- if (!gosHeap)
- {
- heapStart = NULL;
- heapEnd = NULL;
- firstNearBlock = NULL;
- heapSize = 0;
- if (heapName)
- {
- ::gos_Free(heapName);
- heapName = NULL;
- }
- heapState = NO_ERR;
- #ifdef _DEBUG
- if (recordArray)
- {
- delete [] recordArray;
- recordArray = NULL;
- }
- #endif
- }
- else
- {
- gos_DestroyMemoryHeap(gosHeap,false);
- gosHeap = NULL;
- }
- }
-
- //---------------------------------------------------------------------------
- unsigned long UserHeap::totalCoreLeft (void)
- {
- unsigned long result = 0;
- if (gosHeap)
- return result;
- #ifdef SAFE_HEAP
- long localHeapState = heapState;
- #endif
- HeapBlockPtr localFirst = firstNearBlock;
- long heapBlockSize = -(long)allocatedBlockSize;
-
- if (!firstNearBlock)
- {
- #ifdef _DEBUG
- PAUSE(("Heap %s firstNearBlock is NULL.",heapName));
- #endif
- return 0;
- }
- #ifdef SAFE_HEAP
- __asm
- {
- cmp localHeapState,0
- jne error1
- }
- #endif
- __asm
- {
- xor eax,eax
- mov edi,10000
- mov ecx,heapBlockSize
- mov ebx,localFirst
- mov edx,ebx //edx = is place holder for first node
- }
-
- BytesLoop:
- __asm
- {
- mov ebx,[ebx].next
- add eax,[ebx].blockSize
- add eax,ecx
- dec edi
- je short error1
- cmp ebx,edx
- jne short BytesLoop
- jmp short DoneTC
- }
-
- error1:
- __asm
- {
- xor eax,eax
- }
-
- DoneTC:
- __asm
- {
- mov result,eax
- }
- return(result);
- }
- //---------------------------------------------------------------------------
- unsigned long UserHeap::coreLeft (void)
- {
- unsigned long result = 0;
- if (gosHeap)
- return result;
- #ifdef SAFE_HEAP
- long localHeapState = heapState;
- #endif
- HeapBlockPtr localFirst = firstNearBlock;
- long heapBlockSize = -(long)allocatedBlockSize;
-
- #ifdef USE_BEST_FIT
- __asm
- {
- xor eax,eax
- }
-
- #ifdef SAFE_HEAP
- __asm
- {
- cmp localHeapState,0
- jne short DoneCL
- }
-
- #endif
- __asm
- {
- mov ebx,localFirst
- or ebx,ebx
- je short DoneCL
- mov ebx,[ebx].previous
- mov eax,[ebx].blockSize // size of last block in list
- add eax,heapBlockSize
- }
-
- DoneCL:
- __asm
- {
- mov result, eax
- }
-
- return(result);
-
- #else // !DEFINED BEST_FIT
- __asm
- {
- xor eax,eax
- }
-
- #ifdef SAFE_HEAP
- __asm
- {
- cmp localHeapState,0
- jne short DoneCL
- }
-
- #endif
- __asm
- {
- mov ebx,localFirst
- or ebx,ebx
- je short DoneCL
- mov ecx,10000
- }
-
- TopLoop:
- __asm
- {
- cmp [ebx].blockSize,eax
- jb Next
- mov eax,[ebx].blockSize
- }
-
- Next:
- __asm
- {
- dec ecx
- jle DoneCL
- mov ebx,[ebx].next
- cmp ebx,localFirst
- jne TopLoop
- add eax,heapBlockSize
- }
-
- DoneCL:
- __asm
- {
- mov result, eax
- }
-
- return(result);
-
- #endif
- }
- //---------------------------------------------------------------------------
- void * UserHeap::Malloc (unsigned long memSize)
- {
- void * result = NULL;
- if (gosHeap)
- {
- gos_PushCurrentHeap( gosHeap );
- result = gos_Malloc(memSize);
- gos_PopCurrentHeap();
- return result;
- }
- HeapBlockPtr blockOffs = NULL;
- HeapBlockPtr localFirst = firstNearBlock;
- long heapBlockSize = sizeof(HeapBlock);
- bool mf = mallocFatals;
-
- #ifdef _DEBUG
- heapBlockSize += 4;
- #endif
-
- long errorResult = 0;
- __asm
- {
- mov eax,memSize
- or eax,eax
- je Alloc_zero
- }
-
- #ifdef _DEBUG
- __asm
- {
- add eax,4 // extra space for who made me pointer
- }
-
- #endif
- __asm
- {
- add eax,11 //force minimum allocation 8+3
- and al, 0xfc //NOT 3 //force dword alignment
- cmp eax,heapBlockSize
- jae short SizeDone
- mov eax,heapBlockSize
- }
-
- SizeDone:
- __asm
- {
- cmp eax,memSize
- jb Alloc_Overflow
- //search free list for first available block
- mov ebx,localFirst
- or ebx,ebx
- je Zero_Free
- mov edx,ebx //marker to beginning of list
- }
-
- SearchLoop:
- __asm
- {
- mov ecx,[ebx].blockSize
- sub ecx,eax //unsigned math
- jnb short FoundBlock
- mov ebx,[ebx].next
- cmp edx,ebx
- jne SearchLoop //have we come back to first node?
- //else block was not found
-
- add ecx,eax // ECX = biggest block
- mov edx,[memSize] // EDX = bytes asked for
- mov eax,OUT_OF_MEMORY // EAX = Out of memory error number
- jmp Alloc_error
- }
-
- FoundBlock:
- // ebx = offset of found block
- // ecx = size of leftover block
- // eax = size of block to allocate
- __asm
- {
- mov blockOffs,ebx
- cmp ecx,heapBlockSize //any memory left to reallocate?
- jae short UnlinkNormal
- or [ebx].blockSize,1 //mark allocated
- }
- //This code is the unlink macro.
- __asm
- {
- cmp [ebx].next,ebx
- jne short ULine1
-
- //else list is now empty
-
- mov localFirst,0
- jmp short ULine3
- }
-
- ULine1:
- __asm
- {
- mov edx,localFirst
- cmp ebx,edx
- jne short ULine2 //unlinking first element?
- mov eax,[ebx].next
- mov localFirst,eax
- }
-
- ULine2:
- __asm
- {
- mov edi,[ebx].next //edi = ebx.next
- mov ebx,[ebx].previous
- mov [edi].previous,ebx //ebx.next.prev = ebx.prev
- mov [ebx].next,edi //ebx.prev.next = ebx.next
- }
-
- ULine3: //End of Unlink code
- __asm
- {
- mov eax,blockOffs
- jmp short Alloc_Done
- }
-
- UnlinkNormal:
- __asm
- {
- mov edi,ebx
- add edi,[ebx].blockSize //edi -> lower block
- add [edi].upperBlock,ecx //update lower pointer to the new block
- mov [ebx].blockSize,ecx
- mov edi,ebx
- add edi,ecx //edi -> newblock
- or al,1 //mark new block as allocated
- mov [edi].blockSize,eax
- mov [edi].upperBlock,ebx
- }
-
- //-------------------------------------------------------------------------------------
- //SORT Routine
-
- #ifdef USE_BEST_FIT
- __asm
- {
- pushad
- }
-
- //-------------------------------------
- //see if we have to do any work at all
- HeapBlockPtr localFirstSort = firstNearBlock;
- __asm
- {
- mov edx,localFirstSort
- mov ecx,[ebx].blockSize
- mov edi,[ebx].next
- cmp edi,[ebx].previous
- jne short __Line1 //either 1 or two members in list
- cmp edi,ebx
- je __Done //only one member in list
- //else there are only two
- mov localFirstSort,ebx //assume we are the smaller block
- cmp ecx,[edi].blockSize
- jbe __Done //we were right
- mov localFirstSort,edi //else other guy is smaller
- jmp __Done
- }
- __Line1: // else see if we are not in the correct order
- __asm
- {
- cmp ecx,[edi].blockSize
- jbe short __Line2
- //else see if next guy in line is the localFirst
- cmp edi,edx //did we just compare with Beginning of list?
- jne short __Line3 //no
- }
-
- __Line2:
- __asm
- {
- mov edi,[ebx].previous
- cmp ecx,[edi].blockSize
- jae short __Done
- //else we are less than guy to our left
- cmp ebx,edx //are we the first block in list?
- je short __Done
- __Line3: //else we must unlink our block, saving a pointer to lower neighbor
- push edi
- push ebx
- //Unlink Routine inline here
-
- cmp [ebx].next,ebx
- jne short _ULine1
-
- //else list is now empty
-
- mov localFirstSort,0
- jmp short _ULine3
- }
-
- _ULine1:
- __asm
- {
- mov edx,localFirstSort
- cmp ebx,edx
- jne short _ULine2 //unlinking first element?
- mov eax,[ebx].next
- mov localFirstSort,eax
- }
-
- _ULine2:
- __asm
- {
- mov edi,[ebx].next //edi = ebx.next
- mov ebx,[ebx].previous
- mov [edi].previous,ebx //ebx.next.prev = ebx.prev
- mov [ebx].next,edi //ebx.prev.next = ebx.next
- }
-
- _ULine3:
- __asm
- {
- // ecx = unchanged, the size of our block
- pop ebx // ebx -> our block we have just unlinked.
- pop edi // edi -> block to start our search on.
- mov edx,localFirstSort
- cmp [ebx].previous,edi
- je short __Line4 // search previous nodes
- }
- // stop when guy to the right is higher than us, or is the FirstMemBlock
- __Loop1:
- __asm
- {
- mov esi,edi
- mov edi,[edi].next
- cmp edi,edx //have we wrapped around?
- je short __FoundPlace
- cmp [edi].blockSize,ecx
- jae short __FoundPlace
- jmp __Loop1
- }
- __Line4:
- //stop when guy to the left is lower than us, or we stopped on the FirstMemBlock
- __Loop2:
- __asm
- {
- mov esi,edi
- mov edi,[edi].previous
- cmp esi,edx //have we wrapped around?
- je short __Line5
- cmp [edi].blockSize,ecx
- ja __Loop2
- }
-
- __Line5:
- __asm
- {
- xchg esi,edi
- }
-
- __FoundPlace: // esi-> first block, edi->second block, ebx -> us
- //ebx = offset of new block
- __asm
- {
- mov [ebx].previous,esi
- mov [ebx].next,edi
- mov [esi].next,ebx
- mov [edi].previous,ebx
- mov edi,edx
- cmp ecx,[edi].blockSize //see if we are now smallest
- jae short __Done
- mov localFirstSort,ebx //we are smallest
- }
-
- __Done:
- firstNearBlock = localFirstSort;
- //-------------------------------------------------------------------------------------
- //SORT Routine
-
- __asm
- {
- POPAD
- }
-
- #endif
- __asm
- {
- mov eax,edi
- jmp short Alloc_Done
- }
-
- //-----------------------------------------error handling
- Alloc_zero:
- __asm
- {
- mov eax,ALLOC_ZERO
- jmp short Alloc_error
- }
-
- Zero_Free:
- __asm
- {
- mov eax,NULL_FREE_LIST
- jmp short Alloc_error
- }
-
- Alloc_Overflow:
- __asm
- {
- mov eax,ALLOC_OVERFLOW
- }
-
- Alloc_error:
- __asm
- {
- mov errorResult,eax
- cmp mf,0
- // cmp [this].mallocFatals,0
- #ifdef CHECK_HEAP
- je noFatal
- #else
- jmp noFatal
- #endif
- }
- memCoreLeft = totalCoreLeft();
- memTotalLeft = coreLeft();
-
- walkHeap(TRUE,FALSE);
- if (memSize)
- STOP(("Heap %s is Out Of RAM. HeapSize %d, CoreLeft %d, TotalLeft %d, SizeTried %d",heapName,heapSize,memCoreLeft,memTotalLeft,memSize));
- else
- STOP(("Heap %s Tried to Malloc Zero Bytes!"));
-
- noFatal:
- __asm
- {
- mov eax,-8
- #ifdef _DEBUG
- mov eax,-12 //Make that extra room for who made me
- #endif
- }
-
- Alloc_Done:
- __asm
- {
- add eax,8 //skip over header
- #ifdef _DEBUG
- add eax,4 //Skip over extra for debugging
- #endif
- }
-
- #ifdef _DEBUG
- __asm
- {
- //if we allocated memory, store pointer to caller
- or eax,eax
- je NoAllocation
- mov ebx,ebp
- mov edx,dword ptr [ebx+4] // get caller
- mov [eax-4],edx //Store caller in HeapBlock
- }
-
- NoAllocation:
- #endif
- #ifdef HEAP_CHECK
- __asm
- {
- push eax
- }
-
- WalkHeap();
-
- __asm
- {
- pop eax
- }
-
- #endif
- __asm
- {
- mov result,eax
- }
- firstNearBlock = localFirst;
-
- #ifdef _DEBUG
- if (logMallocs)
- {
- recordCount++;
- gosASSERT (recordCount<NUMMEMRECORDS);
-
- recordArray[recordCount].ptr = result;
- recordArray[recordCount].size = memSize;
- CONTEXT ourContext;
- STACKFRAME sf;
- GetCurrentContext(&ourContext);
- InitStackWalk(&sf,&ourContext);
-
- for (long i=0;i<12;i++)
- {
- recordArray[recordCount].stack[i] = WalkStack(&sf);
- }
- }
- #endif
-
- return(result);
- }
- //---------------------------------------------------------------------------
- long UserHeap::Free (void *memBlock)
- {
- if (gosHeap)
- {
- gos_PushCurrentHeap( gosHeap );
- gos_Free(memBlock);
- gos_PopCurrentHeap();
- return 0;
- }
- HeapBlockPtr blockOffs = (HeapBlockPtr)memBlock;
- long result = 0;
- HeapBlockPtr sortBlock = NULL;
- //------------------------------------------
- // If freeing a NULL, we do nothing
- //------------------------------------------
- if (memBlock == NULL)
- return(NO_ERR);
- //-------------------------------------------------------------------
- // this is bad. However, for release, just let it go on the really
- // remote chance it happens.
- if ((memBlock < getHeapPtr()) || (memBlock >= (getHeapPtr() + totalSize)))
- {
- #ifdef _DEBUG
- PAUSE(("Tried to delete a bad pointer."));
- #endif
- return (NO_ERR);
- }
- __asm
- {
- cmp blockOffs,0
- je Dealloc_Done
- sub blockOffs,8 //compensate for heading
- #ifdef _DEBUG
- sub blockOffs,4 //extra return pointer
- #endif
-
- }
- //merge this block with lower one if possible
- long mergeResult = mergeWithLower(blockOffs);
- __asm
- {
- mov eax,mergeResult
- #ifdef SAFE_HEAP
- or eax,eax //return 0 on error
- je Dealloc_Done
- #endif
- //if block above is "free", add our size to it. no relinking is needed
- mov ebx,[blockOffs]
- mov edi,[ebx].upperBlock
- or edi,edi
- je short Relink_needed //no block above this one
- test [edi].blockSize,1
- jne short Relink_needed //block above is allocated
- //else just add size
- mov eax,[ebx].blockSize
- and eax,0xfffffffe //NOT 1
- add [edi].blockSize,eax //add to size of above block
- //inform new lower neighbor about the change
- mov ebx,edi
- add ebx,[edi].blockSize
- mov [ebx].upperBlock,edi
- #ifdef USE_BEST_FIT
- mov ebx,edi
- }
- //-------------------------------------------------------------------------------------
- //SORT Routine
- __asm
- {
- pushad
- }
-
- //-------------------------------------
- //see if we have to do any work at all
- HeapBlockPtr localFirstSort = firstNearBlock;
- __asm
- {
- mov edx,localFirstSort
- mov ecx,[ebx].blockSize
- mov edi,[ebx].next
- cmp edi,[ebx].previous
- jne short __Line1 //either 1 or two members in list
- cmp edi,ebx
- je __Done //only one member in list
- //else there are only two
- mov localFirstSort,ebx //assume we are the smaller block
- cmp ecx,[edi].blockSize
- jbe __Done //we were right
- mov localFirstSort,edi //else other guy is smaller
- jmp __Done
- }
- __Line1: // else see if we are not in the correct order
- __asm
- {
- cmp ecx,[edi].blockSize
- jbe short __Line2
- //else see if next guy in line is the localFirst
- cmp edi,edx //did we just compare with Beginning of list?
- jne short __Line3 //no
- }
-
- __Line2:
- __asm
- {
- mov edi,[ebx].previous
- cmp ecx,[edi].blockSize
- jae short __Done
- //else we are less than guy to our left
- cmp ebx,edx //are we the first block in list?
- je short __Done
- __Line3: //else we must unlink our block, saving a pointer to lower neighbor
- push edi
- push ebx
- //Unlink Routine inline here
-
- cmp [ebx].next,ebx
- jne short _ULine1
-
- //else list is now empty
-
- mov localFirstSort,0
- jmp short _ULine3
- }
-
- _ULine1:
- __asm
- {
- mov edx,localFirstSort
- cmp ebx,edx
- jne short _ULine2 //unlinking first element?
- mov eax,[ebx].next
- mov localFirstSort,eax
- }
-
- _ULine2:
- __asm
- {
- mov edi,[ebx].next //edi = ebx.next
- mov ebx,[ebx].previous
- mov [edi].previous,ebx //ebx.next.prev = ebx.prev
- mov [ebx].next,edi //ebx.prev.next = ebx.next
- }
-
- _ULine3:
- __asm
- {
- // ecx = unchanged, the size of our block
- pop ebx // ebx -> our block we have just unlinked.
- pop edi // edi -> block to start our search on.
- mov edx,localFirstSort
- cmp [ebx].previous,edi
- je short __Line4 // search previous nodes
- }
- // stop when guy to the right is higher than us, or is the FirstMemBlock
- __Loop1:
- __asm
- {
- mov esi,edi
- mov edi,[edi].next
- cmp edi,edx //have we wrapped around?
- je short __FoundPlace
- cmp [edi].blockSize,ecx
- jae short __FoundPlace
- jmp __Loop1
- }
- __Line4:
- //stop when guy to the left is lower than us, or we stopped on the FirstMemBlock
- __Loop2:
- __asm
- {
- mov esi,edi
- mov edi,[edi].previous
- cmp esi,edx //have we wrapped around?
- je short __Line5
- cmp [edi].blockSize,ecx
- ja __Loop2
- }
-
- __Line5:
- __asm
- {
- xchg esi,edi
- }
-
- __FoundPlace: // esi-> first block, edi->second block, ebx -> us
- //ebx = offset of new block
- __asm
- {
- mov [ebx].previous,esi
- mov [ebx].next,edi
- mov [esi].next,ebx
- mov [edi].previous,ebx
- mov edi,edx
- cmp ecx,[edi].blockSize //see if we are now smallest
- jae short __Done
- mov localFirstSort,ebx //we are smallest
- }
-
- __Done:
- firstNearBlock = localFirstSort;
- //-------------------------------------------------------------------------------------
- //SORT Routine
-
- __asm
- {
- POPAD
- }
-
- __asm
- {
- #endif
- jmp short Dealloc_Done
- }
- Relink_needed:
- __asm
- {
- mov ebx,[blockOffs]
- and [ebx].blockSize,0xfffffffe //NOT 1
- mov sortBlock,ebx
- }
- relink(sortBlock);
- Dealloc_Done:
- #ifdef HEAP_CHECK
- walkHeap(FALSE,FALSE," Free Heap Ck ");
- #endif
- __asm
- {
- mov result,eax
- }
- #ifdef _DEBUG
- if (logMallocs)
- {
- long count = 0;
- while (count<NUMMEMRECORDS && recordArray[count].ptr != memBlock)
- count++;
- //This may be OK? Not logging when allocated!
- //gosASSERT (count < NUMMEMRECORDS);
-
- recordArray[count].ptr = NULL;
- recordArray[count].size = 0;
-
- for (int i=0; i<12; i++)
- recordArray[count].stack[i] = 0;
- }
- #endif
-
- return(result);
- }
- //---------------------------------------------------------------------------
- void * UserHeap::calloc (unsigned long memSize)
- {
- void * result = malloc(memSize);
- memset(result,0,memSize);
- return result;
- }
-
- //---------------------------------------------------------------------------
- void UserHeap::walkHeap (bool printIt, bool skipAllocated)
- {
- if (gosHeap)
- {
- gos_WalkMemoryHeap(gosHeap);
- return;
- }
- HeapBlockPtr walker = heapStart;
- bool valid, allocated;
- unsigned long bSize;
- if (!walker || (heapState != NO_ERR))
- return;
- #ifdef _DEBUG
- File logFile;
- logFile.create("walkdump.log");
- #endif
-
- while (walker->blockSize != 1)
- {
- //--------------------
- // check for validity
- //--------------------
- valid = TRUE;
- if (walker->upperBlock)
- {
- bSize = (walker->upperBlock->blockSize & ~1);
- bSize += (unsigned long)walker->upperBlock;
- valid = (bSize == (unsigned long)walker);
- }
- if (valid)
- {
- bSize = (unsigned long)walker + (walker->blockSize & ~1);
- valid = (HeapBlockPtr(bSize)->upperBlock == walker);
- }
- else
- {
- //--------------------------
- // Failed upper block check
- //--------------------------
- heapState = HEAP_CORRUPTED;
- STOP(("Heap %s Upper Block Check Failed",heapName));
- return;
- }
- if (valid && !(walker->blockSize & 1)) // if free block
- {
- valid = ((walker->previous->next == walker) &&
- (walker->next->previous == walker));
- }
- else if (!valid)
- {
- //--------------------------
- // Failed lower block check
- //--------------------------
- heapState = HEAP_CORRUPTED;
- STOP(("Heap %s Lower Block Check Failed",heapName));
- return;
- }
- if (!valid)
- {
- //--------------------------
- // Failed linked list check
- //--------------------------
- heapState = HEAP_CORRUPTED;
- STOP(("Heap %s LinkedList Check Failed",heapName));
- return;
- }
- allocated = walker->blockSize & 1;
- if ((printIt && !allocated) || (printIt && !skipAllocated))
- {
- char errMessage[256];
- #ifdef _DEBUG
- if (allocated)
- {
- sprintf(errMessage, "Allocated block at DS:%08X, size = %u, owner at CS:%08X\n",
- walker,(walker->blockSize & ~1),walker->previous);
-
- //--------------------------------------------------------------------------------------------
- // A size and/or address check can be put here to inspect the block and determine other info
- long magicNumber = 0x6726FB;
- if ((walker->previous) == (void*)magicNumber)
- printf("magicNumber");
- //--------------------------------------------------------------------------------------------
- }
- else
- {
- sprintf(errMessage, "Free block at DS:%08X, size = %u \n", walker,(walker->blockSize & ~1));
- }
- #ifndef _CONSOLE
- logFile.writeLine(errMessage);
- #else
- printf(errMessage);
- #endif
- #else
- sprintf(errMessage, "%s block at DS:%08X, size = %u \n",
- (allocated)?"Allocated":"Free",walker,(walker->blockSize & ~1));
- #ifndef _CONSOLE
- OutputDebugString(errMessage);
- #else
- printf(errMessage);
- #endif
- #endif
- }
- walker = HeapBlockPtr((unsigned long)walker + (walker->blockSize & ~1));
- }
- }
- //---------------------------------------------------------------------------
- long UserHeap::getLastError (void)
- {
- return heapState;
- }
- //---------------------------------------------------------------------------
- void UserHeap::relink (HeapBlockPtr newBlock)
- {
- HeapBlockPtr localFirst = firstNearBlock;
-
- //empty list?
- __asm
- {
- mov ebx, newBlock
- cmp localFirst,0
- jne short Line1
-
- //else this is the only block in the list
-
- mov localFirst,ebx
- mov [ebx].previous,ebx
- mov [ebx].next,ebx
- jmp short Line2
- }
-
- Line1:
- __asm
- {
- //ebx = address of new block
- mov edi,localFirst
- #ifdef USE_BEST_FIT
- mov edx,edi
- mov ecx,[ebx].blockSize
- cmp ecx,[edi].blockSize
- jae short Line3
- mov localFirst,ebx
- jmp short Line4
- }
-
- Line3:
- __asm
- {
- mov edi,[edi].next
- cmp edi,edx
- je short Line4
- cmp ecx,[edi].blockSize
- ja Line3
- }
-
- Line4:
- __asm
- {
- mov edi,[edi].previous
- #endif
- mov eax,[edi].next
- mov [ebx].next,eax
- mov [ebx].previous,edi
- mov [edi].next,ebx
- mov edi,[ebx].next
- mov [edi].previous,ebx
- }
-
- Line2:
- firstNearBlock = localFirst;
- }
- //---------------------------------------------------------------------------
- void UserHeap::unlink (HeapBlockPtr oldBlock)
- {
- HeapBlockPtr localFirst = firstNearBlock;
-
- __asm
- {
- mov ebx,oldBlock
- cmp [ebx].next,ebx
- jne short ULine1
-
- //else list is now empty
-
- mov localFirst,0
- jmp short ULine3
- }
-
- ULine1:
- __asm
- {
- mov edx,localFirst
- cmp ebx,edx
- jne short ULine2 //unlinking first element?
- mov eax,[ebx].next
- mov localFirst,eax
- }
-
- ULine2:
- __asm
- {
- mov edi,[ebx].next //edi = ebx.next
- mov ebx,[ebx].previous
- mov [edi].previous,ebx //ebx.next.prev = ebx.prev
- mov [ebx].next,edi //ebx.prev.next = ebx.next
- }
-
- ULine3:
- firstNearBlock = localFirst;
- }
- //---------------------------------------------------------------------------
- bool UserHeap::mergeWithLower (HeapBlockPtr block)
- {
- HeapBlockPtr localFirst = firstNearBlock;
- bool result = FALSE;
-
- __asm
- {
- mov edi,block
- mov ebx,[edi].blockSize
- }
-
- #ifdef SAFE_HEAP
- __asm
- {
- test ebx,1
- je short Fatal1 //else failed alloc check
- cmp [edi+ebx-1].upperBlock,edi
- jne short Fatal1 //else failed lower check
- mov esi,[edi].upperBlock
- or esi,esi
- je short check_ok
- add esi,[esi].blockSize
- and esi,0xfffffffe //NOT 1
- cmp esi,edi
- je short check_ok
- }
-
- Fatal1:
- walkHeap(FALSE,FALSE);
- //Fatal(HEAP_CORRUPTED);
- __asm
- {
- xor eax,eax //In theory, this will never execute since the Fatal Exits
- jmp DoneML //Maybe if Fatal is not operating?
- }
-
- check_ok:
- #endif
- __asm
- {
- and ebx,0xfffffffe //NOT 1 //make size be acurate
- mov esi,ebx
- add esi,edi //esi = offset of lower neighbor
- mov ecx,[esi].blockSize
- test ecx,1
- jne short NoMerge //lower block is allocated
- add ebx,ecx //ebx = new size of block
- mov [edi].blockSize,ebx
- or [edi].blockSize,1 //dealloc() expects allocated block
- mov eax,edi
- add ebx,eax //ebx -> new lower neigbor
- mov [ebx].upperBlock,edi //inform new neighbor about the change
- mov ebx,esi //ebx = offset of old lower neighbor
- }
- //This is the UNLINK routine directly.
- __asm
- {
- cmp [ebx].next,ebx
- jne short ULine1
-
- //else list is now empty
-
- mov localFirst,0
- jmp short ULine3
- }
-
- ULine1:
- __asm
- {
- mov edx,localFirst
- cmp ebx,edx
- jne short ULine2 //unlinking first element?
- mov eax,[ebx].next
- mov localFirst,eax
- }
-
- ULine2:
- __asm
- {
- mov edi,[ebx].next //edi = bx.next
- mov ebx,[ebx].previous
- mov [edi].previous,ebx //ebx.next.prev = ebx.prev
- mov [ebx].next,edi //ebx.prev.next = bx.next
- }
-
- ULine3:
- NoMerge:
- __asm
- {
- mov eax,1 //Return TRUE
- }
-
- #ifdef SAFE_HEAP
- DoneML:
- #endif
- __asm
- {
- mov result,al //Move eax into result
- }
-
- firstNearBlock = localFirst;
- return(result);
- }
-
- //---------------------------------------------------------------------------
- void HeapList::addHeap (HeapManagerPtr newHeap)
- {
- for (long i=0;i<MAX_HEAPS;i++)
- {
- if (heapRecords[i].thisHeap == NULL)
- {
- heapRecords[i].thisHeap = newHeap;
- heapRecords[i].heapSize = newHeap->tSize();
- return;
- }
- }
- }
- //---------------------------------------------------------------------------
- void HeapList::removeHeap (HeapManagerPtr oldHeap)
- {
- for (long i=0;i<MAX_HEAPS;i++)
- {
- if (heapRecords[i].thisHeap == oldHeap)
- {
- heapRecords[i].thisHeap = NULL;
- heapRecords[i].heapSize = 0;
- return;
- }
- }
- }
- void HeapList::initializeStatistics()
- {
- if (heapInstrumented == 0)
- {
- StatisticFormat( "" );
- StatisticFormat( "MechCommander 2 Heaps" );
- StatisticFormat( "======================" );
- StatisticFormat( "" );
- AddStatistic("Total Memory","bytes",gos_DWORD, &(totalSize), Stat_AutoReset | Stat_Total);
- AddStatistic("Total Memory Core Left","bytes",gos_DWORD, &(totalCoreLeft), Stat_AutoReset | Stat_Total);
- AddStatistic("Total Memory Left","bytes",gos_DWORD, &(totalLeft), Stat_AutoReset | Stat_Total);
- StatisticFormat( "" );
- StatisticFormat( "" );
-
- for (long i=0;i<50;i++)
- {
- char heapString[255];
- sprintf(heapString,"Heap %d - HeapSize",i);
- AddStatistic(heapString,"bytes",gos_DWORD, &(heapRecords[i].heapSize), Stat_AutoReset | Stat_Total);
- sprintf(heapString,"Heap %d - TotalLeft",i);
- AddStatistic(heapString,"bytes",gos_DWORD, &(heapRecords[i].totalCoreLeft), Stat_AutoReset | Stat_Total);
- sprintf(heapString,"Heap %d - CoreLeft",i);
- AddStatistic(heapString,"bytes",gos_DWORD, &(heapRecords[i].coreLeft), Stat_AutoReset | Stat_Total);
- StatisticFormat( "" );
- }
- heapInstrumented = true;
- }
- }
-
- //---------------------------------------------------------------------------
- void HeapList::update (void)
- {
- totalSize = totalCoreLeft = totalLeft = 0;
- for (long i=0;i<50;i++)
- {
- if (heapRecords[i].thisHeap && (heapRecords[i].thisHeap->heapType() == USER_HEAP))
- {
- heapRecords[i].heapSize = ((UserHeapPtr)heapRecords[i].thisHeap)->tSize();
- totalSize += heapRecords[i].heapSize;
- heapRecords[i].coreLeft = ((UserHeapPtr)heapRecords[i].thisHeap)->coreLeft();
- totalLeft += heapRecords[i].coreLeft;
- heapRecords[i].totalCoreLeft = ((UserHeapPtr)heapRecords[i].thisHeap)->totalCoreLeft();
- totalCoreLeft += heapRecords[i].totalCoreLeft;
- }
- else if (heapRecords[i].thisHeap)
- {
- heapRecords[i].heapSize = heapRecords[i].thisHeap->tSize();
- totalSize += heapRecords[i].heapSize;
- heapRecords[i].coreLeft = 0;
- heapRecords[i].totalCoreLeft = 0;
- }
- }
- }
- //---------------------------------------------------------------------------
- unsigned long textToLong (char *num)
- {
- long result = 0;
- char *hexOffset = num;
-
- hexOffset += 2;
- long numDigits = strlen(hexOffset)-1;
- long power = 0;
-
- for (long count = numDigits;count >= 0;count--,power++)
- {
- unsigned char currentDigit = toupper(hexOffset[count]);
-
- if (currentDigit >= 'A' && currentDigit <= 'F')
- {
- result += (currentDigit - 'A' + 10)<<(4*power);
- }
- else if (currentDigit >= '0' && currentDigit <= '9')
- {
- result += (currentDigit - '0')<<(4*power);
- }
- else
- {
- //---------------------------------------------------------
- // There is a digit in here I don't understand. Return 0.
- result = 0;
- break;
- }
- }
- return(result);
- }
- //-----------------------------------------------------------
- long longToText (char *result, long num, unsigned long bufLen)
- {
- char temp[250];
- sprintf(temp,"%08X",num);
- unsigned long numLength = strlen(temp);
- if (numLength >= bufLen)
- return(0);
- strncpy(result,temp,numLength);
- result[numLength] = '\0';
-
- return(NO_ERR);
- }
- //--------------------------------------------------------------------------
- long getStringFromMap (File &mapFile, unsigned long addr, char *result)
- {
- //----------------------------------------
- // Convert function address to raw offset
- #ifdef TERRAINEDIT
- unsigned long offsetAdd = 0x00601000;
- #else
- unsigned long offsetAdd = 0x00601000;
- #endif
-
- unsigned long function = addr;
- function -= offsetAdd;
-
- char actualAddr[10];
- longToText(actualAddr,function,9);
-
- //------------------------------------
- // Find the first code entry address.
- // This is the first line encountered with " Address" as the first nine characters.
- char mapFileLine[512];
-
- mapFile.seek(0);
- mapFile.readLine((MemoryPtr)mapFileLine,511);
- while (strstr(mapFileLine," Address") == NULL)
- {
- mapFile.readLine((MemoryPtr)mapFileLine,511);
- }
-
- mapFile.readLine((MemoryPtr)mapFileLine,511);
- mapFile.readLine((MemoryPtr)mapFileLine,511);
- //-------------------------------------------------------------
- // We've found the first code entry. Now, scan until
- // the current address is greater than the address asked for.
- // The previous function name is the function in question.
- char *currentAddress = &(mapFileLine[6]);
- char previousAddress[511];
- strncpy(previousAddress,&(mapFileLine[6]),510);
-
- while (strstr(mapFileLine,"0001:") != NULL)
- {
- if (strnicmp(currentAddress,actualAddr,8) > 0)
- {
- //-----------------------------------------------
- // We've found it, print the previous address.
- strncpy(result,previousAddress,510);
- return(strlen(result));
- }
-
- strncpy(previousAddress,&(mapFileLine[6]),510);
- mapFile.readLine((MemoryPtr)mapFileLine,511);
- }
-
- return(0);
- }
-
- //---------------------------------------------------------------------------
- void HeapList::dumpLog (void)
- {
- //----------------------------------------------
- // This function dumps information on each heap
- // to a log file.
- File logFile;
- logFile.create("heap.dump.log");
-
- File mapFile;
-
- long mapResult = 0;
- #ifdef _DEBUG
- #ifdef TERRAINEDIT
- mapResult = mapFile.open("teditor.map");
- #else
- mapResult = mapFile.open("mechcmdrdbg.map");
- #endif
- #endif
- HeapManagerPtr currentHeap = NULL;
- unsigned long heapNumber = 1;
- unsigned long mapStringSize = 0;
- char msg[1024];
- char mapInfo[513];
- unsigned long totalCommit = 0;
- unsigned long totalFree = 0;
-
- for (long i=0;i<MAX_HEAPS;i++)
- {
- currentHeap = heapRecords[i].thisHeap;
-
- if (currentHeap)
- {
- sprintf(msg,"ListNo: %d Heap: %d Type: %d Made by: %08X",i,heapNumber,currentHeap->heapType(),currentHeap->owner());
- logFile.writeLine(msg);
- if (mapResult == NO_ERR)
- {
- mapStringSize = getStringFromMap(mapFile,currentHeap->owner(),mapInfo);
- if (mapStringSize)
- {
- sprintf(msg,"Made in Function : %s",mapInfo);
- logFile.writeLine(msg);
- }
- }
-
- sprintf(msg,"HeapSize: %d HeapStart: %08X",currentHeap->tSize(),currentHeap->getHeapPtr());
- logFile.writeLine(msg);
- totalCommit += currentHeap->tSize();
-
- if (currentHeap->heapType() == 1)
- {
- UserHeapPtr userHeap = (UserHeapPtr)currentHeap;
- sprintf(msg,"TotalCoreLeft: %d CoreLeft: %d",userHeap->totalCoreLeft(),userHeap->coreLeft());
- logFile.writeLine(msg);
-
- sprintf(msg,"Frag Level: %f PercentFree: %f",(float(userHeap->coreLeft())/float(userHeap->totalCoreLeft())),1.0 - (float(currentHeap->tSize()-userHeap->coreLeft())/float(currentHeap->tSize())) );
- logFile.writeLine(msg);
-
- totalFree += userHeap->coreLeft();
- }
-
- currentHeap = currentHeap->nxt;
- heapNumber++;
- }
- else
- {
- sprintf(msg,"ListNo: %d is Freed",i);
- logFile.writeLine(msg);
- }
-
- sprintf(msg,"---------------------------");
- logFile.writeLine(msg);
- }
-
- sprintf(msg,"Total Committed Memory: %d Total Free in Commit: %d",totalCommit,totalFree);
- logFile.writeLine(msg);
- sprintf(msg,"---------------------------");
- logFile.writeLine(msg);
-
- logFile.close();
- }
- bool UserHeap::pointerOnHeap (void *ptr)
- {
- if (IsBadReadPtr(getHeapPtr(),totalSize))
- return false;
- if ((ptr < getHeapPtr()) || (ptr >= (getHeapPtr() + totalSize)))
- return false;
- return true;
- }
- //---------------------------------------------------------------------------
- //
- // Edit Log
- //
- //---------------------------------------------------------------------------
|