Newer
Older
#if defined(CONFIG_UNIT_TEST)
#include <asm/io.h>
#ifdef DEBUG
#if __STD_C
static void malloc_update_mallinfo (void);
void malloc_stats (void);
#else
static void malloc_update_mallinfo ();
void malloc_stats();
#endif
#endif /* DEBUG */
DECLARE_GLOBAL_DATA_PTR;
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
/*
Emulation of sbrk for WIN32
All code within the ifdef WIN32 is untested by me.
Thanks to Martin Fong and others for supplying this.
*/
#ifdef WIN32
#define AlignPage(add) (((add) + (malloc_getpagesize-1)) & \
~(malloc_getpagesize-1))
#define AlignPage64K(add) (((add) + (0x10000 - 1)) & ~(0x10000 - 1))
/* resrve 64MB to insure large contiguous space */
#define RESERVED_SIZE (1024*1024*64)
#define NEXT_SIZE (2048*1024)
#define TOP_MEMORY ((unsigned long)2*1024*1024*1024)
struct GmListElement;
typedef struct GmListElement GmListElement;
struct GmListElement
{
GmListElement* next;
void* base;
};
static GmListElement* head = 0;
static unsigned int gNextAddress = 0;
static unsigned int gAddressBase = 0;
static unsigned int gAllocatedSize = 0;
static
GmListElement* makeGmListElement (void* bas)
{
GmListElement* this;
this = (GmListElement*)(void*)LocalAlloc (0, sizeof (GmListElement));
assert (this);
if (this)
{
this->base = bas;
this->next = head;
head = this;
}
return this;
}
void gcleanup ()
{
BOOL rval;
assert ( (head == NULL) || (head->base == (void*)gAddressBase));
if (gAddressBase && (gNextAddress - gAddressBase))
{
rval = VirtualFree ((void*)gAddressBase,
gNextAddress - gAddressBase,
MEM_DECOMMIT);
}
while (head)
{
GmListElement* next = head->next;
rval = VirtualFree (head->base, 0, MEM_RELEASE);
assert (rval);
LocalFree (head);
head = next;
}
}
static
void* findRegion (void* start_address, unsigned long size)
{
MEMORY_BASIC_INFORMATION info;
if (size >= TOP_MEMORY) return NULL;
while ((unsigned long)start_address + size < TOP_MEMORY)
{
VirtualQuery (start_address, &info, sizeof (info));
if ((info.State == MEM_FREE) && (info.RegionSize >= size))
return start_address;
else
{
/* Requested region is not available so see if the */
/* next region is available. Set 'start_address' */
/* to the next region and call 'VirtualQuery()' */
/* again. */
start_address = (char*)info.BaseAddress + info.RegionSize;
/* Make sure we start looking for the next region */
/* on the *next* 64K boundary. Otherwise, even if */
/* the new region is free according to */
/* 'VirtualQuery()', the subsequent call to */
/* 'VirtualAlloc()' (which follows the call to */
/* this routine in 'wsbrk()') will round *down* */
/* the requested address to a 64K boundary which */
/* we already know is an address in the */
/* unavailable region. Thus, the subsequent call */
/* to 'VirtualAlloc()' will fail and bring us back */
/* here, causing us to go into an infinite loop. */
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
start_address =
(void *) AlignPage64K((unsigned long) start_address);
}
}
return NULL;
}
void* wsbrk (long size)
{
void* tmp;
if (size > 0)
{
if (gAddressBase == 0)
{
gAllocatedSize = max (RESERVED_SIZE, AlignPage (size));
gNextAddress = gAddressBase =
(unsigned int)VirtualAlloc (NULL, gAllocatedSize,
MEM_RESERVE, PAGE_NOACCESS);
} else if (AlignPage (gNextAddress + size) > (gAddressBase +
gAllocatedSize))
{
long new_size = max (NEXT_SIZE, AlignPage (size));
void* new_address = (void*)(gAddressBase+gAllocatedSize);
do
{
new_address = findRegion (new_address, new_size);
if (new_address == 0)
return (void*)-1;
gAddressBase = gNextAddress =
(unsigned int)VirtualAlloc (new_address, new_size,
MEM_RESERVE, PAGE_NOACCESS);
/* repeat in case of race condition */
/* The region that we found has been snagged */
/* by another thread */
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
}
while (gAddressBase == 0);
assert (new_address == (void*)gAddressBase);
gAllocatedSize = new_size;
if (!makeGmListElement ((void*)gAddressBase))
return (void*)-1;
}
if ((size + gNextAddress) > AlignPage (gNextAddress))
{
void* res;
res = VirtualAlloc ((void*)AlignPage (gNextAddress),
(size + gNextAddress -
AlignPage (gNextAddress)),
MEM_COMMIT, PAGE_READWRITE);
if (res == 0)
return (void*)-1;
}
tmp = (void*)gNextAddress;
gNextAddress = (unsigned int)tmp + size;
return tmp;
}
else if (size < 0)
{
unsigned int alignedGoal = AlignPage (gNextAddress + size);
/* Trim by releasing the virtual memory */
if (alignedGoal >= gAddressBase)
{
VirtualFree ((void*)alignedGoal, gNextAddress - alignedGoal,
MEM_DECOMMIT);
gNextAddress = gNextAddress + size;
return (void*)gNextAddress;
}
else
{
VirtualFree ((void*)gAddressBase, gNextAddress - gAddressBase,
MEM_DECOMMIT);
gNextAddress = gAddressBase;
Loading
Loading full blame...