795 lines
17 KiB
C
Executable File
795 lines
17 KiB
C
Executable File
/*****************************************************************************
|
|
*
|
|
* This program is free software ; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* $Id: mem_win32.c 430 2005-12-28 14:50:08Z picard $
|
|
*
|
|
* The Core Pocket Media Player
|
|
* Copyright (c) 2004-2005 Gabor Kovacs
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "../common.h"
|
|
|
|
#if defined(TARGET_WIN32) || defined(TARGET_WINCE)
|
|
|
|
//#define FIND 0xCF9390
|
|
//#define SAFEGUARD 32
|
|
|
|
#define BLOCKGROUP 8
|
|
|
|
#ifndef STRICT
|
|
#define STRICT
|
|
#endif
|
|
#include <windows.h>
|
|
|
|
#if defined(_MSC_VER) && !defined(TARGET_WINCE)
|
|
#include <crtdbg.h>
|
|
#endif
|
|
|
|
#if defined(TARGET_WINCE)
|
|
|
|
#define MAXPHY 16
|
|
|
|
#define CACHE_SYNC_INSTRUCTIONS 2
|
|
#define LOCKFLAG_WRITE 1
|
|
#define TBL_CACHE 0x08
|
|
#define TBL_BUFFER 0x04
|
|
|
|
typedef struct phymem
|
|
{
|
|
char* Virt;
|
|
uint32_t Phy;
|
|
uint32_t Length;
|
|
uint32_t RefCount;
|
|
phymemblock* Blocks;
|
|
int BlockCount;
|
|
|
|
} phymem;
|
|
|
|
static phymem PhyMem[MAXPHY] = { 0 };
|
|
|
|
static BOOL (WINAPI* FuncVirtualSetAttributes)(LPVOID lpvAddress, DWORD cbSize, DWORD dwNewFlags, DWORD dwMask, LPDWORD lpdwOldFlags) = NULL;
|
|
static BOOL (WINAPI* FuncFreePhysMem)(LPVOID) = NULL;
|
|
static BOOL (WINAPI* FuncLockPages)(LPVOID lpvAddress,DWORD cbSize,PDWORD pPFNs,int fOptions) = NULL;
|
|
static BOOL (WINAPI* FuncUnlockPages)(LPVOID lpvAddress,DWORD cbSize) = NULL;
|
|
static LPVOID (WINAPI* FuncAllocPhysMem)(DWORD cbSize, DWORD fdwProtect, DWORD dwAlignmentMask, DWORD dwFlags, PULONG pPhysicalAddress) = NULL;
|
|
static void (WINAPI* FuncCacheSync)(DWORD) = NULL;
|
|
static BOOL (WINAPI* FuncVirtualCopy)(LPVOID, LPVOID, DWORD, DWORD) = NULL;
|
|
|
|
static HMODULE CoreDLL = NULL;
|
|
|
|
#endif
|
|
|
|
typedef struct blockgroup
|
|
{
|
|
block Block;
|
|
int Mask;
|
|
int Unused; //align to 16bytes
|
|
|
|
} blockgroup;
|
|
|
|
static int PageSize = 4096;
|
|
static array BlockGroup = { NULL };
|
|
|
|
#ifndef NDEBUG
|
|
static int BlockAllocated = 0;
|
|
#endif
|
|
|
|
void* PhyMemAlloc(int Length,phymemblock* Blocks,int* BlockCount)
|
|
{
|
|
void* p = NULL;
|
|
|
|
#if defined(TARGET_WINCE)
|
|
if (*BlockCount>=1)
|
|
{
|
|
int n,Pos;
|
|
int Count = 0;
|
|
|
|
Length = (Length + PageSize-1) & ~(PageSize-1);
|
|
|
|
if (FuncAllocPhysMem && FuncFreePhysMem && FuncVirtualCopy)
|
|
{
|
|
// try allocate in one continous block
|
|
Blocks[0].Private = FuncAllocPhysMem(Length,PAGE_READWRITE,PageSize-1,0,&Blocks[0].Addr);
|
|
if (Blocks[0].Private)
|
|
{
|
|
Blocks[0].Length = Length;
|
|
Count = 1;
|
|
}
|
|
|
|
/* not worth it. allocphysmem is buggy anyway. won't be able to allocate per one pagesize
|
|
|
|
if (!Count && *BlockCount>1)
|
|
{
|
|
int Left = Length;
|
|
int BlockMax;
|
|
int BlockSize = (Left+PageSize-1) & ~(PageSize-1);
|
|
|
|
// allocate in separate blocks
|
|
|
|
while (Count < *BlockCount && BlockSize > 0)
|
|
{
|
|
Blocks[Count].Private = FuncAllocPhysMem(BlockSize,PAGE_READWRITE,PageSize-1,0,&Blocks[Count].Addr);
|
|
if (Blocks[Count].Private)
|
|
{
|
|
Blocks[Count].Length = BlockSize;
|
|
++Count;
|
|
Left -= BlockSize;
|
|
BlockMax = (Left+PageSize-1) & ~(PageSize-1);
|
|
if (BlockSize > BlockMax)
|
|
BlockSize = BlockMax;
|
|
}
|
|
else
|
|
if (BlockSize > PageSize*8)
|
|
BlockSize = (BlockSize/2+PageSize-1) & ~(PageSize-1);
|
|
else
|
|
BlockSize -= PageSize;
|
|
}
|
|
|
|
if (Left>0)
|
|
{
|
|
for (n=0;n<Count;++n)
|
|
FuncFreePhysMem(Blocks[n].Private);
|
|
Count = 0;
|
|
}
|
|
}
|
|
*/
|
|
|
|
if (Count)
|
|
{
|
|
p = VirtualAlloc(NULL,Length,MEM_RESERVE,PAGE_READWRITE);
|
|
|
|
if (p)
|
|
{
|
|
Pos = 0;
|
|
for (n=0;n<Count;++n)
|
|
{
|
|
if (!FuncVirtualCopy((char*)p+Pos,(LPVOID)(Blocks[n].Addr >> 8),Blocks[n].Length, PAGE_READWRITE | PAGE_PHYSICAL))
|
|
break;
|
|
Pos += Blocks[n].Length;
|
|
}
|
|
|
|
if (n!=Count)
|
|
{
|
|
VirtualFree(p,0,MEM_RELEASE);
|
|
p = NULL;
|
|
}
|
|
}
|
|
|
|
if (!p)
|
|
{
|
|
for (n=0;n<Count;++n)
|
|
FuncFreePhysMem(Blocks[n].Private);
|
|
Count = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!p && FuncLockPages && FuncUnlockPages)
|
|
{
|
|
do
|
|
{
|
|
p = VirtualAlloc(NULL,Length,MEM_COMMIT,PAGE_READWRITE);
|
|
}
|
|
while (!p && Length && NodeHibernate());
|
|
|
|
if (p)
|
|
{
|
|
int Pages = Length / PageSize;
|
|
DWORD* PFN = (DWORD*) alloca(sizeof(DWORD)*Pages);
|
|
|
|
if (FuncLockPages(p,Length,PFN,LOCKFLAG_WRITE))
|
|
{
|
|
DWORD Last = (DWORD)-1;
|
|
for (n=0;n<Pages;++n)
|
|
{
|
|
if (PFN[n] != Last)
|
|
{
|
|
if (Count >= *BlockCount)
|
|
{
|
|
Count = 0;
|
|
break;
|
|
}
|
|
|
|
Blocks[Count].Addr = PFN[n];
|
|
Blocks[Count].Length = PageSize;
|
|
Blocks[Count].Private = NULL;
|
|
++Count;
|
|
}
|
|
else
|
|
Blocks[Count-1].Length += PageSize;
|
|
|
|
Last = PFN[n] + PageSize;
|
|
}
|
|
|
|
if (!Count)
|
|
FuncUnlockPages(p,Length);
|
|
}
|
|
|
|
if (!Count)
|
|
{
|
|
VirtualFree(p,0,MEM_RELEASE);
|
|
p = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef ARM
|
|
if (p && FuncVirtualSetAttributes && (QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_XSCALE))
|
|
FuncVirtualSetAttributes(p,Length,TBL_CACHE|TBL_BUFFER,TBL_CACHE|TBL_BUFFER,NULL);
|
|
#endif
|
|
|
|
*BlockCount = Count;
|
|
}
|
|
#endif
|
|
|
|
return p;
|
|
}
|
|
|
|
void PhyMemFree(void* p,phymemblock* Blocks,int BlockCount)
|
|
{
|
|
#if defined(TARGET_WINCE)
|
|
if (p)
|
|
{
|
|
int n;
|
|
|
|
if (FuncLockPages && FuncUnlockPages)
|
|
{
|
|
int Size = 0;
|
|
for (n=0;n<BlockCount;++n)
|
|
{
|
|
if (Blocks[n].Private)
|
|
break;
|
|
Size += Blocks[n].Length;
|
|
}
|
|
if (Size)
|
|
FuncUnlockPages(p,Size);
|
|
}
|
|
|
|
VirtualFree(p,0,MEM_RELEASE);
|
|
|
|
if (FuncAllocPhysMem && FuncFreePhysMem && FuncVirtualCopy)
|
|
for (n=0;n<BlockCount;++n)
|
|
if (Blocks[n].Private)
|
|
FuncFreePhysMem(Blocks[n].Private);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if defined(TARGET_WINCE)
|
|
static void SafeVirtualFree(PVOID p,DWORD Size)
|
|
{
|
|
#ifdef ARM
|
|
// O2 Atom destroys video memory and LCD descriptors unless this code... (WM5)
|
|
if (FuncVirtualSetAttributes)
|
|
FuncVirtualSetAttributes(p,Size,0,0xFFFFF000,NULL);
|
|
#endif
|
|
VirtualFree(p,0,MEM_RELEASE);
|
|
}
|
|
#endif
|
|
|
|
void* PhyMemBeginEx(phymemblock* Blocks,int BlockCount,bool_t Cached)
|
|
{
|
|
#if defined(TARGET_WINCE)
|
|
if (FuncVirtualCopy && Blocks && BlockCount)
|
|
{
|
|
int n;
|
|
int Mode;
|
|
phymem* p;
|
|
for (p=PhyMem;p!=PhyMem+MAXPHY;++p)
|
|
if (p->BlockCount == BlockCount && p->Length == Blocks[0].Length && p->Phy == Blocks[0].Addr)
|
|
{
|
|
for (n=1;n<BlockCount;++n)
|
|
if (p->Blocks[n].Addr != Blocks[n].Addr || p->Blocks[n].Length != Blocks[n].Length)
|
|
break;
|
|
|
|
if (n==BlockCount)
|
|
{
|
|
++p->RefCount;
|
|
return p->Virt;
|
|
}
|
|
}
|
|
|
|
if (BlockCount==1)
|
|
return PhyMemBegin(Blocks[0].Addr,Blocks[0].Length,Cached);
|
|
|
|
for (Mode=0;Mode<2;++Mode)
|
|
for (p=PhyMem;p!=PhyMem+MAXPHY;++p)
|
|
{
|
|
if (Mode && !p->RefCount && p->Length)
|
|
{
|
|
free(p->Blocks);
|
|
SafeVirtualFree(p->Virt,p->Length);
|
|
memset(p,0,sizeof(phymem));
|
|
}
|
|
|
|
if (!p->Length)
|
|
{
|
|
p->Blocks = (phymemblock*) malloc(sizeof(phymemblock)*BlockCount);
|
|
if (p->Blocks)
|
|
{
|
|
int Size = 0;
|
|
for (n=0;n<BlockCount;++n)
|
|
Size += Blocks[n].Length;
|
|
|
|
p->BlockCount = BlockCount;
|
|
p->Virt = (char*) VirtualAlloc(0, Size, MEM_RESERVE, PAGE_NOACCESS);
|
|
if (p->Virt)
|
|
{
|
|
int Mode = PAGE_READWRITE | PAGE_PHYSICAL;
|
|
char* Virt = p->Virt;
|
|
|
|
if (!Cached)
|
|
Mode |= PAGE_NOCACHE;
|
|
|
|
for (n=0;n<BlockCount;++n)
|
|
{
|
|
if (!FuncVirtualCopy(Virt,(LPVOID)(Blocks[n].Addr >> 8), Blocks[n].Length,Mode))
|
|
break;
|
|
|
|
p->Blocks[n].Addr = Blocks[n].Addr;
|
|
p->Blocks[n].Length = Blocks[n].Length;
|
|
Virt += Blocks[n].Length;
|
|
}
|
|
|
|
if (n==BlockCount)
|
|
{
|
|
p->RefCount = 1;
|
|
p->Phy = Blocks[0].Addr;
|
|
p->Length = Blocks[0].Length;
|
|
p->BlockCount = BlockCount;
|
|
|
|
#ifdef ARM
|
|
if (Cached && FuncVirtualSetAttributes && (QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_XSCALE))
|
|
FuncVirtualSetAttributes(p->Virt,Size,TBL_CACHE|TBL_BUFFER,TBL_CACHE|TBL_BUFFER,NULL);
|
|
#endif
|
|
return p->Virt;
|
|
}
|
|
|
|
VirtualFree(p->Virt,0,MEM_RELEASE);
|
|
}
|
|
free(p->Blocks);
|
|
}
|
|
|
|
memset(p,0,sizeof(phymem));
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
void* PhyMemBegin(uint32_t Phy,uint32_t Length,bool_t Cached)
|
|
{
|
|
#if defined(TARGET_WINCE)
|
|
if (FuncVirtualCopy && Phy && Length)
|
|
{
|
|
int Mode;
|
|
phymem* p;
|
|
for (p=PhyMem;p!=PhyMem+MAXPHY;++p)
|
|
if (p->Phy <= Phy && p->Phy+p->Length >= Phy+Length)
|
|
{
|
|
++p->RefCount;
|
|
return p->Virt + (Phy - p->Phy);
|
|
}
|
|
|
|
for (Mode=0;Mode<2;++Mode)
|
|
for (p=PhyMem;p!=PhyMem+MAXPHY;++p)
|
|
{
|
|
if (Mode && !p->RefCount && p->Length)
|
|
{
|
|
free(p->Blocks);
|
|
SafeVirtualFree(p->Virt,p->Length);
|
|
memset(p,0,sizeof(phymem));
|
|
}
|
|
|
|
if (!p->Length)
|
|
{
|
|
int Align = Phy & 4095;
|
|
Phy -= Align;
|
|
Length = (Length + Align + 4095) & ~4095;
|
|
p->Virt = (char*) VirtualAlloc(0, Length, MEM_RESERVE, PAGE_NOACCESS);
|
|
if (p->Virt)
|
|
{
|
|
int Mode = PAGE_READWRITE | PAGE_PHYSICAL;
|
|
if (!Cached)
|
|
Mode |= PAGE_NOCACHE;
|
|
|
|
if (FuncVirtualCopy(p->Virt,(LPVOID)(Phy >> 8), Length, Mode))
|
|
{
|
|
p->RefCount = 1;
|
|
p->Phy = Phy;
|
|
p->Length = Length;
|
|
p->BlockCount = 1;
|
|
|
|
#ifdef ARM
|
|
if (Cached && FuncVirtualSetAttributes && (QueryPlatform(PLATFORM_CAPS) & CAPS_ARM_XSCALE))
|
|
FuncVirtualSetAttributes(p->Virt,Length,TBL_CACHE|TBL_BUFFER,TBL_CACHE|TBL_BUFFER,NULL);
|
|
#endif
|
|
return p->Virt + Align;
|
|
}
|
|
VirtualFree(p->Virt,0,MEM_RELEASE);
|
|
}
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
void PhyMemEnd(void* Virt)
|
|
{
|
|
#if defined(TARGET_WINCE)
|
|
if (Virt)
|
|
{
|
|
phymem* p;
|
|
for (p=PhyMem;p!=PhyMem+MAXPHY;++p)
|
|
if (p->RefCount && p->Virt <= (char*)Virt && p->Virt+p->Length > (char*)Virt)
|
|
{
|
|
--p->RefCount;
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
bool_t MemGetInfo(memoryinfo* p)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void* CodeAlloc(int Size)
|
|
{
|
|
void* p;
|
|
do
|
|
{
|
|
p = VirtualAlloc(NULL,Size,MEM_COMMIT,PAGE_EXECUTE_READ);
|
|
}
|
|
while (!p && Size && NodeHibernate());
|
|
return p;
|
|
}
|
|
|
|
void CodeFree(void* Code,int Size)
|
|
{
|
|
VirtualFree(Code,Size,MEM_DECOMMIT);
|
|
VirtualFree(Code,0,MEM_RELEASE);
|
|
}
|
|
|
|
void CodeLock(void* Code,int Size)
|
|
{
|
|
DWORD Protect;
|
|
VirtualProtect(Code,Size,PAGE_READWRITE|PAGE_NOCACHE,&Protect);
|
|
}
|
|
|
|
void CodeUnlock(void* Code,int Size)
|
|
{
|
|
DWORD Protect;
|
|
VirtualProtect(Code,Size,PAGE_EXECUTE_READ,&Protect);
|
|
#if defined(TARGET_WINCE)
|
|
if (FuncCacheSync)
|
|
FuncCacheSync(CACHE_SYNC_INSTRUCTIONS);
|
|
#endif
|
|
}
|
|
|
|
void CodeFindPages(void* Ptr,uint8_t** PMin,uint8_t** PMax,uintptr_t* PPageSize)
|
|
{
|
|
uint8_t* Min;
|
|
uint8_t* Max;
|
|
uintptr_t PageSize =
|
|
#if defined(MIPS)
|
|
1024;
|
|
#else
|
|
4096;
|
|
#endif
|
|
if (PPageSize)
|
|
*PPageSize = PageSize;
|
|
|
|
Min = Max = (uint8_t*)((uintptr_t)Ptr & ~(PageSize-1));
|
|
while (!IsBadCodePtr((FARPROC)(Min-PageSize)))
|
|
Min -= PageSize;
|
|
while (!IsBadCodePtr((FARPROC)Max))
|
|
Max += PageSize;
|
|
|
|
*PMin = Min;
|
|
*PMax = Max;
|
|
}
|
|
|
|
void CheckHeap()
|
|
{
|
|
#if defined(_DEBUG) && defined(_MSC_VER) && (_MSC_VER < 1400)
|
|
assert(_CrtCheckMemory());
|
|
#endif
|
|
}
|
|
|
|
//#define FIND 0xAD1A30
|
|
|
|
size_t AvailMemory()
|
|
{
|
|
MEMORYSTATUS Status;
|
|
Status.dwLength = sizeof(Status);
|
|
|
|
GlobalMemoryStatus(&Status);
|
|
|
|
return Status.dwAvailPhys;
|
|
}
|
|
|
|
void WriteBlock(block* Block,int Ofs,const void* Src,int Length)
|
|
{
|
|
memcpy((uint8_t*)Block->Ptr+Ofs,Src,Length);
|
|
}
|
|
|
|
void FreeBlock(block* p)
|
|
{
|
|
if (p)
|
|
{
|
|
#ifdef BLOCKGROUP
|
|
if (p->Id) //group
|
|
{
|
|
blockgroup* g = ARRAYBEGIN(BlockGroup,blockgroup)+(p->Id>>8);
|
|
int Bit = 1 << ((p->Id & 255)-1);
|
|
if (g<ARRAYEND(BlockGroup,blockgroup) && g->Mask & Bit)
|
|
{
|
|
g->Mask &= ~Bit;
|
|
if (!g->Mask)
|
|
FreeBlock(&g->Block);
|
|
}
|
|
p->Ptr = NULL;
|
|
p->Id = 0;
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NDEBUG
|
|
if (VirtualFree((void*)p->Ptr,0,MEM_RELEASE))
|
|
--BlockAllocated;
|
|
#else
|
|
VirtualFree((void*)p->Ptr,0,MEM_RELEASE);
|
|
#endif
|
|
|
|
p->Ptr = NULL;
|
|
p->Id = 0;
|
|
}
|
|
}
|
|
|
|
bool_t SetHeapBlock(int n,block* Block,int Heap)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#ifdef BLOCKGROUP
|
|
static bool_t AllocBlockGroup(block* Block, bool_t Optional)
|
|
{
|
|
int n;
|
|
blockgroup* g;
|
|
for (g=ARRAYBEGIN(BlockGroup,blockgroup);g!=ARRAYEND(BlockGroup,blockgroup);++g)
|
|
if (g->Mask && g->Mask != (1<<BLOCKGROUP)-1)
|
|
break;
|
|
|
|
if (g==ARRAYEND(BlockGroup,blockgroup))
|
|
{
|
|
if (!Optional)
|
|
return 0;
|
|
|
|
for (g=ARRAYBEGIN(BlockGroup,blockgroup);g!=ARRAYEND(BlockGroup,blockgroup);++g)
|
|
if (!g->Mask)
|
|
break;
|
|
|
|
if (g==ARRAYEND(BlockGroup,blockgroup))
|
|
{
|
|
if (!ArrayAppend(&BlockGroup,NULL,sizeof(blockgroup),64))
|
|
return 0;
|
|
g=ARRAYEND(BlockGroup,blockgroup)-1;
|
|
g->Mask = 0;
|
|
}
|
|
|
|
if (!AllocBlock(BLOCKSIZE*BLOCKGROUP,&g->Block,1,HEAP_ANY))
|
|
return 0;
|
|
}
|
|
|
|
for (n=0;n<BLOCKGROUP;++n)
|
|
if (!(g->Mask & (1<<n)))
|
|
{
|
|
g->Mask |= (1<<n);
|
|
Block->Id = ((g-ARRAYBEGIN(BlockGroup,blockgroup))<<8)+(n+1);
|
|
Block->Ptr = g->Block.Ptr + n*BLOCKSIZE;
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
bool_t AllocBlock(size_t n,block* Block,bool_t Optional,int Heap)
|
|
{
|
|
void* p;
|
|
|
|
if (Optional && AvailMemory() < (256+64)*1024+n) // we want to avoid OS low memory warning
|
|
return 0;
|
|
#ifdef BLOCKGROUP
|
|
if (n == BLOCKSIZE && AllocBlockGroup(Block,Optional))
|
|
return 1;
|
|
#endif
|
|
do
|
|
{
|
|
p = VirtualAlloc(NULL,n,MEM_COMMIT,PAGE_READWRITE);
|
|
}
|
|
while (!p && !Optional && n && NodeHibernate());
|
|
|
|
Block->Ptr = p;
|
|
Block->Id = 0;
|
|
|
|
#ifndef NDEBUG
|
|
if (p) ++BlockAllocated;
|
|
#endif
|
|
|
|
return p!=NULL;
|
|
}
|
|
|
|
#undef malloc
|
|
#undef realloc
|
|
#undef free
|
|
|
|
|
|
#ifdef SAFEGUARD
|
|
void* safeset(uint8_t* p,int n,bool_t clear)
|
|
{
|
|
if (p)
|
|
{
|
|
*(int*)p = n;
|
|
p += sizeof(int);
|
|
memset(p,0xDA,SAFEGUARD);
|
|
p += SAFEGUARD;
|
|
if (clear)
|
|
memset(p,0xCC,n);
|
|
p += n;
|
|
memset(p,0xDE,SAFEGUARD);
|
|
p -= n;
|
|
}
|
|
return p;
|
|
}
|
|
void* safeget(uint8_t* p,bool_t clear)
|
|
{
|
|
if (p)
|
|
{
|
|
int n = *(int*)(p-SAFEGUARD-sizeof(int));
|
|
int i;
|
|
for (i=0;i<SAFEGUARD;++i)
|
|
assert(p[-i-1] == 0xDA);
|
|
for (i=0;i<SAFEGUARD;++i)
|
|
assert(p[n+i] == 0xDE);
|
|
p -= SAFEGUARD+sizeof(int);
|
|
if (clear)
|
|
memset(p,0xEE,n+SAFEGUARD*2+sizeof(int));
|
|
}
|
|
return p;
|
|
}
|
|
#endif
|
|
|
|
void* malloc_win32(size_t n)
|
|
{
|
|
void* p = NULL;
|
|
if (n)
|
|
{
|
|
do
|
|
{
|
|
#ifdef SAFEGUARD
|
|
p = safeset(malloc(n+SAFEGUARD*2+sizeof(int)),n,1);
|
|
#else
|
|
p = malloc(n);
|
|
#endif
|
|
|
|
#ifdef FIND
|
|
if ((int)p == FIND)
|
|
DebugBreak();
|
|
#endif
|
|
} while (!p && NodeHibernate());
|
|
}
|
|
return p;
|
|
}
|
|
|
|
void* realloc_win32(void* p,size_t n)
|
|
{
|
|
do
|
|
{
|
|
#ifdef SAFEGUARD
|
|
p = safeset(realloc(safeget(p,0),n+SAFEGUARD*2+sizeof(int)),n,p==NULL);
|
|
#else
|
|
p = realloc(p,n);
|
|
#endif
|
|
|
|
#ifdef FIND
|
|
if ((int)p == FIND)
|
|
DebugBreak();
|
|
#endif
|
|
} while (!p && n && NodeHibernate());
|
|
return p;
|
|
}
|
|
|
|
void free_win32(void* p)
|
|
{
|
|
#ifdef SAFEGUARD
|
|
free(safeget(p,1));
|
|
#else
|
|
free(p);
|
|
#endif
|
|
}
|
|
|
|
void ShowOutOfMemory()
|
|
{
|
|
}
|
|
|
|
void EnableOutOfMemory()
|
|
{
|
|
}
|
|
|
|
void DisableOutOfMemory()
|
|
{
|
|
}
|
|
|
|
void Mem_Init()
|
|
{
|
|
SYSTEM_INFO SysInfo;
|
|
|
|
#if defined(_DEBUG) && defined(_MSC_VER) && !defined(TARGET_WINCE)
|
|
int Flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
|
|
Flag |= _CRTDBG_LEAK_CHECK_DF;
|
|
Flag |= _CRTDBG_CHECK_ALWAYS_DF;
|
|
_CrtSetDbgFlag(Flag);
|
|
#endif
|
|
|
|
#if defined(TARGET_WINCE)
|
|
CoreDLL = LoadLibrary(T("coredll.dll"));
|
|
if (CoreDLL)
|
|
{
|
|
*(FARPROC*)&FuncCacheSync = GetProcAddress(CoreDLL,T("CacheSync"));
|
|
*(FARPROC*)&FuncVirtualCopy = GetProcAddress(CoreDLL,T("VirtualCopy"));
|
|
*(FARPROC*)&FuncVirtualSetAttributes = GetProcAddress(CoreDLL,T("VirtualSetAttributes"));
|
|
*(FARPROC*)&FuncFreePhysMem = GetProcAddress(CoreDLL,T("FreePhysMem"));
|
|
*(FARPROC*)&FuncAllocPhysMem = GetProcAddress(CoreDLL,T("AllocPhysMem"));
|
|
*(FARPROC*)&FuncLockPages = GetProcAddress(CoreDLL,T("LockPages"));
|
|
*(FARPROC*)&FuncUnlockPages = GetProcAddress(CoreDLL,T("UnlockPages"));
|
|
}
|
|
#endif
|
|
|
|
GetSystemInfo(&SysInfo);
|
|
PageSize = SysInfo.dwPageSize;
|
|
}
|
|
|
|
void Mem_Done()
|
|
{
|
|
#if defined(TARGET_WINCE)
|
|
phymem* p;
|
|
for (p=PhyMem;p!=PhyMem+MAXPHY;++p)
|
|
if (p->Length)
|
|
{
|
|
free(p->Blocks);
|
|
SafeVirtualFree(p->Virt,p->Length);
|
|
memset(p,0,sizeof(phymem));
|
|
}
|
|
|
|
if (CoreDLL) FreeLibrary(CoreDLL);
|
|
#endif
|
|
#ifndef NDEBUG
|
|
assert(BlockAllocated==0);
|
|
#endif
|
|
ArrayClear(&BlockGroup);
|
|
}
|
|
|
|
#endif
|