1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// ZONE MEMORY ALLOCATION
//
// There is never any space between memblocks, and there will never be two
// contiguous free memblocks.
//
// The rover can be left pointing at a non-empty block
//
// The zone calls are pretty much only used for small strings and structures,
// all big things are allocated on the hunk.
//=============================================================================//
#include "basetypes.h"
#include "zone.h"
#include "host.h"
#include "tier1/strtools.h"
#include "tier0/icommandline.h"
#include "memstack.h"
#include "datacache/idatacache.h"
#include "sys_dll.h"
#include "tier0/memalloc.h"
#define MINIMUM_WIN_MEMORY 0x03000000 // FIXME: copy from sys_dll.cpp, find a common header at some point
#ifdef _X360
#define HUNK_USE_16MB_PAGE
#endif
CMemoryStack g_HunkMemoryStack;
#ifdef HUNK_USE_16MB_PAGE
CMemoryStack g_HunkOverflow;
static bool g_bWarnedOverflow;
#endif
static int GetTargetCacheSize()
{
int nMemLimit = host_parms.memsize - Hunk_Size();
if ( nMemLimit < 0x100000 )
{
nMemLimit = 0x100000;
}
return nMemLimit;
}
/*
===================
Hunk_AllocName
===================
*/
void *Hunk_AllocName (int size, const char *name, bool bClear)
{
MEM_ALLOC_CREDIT();
void * p = g_HunkMemoryStack.Alloc( size, bClear );
if ( p )
return p;
#ifdef HUNK_USE_16MB_PAGE
if ( !g_bWarnedOverflow )
{
g_bWarnedOverflow = true;
DevMsg( "Note: Hunk base page exhausted\n" );
}
p = g_HunkOverflow.Alloc( size, bClear );
if ( p )
return p;
#endif
Error( "Engine hunk overflow!\n" );
return NULL;
}
/*
===================
Hunk_Alloc
===================
*/
void *Hunk_Alloc(int size, bool bClear )
{
MEM_ALLOC_CREDIT();
return Hunk_AllocName( size, NULL, bClear );
}
int Hunk_LowMark(void)
{
return (int)( g_HunkMemoryStack.GetCurrentAllocPoint() );
}
void Hunk_FreeToLowMark(int mark)
{
Assert( mark < g_HunkMemoryStack.GetSize() );
#ifdef HUNK_USE_16MB_PAGE
g_HunkOverflow.FreeAll();
g_bWarnedOverflow = false;
#endif
g_HunkMemoryStack.FreeToAllocPoint( mark );
}
int Hunk_MallocSize()
{
#ifdef HUNK_USE_16MB_PAGE
return g_HunkMemoryStack.GetSize() + g_HunkOverflow.GetSize();
#else
return g_HunkMemoryStack.GetSize();
#endif
}
int Hunk_Size()
{
#ifdef HUNK_USE_16MB_PAGE
return g_HunkMemoryStack.GetUsed() + g_HunkOverflow.GetUsed();
#else
return g_HunkMemoryStack.GetUsed();
#endif
}
void Hunk_Print()
{
#ifdef HUNK_USE_16MB_PAGE
Msg( "Total used memory: %d (%d/%d)\n", Hunk_Size(), g_HunkMemoryStack.GetUsed(), g_HunkOverflow.GetUsed() );
Msg( "Total committed memory: %d (%d/%d)\n", Hunk_MallocSize(), g_HunkMemoryStack.GetSize(), g_HunkOverflow.GetSize() );
#else
Msg( "Total used memory: %d\n", Hunk_Size() );
Msg( "Total committed memory: %d\n", Hunk_MallocSize() );
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Memory_Init( void )
{
MEM_ALLOC_CREDIT();
int nMaxBytes = 48*1024*1024;
const int nMinCommitBytes = 0x8000;
#ifndef HUNK_USE_16MB_PAGE
const int nInitialCommit = 0x280000;
while ( !g_HunkMemoryStack.Init( nMaxBytes, nMinCommitBytes, nInitialCommit ) )
{
Warning( "Unable to allocate %d MB of memory, trying %d MB instead\n", nMaxBytes, nMaxBytes/2 );
nMaxBytes /= 2;
if ( nMaxBytes < MINIMUM_WIN_MEMORY )
{
Error( "Failed to allocate minimum memory requirement for game (%d MB)\n", MINIMUM_WIN_MEMORY/(1024*1024));
}
}
#else
if ( !g_HunkMemoryStack.InitPhysical( 16*1024*1024 ) || !g_HunkOverflow.Init( nMaxBytes - 16*1024*1024, nMinCommitBytes ) )
{
Error( "Failed to allocate minimum memory requirement for game (%d MB)\n", nMaxBytes );
}
#endif
g_pDataCache->SetSize( GetTargetCacheSize() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Memory_Shutdown( void )
{
g_HunkMemoryStack.FreeAll();
// This disconnects the engine data cache
g_pDataCache->SetSize( 0 );
}
|