Subversion Repositories Kolibri OS

Rev

Rev 7520 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 7520 Rev 7537
1
/*
1
/*
2
 * Easy and fast memory allocator from
2
 * Easy and fast memory allocator from
3
 * https://wiki.osdev.org/Memory_Allocation
3
 * https://wiki.osdev.org/Memory_Allocation
4
 * Coded by Siemargl, 2018
4
 * Coded by Siemargl, 2018
5
 * 
5
 * 
6
 * No Garbage Collector
6
 * No Garbage Collector
7
 */
7
 */
8
 
8
 
9
#include 
9
#include 
10
#include 
10
#include 
11
#include 
11
#include 
12
#include 
12
#include 
13
#include 
13
#include 
14
 
14
 
15
#define UINT_MAX  (4294967295U)
15
#define UINT_MAX  (4294967295U)
16
 
16
 
17
#ifndef NDEBUG
17
#ifndef NDEBUG
18
#include 
18
#include 
-
 
19
#	ifdef __TINYC__
-
 
20
#		include 
-
 
21
#		define TRACE1(s, a) { char buf[400]; sprintf(buf, s, a); debug_out_str(buf); }
-
 
22
#		define TRACE2(s, a, b) { char buf[400]; sprintf(buf, s, a, b); debug_out_str(buf); }
-
 
23
#	else
19
#	define TRACE1(s, a) printf(s, a)
24
#		define TRACE1(s, a) printf(s, a)
20
#	define TRACE2(s, a, b) printf(s, a, b)
25
#		define TRACE2(s, a, b) printf(s, a, b)
-
 
26
#	endif
21
#else
27
#else
22
#	define TRACE1(s, a) (void)0
28
#	define TRACE1(s, a) (void)0
23
#	define TRACE2(s, a, b) (void)0
29
#	define TRACE2(s, a, b) (void)0
24
#endif
30
#endif
-
 
31
 
-
 
32
 
-
 
33
 
25
 
34
 
26
// get address, fromwhere function was called
35
// get address, fromwhere function was called
27
#define CALLEDFROM(param1) (*(int*)((char*)¶m1-4)-5)
36
#define CALLEDFROM(param1) (*(int*)((char*)¶m1-4)-5)
28
   
37
   
29
const uint32_t c_used = 0x44455355; //'USED'
38
const uint32_t c_used = 0x44455355; //'USED'
30
const uint32_t c_free = 0x45455246; //'FREE'
39
const uint32_t c_free = 0x45455246; //'FREE'
31
 
40
 
32
struct hdrfree {
41
struct hdrfree {
33
	uint32_t 	mark; // 'FREE'
42
	uint32_t 	mark; // 'FREE'
34
	size_t		size; // including header
43
	size_t		size; // including header
35
	struct hdrfree	*prev;
44
	struct hdrfree	*prev;
36
	struct hdrfree	*next;
45
	struct hdrfree	*next;
37
};
46
};
38
 
47
 
39
struct hdrused {
48
struct hdrused {
40
	uint32_t	mark; // 'USED'
49
	uint32_t	mark; // 'USED'
41
	size_t		size;
50
	size_t		size;
42
};
51
};
43
 
52
 
44
 
53
 
45
static char *__freebase = NULL; 	// begin of free area
54
static char *__freebase = NULL; 	// begin of free area
46
static char *__freetop = NULL;		// after last byte of free area
55
static char *__freetop = NULL;		// after last byte of free area
47
static struct hdrfree *__firstfree = NULL;	// ptr to first node in dual-link list
56
static struct hdrfree *__firstfree = NULL;	// ptr to first node in dual-link list
-
 
57
 
-
 
58
static struct {
-
 
59
	uint32_t	malloc_calls;
-
 
60
	uint32_t	malloc_max;
-
 
61
	uint32_t	malloc_sum;
-
 
62
	
-
 
63
	uint32_t	sysalloc_calls;
-
 
64
	uint32_t	sysalloc_max;
-
 
65
	uint32_t	sysalloc_sum;
-
 
66
	
48
static unsigned __crtfreeblocks = 0; // number of free blocks, checking corruptions
67
	uint32_t	crtfreeblocks; // number of free blocks, checking corruptions
-
 
68
	uint32_t	freeblocks_sum;
-
 
69
} wtalloc_stat;
49
 
70
 
50
 
71
 
51
void *wtmalloc(size_t sz)
72
void *wtmalloc(size_t sz)
52
{
73
{
53
	struct hdrfree *fndnode, *newnode;
74
	struct hdrfree *fndnode, *newnode;
54
	sz = (sizeof(struct hdrused) + sz + 15) & ~15; // align 16bytes
75
	sz = (sizeof(struct hdrused) + sz + 15) & ~15; // align 16bytes
55
//TRACE1("_call alloc(%d)\n", sz);
76
//TRACE1("_call alloc(%d)\n", sz);
-
 
77
 
-
 
78
	//statistics
-
 
79
	wtalloc_stat.malloc_calls++;
-
 
80
	if (sz > wtalloc_stat.malloc_max) wtalloc_stat.malloc_max = sz;
-
 
81
	wtalloc_stat.malloc_sum += sz;
56
	
82
	
57
	// try to find free block enough size
83
	// try to find free block enough size
58
	fndnode = __firstfree;
84
	fndnode = __firstfree;
59
	while(fndnode)
85
	while(fndnode)
60
	{
86
	{
61
#ifndef NDEBUG
87
#ifndef NDEBUG
62
		if (fndnode->mark != c_free)
88
		if (fndnode->mark != c_free)
63
		{
89
		{
64
			TRACE2("heap free block list corrupt %x  EIP@%x\n", fndnode, CALLEDFROM(sz));
90
			TRACE2("heap free block list corrupt %x  EIP@%x\n", fndnode, CALLEDFROM(sz));
65
			assert(0);
91
			assert(0);
66
		}
92
		}
67
#endif
93
#endif
68
		if (fndnode->size >= sz) break;
94
		if (fndnode->size >= sz) break;
69
		fndnode = fndnode->next;
95
		fndnode = fndnode->next;
70
	}
96
	}
71
	
97
	
72
	if (fndnode) // found free block
98
	if (fndnode) // found free block
73
	{
99
	{
74
		if (fndnode->size - sz > 15) // split smaller size, move free node
100
		if (fndnode->size - sz > 15) // split smaller size, move free node
75
		{
101
		{
76
//TRACE2("alloc(%d) split (%x)\n", sz, fndnode);
102
//TRACE2("alloc(%d) split (%x)\n", sz, fndnode);
-
 
103
			wtalloc_stat.freeblocks_sum -= sz;
77
			newnode = (struct hdrfree*)((char*)fndnode + sz);
104
			newnode = (struct hdrfree*)((char*)fndnode + sz);
78
			newnode->mark = c_free;
105
			newnode->mark = c_free;
79
			newnode->size = fndnode->size - sz;
106
			newnode->size = fndnode->size - sz;
80
			newnode->next = fndnode->next;
107
			newnode->next = fndnode->next;
81
			newnode->prev = fndnode->prev;
108
			newnode->prev = fndnode->prev;
82
			
109
			
83
			if (fndnode->next)
110
			if (fndnode->next)
84
				fndnode->next->prev = newnode;
111
				fndnode->next->prev = newnode;
85
			
112
			
86
			//перед может быть не нода, а 1й указатель
113
			//перед может быть не нода, а 1й указатель
87
			if (!fndnode->prev)
114
			if (fndnode->prev)
88
				__firstfree = newnode;
-
 
89
			else
-
 
90
				newnode->prev->next = newnode;
115
				newnode->prev->next = newnode;
-
 
116
			else
-
 
117
				__firstfree = newnode;
91
		} else // nothing to split, just exclude
118
		} else // nothing to split, just exclude
92
		{
119
		{
93
//TRACE1("alloc(%d) remove freenode\n", sz);
120
//TRACE1("alloc(%d) remove freenode\n", sz);
94
 
121
 
-
 
122
			wtalloc_stat.crtfreeblocks--;
95
			__crtfreeblocks--;
123
			wtalloc_stat.freeblocks_sum -= fndnode->size;
96
			if (fndnode->next)
124
			if (fndnode->next)
97
				fndnode->next->prev = fndnode->prev;
125
				fndnode->next->prev = fndnode->prev;
98
			//перед может быть не нода, а 1й указатель
126
			//перед может быть не нода, а 1й указатель
99
			if (!fndnode->prev)
127
			if (fndnode->prev)
100
				__firstfree = fndnode->next;
-
 
101
			else
-
 
102
				fndnode->prev->next = fndnode->next;
128
				fndnode->prev->next = fndnode->next;
-
 
129
			else
-
 
130
				__firstfree = fndnode->next;
103
		}
131
		}
104
		
132
		
105
		fndnode->mark = c_used;
133
		fndnode->mark = c_used;
106
		fndnode->size = sz;
134
		fndnode->size = sz;
107
		return (char*)fndnode + sizeof(struct hdrused);
135
		return (char*)fndnode + sizeof(struct hdrused);
108
	}
136
	}
109
	
137
	
110
	char *ptr;
138
	char *ptr;
111
	// free block not found, try to add @end
139
	// free block not found, try to add @end
112
	if (__freetop - __freebase < sz)  // not enough memory - call system 
140
	if (__freetop - __freebase < sz)  // not enough memory - call system 
113
	{
141
	{
114
		if (sz > UINT_MAX - 16) return NULL;  // check 32-bit heap overflow
142
		if (sz > UINT_MAX - 16) return NULL;  // check 32-bit heap overflow
115
		size_t new_heap_size = (__freetop - __freebase + sz + 4095) & ~4095;   
143
//		size_t new_heap_size = (__freetop - __freebase + sz + 4095) & ~4095;   
-
 
144
		size_t new_heap_size = (sz + sz / 5 + 4095) & ~4095;  // 20% reserved 
-
 
145
		
-
 
146
		//statistics
-
 
147
		wtalloc_stat.sysalloc_calls++;
-
 
148
		if (new_heap_size > wtalloc_stat.malloc_max) wtalloc_stat.sysalloc_max = new_heap_size;
-
 
149
		wtalloc_stat.sysalloc_sum += new_heap_size;
-
 
150
 
116
		
151
 
117
		//хвост сунуть в свободные, а фритоп и базу перености на новый кусок
152
		//хвост сунуть в свободные, а фритоп и базу перености на новый кусок
118
		ptr = sysmalloc(new_heap_size);   // rounded 4k
153
		ptr = sysmalloc(new_heap_size);   // rounded 4k
119
//TRACE2("call systemalloc(%d) returned %x\n", new_heap_size, ptr);
154
//TRACE2("call systemalloc(%d) returned %x\n", new_heap_size, ptr);
120
		if (!ptr)
155
		if (!ptr)
121
		{
156
		{
122
			TRACE2("sysmalloc failed trying to allocate %u bytes EIP@%x\n", sz, CALLEDFROM(sz));
157
			TRACE2("sysmalloc failed trying to allocate %u bytes EIP@%x\n", sz, CALLEDFROM(sz));
123
			return NULL;
158
			return NULL;
124
		}
159
		}
125
		// add new free block in front of list
160
		// add new free block in front of list
126
		if (__freetop - __freebase > 15)
161
		if (__freetop - __freebase > 15)
127
		{
162
		{
128
			newnode = (struct hdrfree*)__freebase;
163
			newnode = (struct hdrfree*)__freebase;
129
			newnode->mark = c_free;
164
			newnode->mark = c_free;
130
			newnode->size = __freetop - __freebase;
165
			newnode->size = __freetop - __freebase;
131
			newnode->next = __firstfree;
166
			newnode->next = __firstfree;
132
			newnode->prev = NULL;
167
			newnode->prev = NULL;
133
			if (__firstfree)
168
			if (__firstfree)
134
				__firstfree->prev = newnode;
169
				__firstfree->prev = newnode;
135
			__firstfree = newnode;
170
			__firstfree = newnode;
136
			__crtfreeblocks++;
171
			wtalloc_stat.crtfreeblocks++;
-
 
172
			wtalloc_stat.freeblocks_sum += newnode->size;
137
//TRACE2("alloc(%d) add tail %d to freenode", sz, newnode->size);
173
//TRACE2("alloc(%d) add tail %d to freenode", sz, newnode->size);
138
//TRACE1(".tail [%x]\n", newnode);
174
//TRACE1(".tail [%x]\n", newnode);
139
		}
175
		}
140
		// we don't save allocated block from system, so cant free them ltr
176
		// we don't save allocated block from system, so cant free them ltr
141
		
177
		
142
		__freebase = ptr;
178
		__freebase = ptr;
143
		__freetop = __freebase + new_heap_size;
179
		__freetop = __freebase + new_heap_size;
144
	}
180
	}
145
	
181
	
146
	ptr = __freebase + sizeof(struct hdrused);
182
	ptr = __freebase + sizeof(struct hdrused);
147
	((struct hdrused*)__freebase)->mark = c_used;
183
	((struct hdrused*)__freebase)->mark = c_used;
148
	((struct hdrused*)__freebase)->size = sz;
184
	((struct hdrused*)__freebase)->size = sz;
149
	__freebase += sz;
185
	__freebase += sz;
150
//TRACE1("__freebase [%x]\n", __freebase);
186
//TRACE1("__freebase [%x]\n", __freebase);
-
 
187
 
-
 
188
 
-
 
189
// check list availability
-
 
190
/*
-
 
191
int maxfree = 0;
-
 
192
for (fndnode = __firstfree; fndnode; fndnode = fndnode->next)
-
 
193
{
-
 
194
	if (fndnode->size > maxfree) maxfree = fndnode->size;
-
 
195
}
-
 
196
 
-
 
197
TRACE2("alloc(%d) from freebase, maxfree = %d,", sz, maxfree);
-
 
198
TRACE1(" freelist len = %u \n", wtalloc_stat.crtfreeblocks);
151
	
199
*/	
152
	return ptr;
200
	return ptr;
153
}
201
}
154
 
202
 
155
void wtfree(void *ptr)
203
void wtfree(void *ptr)
156
{
204
{
157
	if (!ptr) return;
205
	if (!ptr) return;
-
 
206
 
-
 
207
//TRACE1("free() to freenode, sized %d\n", ((struct hdrused*)((char*)ptr - 8))->size);
158
 
208
 
159
#ifndef NDEBUG
209
#ifndef NDEBUG
160
	if (((struct hdrused*)((char*)ptr - 8))->mark != c_used)
210
	if (((struct hdrused*)((char*)ptr - 8))->mark != c_used)
161
	{
211
	{
162
		TRACE2("try free unallocated block ptr = %x bytes EIP@%x\n", ptr, CALLEDFROM(ptr));
212
		TRACE2("try free unallocated block ptr = %x bytes EIP@%x\n", ptr, CALLEDFROM(ptr));
163
		assert(0);
213
		assert(0);
164
	}
214
	}
165
#endif
215
#endif
166
	struct hdrfree *newnode = (struct hdrfree*)((char*)ptr - 8);
216
	struct hdrfree *newnode = (struct hdrfree*)((char*)ptr - 8);
167
	newnode->mark = c_free;
217
	newnode->mark = c_free;
168
	//size stays
218
	//size stays
-
 
219
	newnode->next = NULL;
-
 
220
	newnode->prev = NULL;
-
 
221
	
-
 
222
 
-
 
223
	// experimental - try to merge, if adjanced from bottom is also freeblock
-
 
224
	int reorganized = 0;
-
 
225
	struct hdrfree *higher;
-
 
226
	{
-
 
227
		struct hdrfree *p1;
-
 
228
		higher = NULL;
-
 
229
		for (p1 = __firstfree; p1; p1 = p1->next)
-
 
230
		{
-
 
231
			higher = (struct hdrfree *)((char*)p1 + p1->size);
-
 
232
			if (higher == newnode) break;
-
 
233
		}
-
 
234
		if (p1) // yes, it is
-
 
235
		{
-
 
236
			wtalloc_stat.freeblocks_sum += newnode->size;
-
 
237
			p1->size += newnode->size;
-
 
238
			// p1->prev, p1->next  already OK
-
 
239
			newnode->mark = 0; // for safety
-
 
240
			newnode = p1;  // continue optimization
-
 
241
//TRACE2("free block merged w/bottom sized %u bytes, list len %u\n", p1->size, wtalloc_stat.crtfreeblocks);
-
 
242
			reorganized = 1;
-
 
243
		}
-
 
244
	}
-
 
245
 
-
 
246
 
-
 
247
/* removed, as very seldom succeeds */
-
 
248
	// experimental - try to merge, if adjanced from top is also freeblock
-
 
249
	higher = (struct hdrfree *)((char*)newnode + newnode->size);
-
 
250
// dont work - we try to read after our memory
-
 
251
//	if ((char*)higher < (char*)__freetop &&   // saves from reading out of our memory
-
 
252
//		higher->mark == c_free) // only suspisious, must be in list
-
 
253
	{
-
 
254
		struct hdrfree *p1;
-
 
255
		for (p1 = __firstfree; p1 && p1 != higher; p1 = p1->next);
-
 
256
		if (p1) // yes, it is
-
 
257
		{
-
 
258
			if (newnode->next || newnode->prev)  // optimized 1st stage, must remove from list and readd later
-
 
259
			{
-
 
260
				wtalloc_stat.crtfreeblocks--;
-
 
261
				wtalloc_stat.freeblocks_sum -= newnode->size;
-
 
262
				if (newnode->next)
-
 
263
					newnode->next->prev = newnode->prev;
-
 
264
				if (newnode->prev)
-
 
265
					newnode->prev->next = newnode->next;
-
 
266
				else
-
 
267
					__firstfree = newnode->next;
-
 
268
			}
-
 
269
			wtalloc_stat.freeblocks_sum += newnode->size;
-
 
270
			newnode->size += higher->size;
-
 
271
			newnode->prev = higher->prev;
-
 
272
			newnode->next = higher->next;
-
 
273
			higher->mark = 0; // for safety
-
 
274
			if (higher->next)
-
 
275
				higher->next->prev = newnode;
-
 
276
			if (higher->prev)
-
 
277
				higher->prev->next = newnode;
-
 
278
			else
-
 
279
				__firstfree = newnode;
-
 
280
//TRACE1("free block merged w/top\n", 0);
-
 
281
			reorganized = 1;
-
 
282
		}
-
 
283
	}
-
 
284
 
-
 
285
	if (reorganized) return;  // experimental reorganized do all work
-
 
286
	
-
 
287
//TRACE1("free block added\n", 0);
-
 
288
	wtalloc_stat.crtfreeblocks++;
-
 
289
	wtalloc_stat.freeblocks_sum += newnode->size;
-
 
290
 
169
	newnode->next = __firstfree;
291
	newnode->next = __firstfree;
170
	newnode->prev = NULL;
292
	newnode->prev = NULL;
171
	if (__firstfree)
293
	if (__firstfree)
172
		__firstfree->prev = newnode;
294
		__firstfree->prev = newnode;
173
	__firstfree = newnode;
295
	__firstfree = newnode;
174
	__crtfreeblocks++;
-
 
175
//TRACE1("free to freenode\n", 0);
-
 
176
}	
296
}	
177
 
297
 
178
 
298
 
179
void *wtrealloc(void *ptr, size_t sz)
299
void *wtrealloc(void *ptr, size_t sz)
180
{
300
{
181
	if (!ptr) return wtmalloc(sz);
301
	if (!ptr) return wtmalloc(sz);
182
	
302
	
183
	struct hdrused* oldptr = (struct hdrused*)((char*)ptr - 8);
303
	struct hdrused* oldptr = (struct hdrused*)((char*)ptr - 8);
184
 
304
 
185
#ifndef NDEBUG
305
#ifndef NDEBUG
186
	if (oldptr->mark != c_used)
306
	if (oldptr->mark != c_used)
187
	{
307
	{
188
		TRACE2("try realloc unallocated block ptr = %x  EIP@%x\n", ptr, CALLEDFROM(ptr));
308
		TRACE2("try realloc unallocated block ptr = %x  EIP@%x\n", ptr, CALLEDFROM(ptr));
189
		assert(0);
309
		assert(0);
190
	}
310
	}
191
#endif
311
#endif
192
 
312
 
193
	if (oldptr->size - 8 >= sz) return ptr; // enough room in this block, ex from freelist
313
	if (oldptr->size - 8 >= sz) return ptr; // enough room in this block, ex from freelist
-
 
314
	
-
 
315
	/* experimental	growth last block */
-
 
316
	int growth = (oldptr->size + sz + 15) & ~15;
-
 
317
	if ((char*)oldptr + oldptr->size == __freebase && 
-
 
318
		__freetop - __freebase + oldptr->size >= growth )  // we at top, can grow up
-
 
319
	{
-
 
320
		wtalloc_stat.malloc_sum += growth - oldptr->size;
-
 
321
		__freebase += growth - oldptr->size;
-
 
322
		oldptr->size = growth;
-
 
323
		return ptr;
-
 
324
	}
194
	
325
	
195
	void *newptr = wtmalloc(sz);
326
	void *newptr = wtmalloc(sz);
196
	if (newptr)
327
	if (newptr)
197
	{
328
	{
198
		memcpy(newptr, (char*)oldptr +8, oldptr->size -8); // why -8 dont fail test?!?
329
		memcpy(newptr, (char*)oldptr +8, oldptr->size -8); // why forgeting -8 dont fail test?!?
199
		wtfree((char*)oldptr +8);
330
		wtfree((char*)oldptr +8);
200
		return newptr;
331
		return newptr;
201
	}
332
	}
202
	
333
	
203
	return NULL;
334
	return NULL;
204
}	
335
}	
205
 
336
 
206
void* wtcalloc( size_t num, size_t size )
337
void* wtcalloc( size_t num, size_t size )
207
{
338
{
208
	void *newptr = wtmalloc(num * size);
339
	void *newptr = wtmalloc(num * size);
209
	if (newptr)
340
	if (newptr)
210
		memset(newptr, 0, num * size);
341
		memset(newptr, 0, num * size);
211
	return newptr;
342
	return newptr;
212
}
343
}
213
 
344
 
214
 
345
 
215
 
346
 
216
 
347
 
217
int wtmalloc_freelist_check()
348
int wtmalloc_freelist_check()
218
//контроль целостности списка фри OK == 1
349
//контроль целостности списка фри OK == 1
219
{
350
{
220
	int cnt = 0;
351
	int cnt = 0;
221
	struct hdrfree *ptr = __firstfree;
352
	struct hdrfree *ptr = __firstfree;
222
	
353
	
223
	if(ptr && ptr->prev)
354
	if(ptr && ptr->prev)
224
	{
355
	{
225
		TRACE1("allocated memory freelist 1st block fail, ptr = %x\n", ptr);
356
		TRACE1("allocated memory freelist 1st block fail, ptr = %x\n", ptr);
226
		return 0;
357
		return 0;
227
	}
358
	}
228
	
359
	
229
	for(;ptr; ptr = ptr->next)
360
	for(;ptr; ptr = ptr->next)
230
	{
361
	{
231
//TRACE1("(%x)", ptr);
362
//TRACE1("(%x)", ptr);
232
 
363
 
233
		cnt++;
364
		cnt++;
234
		if (ptr->mark != c_free)
365
		if (ptr->mark != c_free)
235
		{
366
		{
236
			TRACE1("allocated memory freelist check fail, ptr = %x\n", ptr);
367
			TRACE1("allocated memory freelist check fail, ptr = %x\n", ptr);
237
			return 0;
368
			return 0;
238
		}
369
		}
239
	}
370
	}
240
	if (cnt != __crtfreeblocks)
371
	if (cnt != wtalloc_stat.crtfreeblocks)
241
	{
372
	{
242
		TRACE1("allocated memory freelist check fail, length must be = %u\n", __crtfreeblocks);
373
		TRACE2("allocated memory freelist check fail, length must be = %u but is %u\n", wtalloc_stat.crtfreeblocks, cnt);
243
		return 0;
374
		return 0;
244
	}
375
	}
245
	return 1;	
376
	return 1;	
246
}
377
}
-
 
378
 
-
 
379
void wtmalloc_freelist_print()
-
 
380
{
-
 
381
	struct hdrfree *ptr = __firstfree;
-
 
382
	for(;ptr; ptr = ptr->next)
-
 
383
	{
-
 
384
		TRACE2("(%x[%u])", ptr, ptr->size);
-
 
385
	}
-
 
386
	TRACE1("\n", 0);
-
 
387
	
-
 
388
}
247
 
389
 
248
int wtmalloc_poiner_check(void *ptr)
390
int wtmalloc_poiner_check(void *ptr)
249
//контроль указателя - mark  OK == 1
391
//контроль указателя - mark  OK == 1
250
{
392
{
251
	if (((struct hdrused*)((char*)ptr - 8))->mark != c_used)
393
	if (((struct hdrused*)((char*)ptr - 8))->mark != c_used)
252
	{
394
	{
253
		TRACE2("pointer watermark check fail ptr = %x bytes EIP@%x\n", ptr, CALLEDFROM(ptr));
395
		TRACE2("pointer watermark check fail ptr = %x bytes EIP@%x\n", ptr, CALLEDFROM(ptr));
254
		return 0;
396
		return 0;
255
	}
397
	}
256
	return 1;
398
	return 1;
257
}
399
}
-
 
400
 
-
 
401
void wtdump_alloc_stats()
-
 
402
{
-
 
403
		TRACE1("----Watermark allocator stats:----\n", 0);
-
 
404
		TRACE2("allocated %u calls, max of %u bytes\n", wtalloc_stat.malloc_calls, wtalloc_stat.malloc_max);
-
 
405
		TRACE2("total %u bytes, average call %u bytes\n", wtalloc_stat.malloc_sum, wtalloc_stat.malloc_sum / wtalloc_stat.malloc_calls);
-
 
406
		TRACE1("SYSTEM:\n", 0);
-
 
407
		TRACE2("allocated %u calls, max of %u bytes\n", wtalloc_stat.sysalloc_calls, wtalloc_stat.sysalloc_max);
-
 
408
		TRACE2("total %u bytes, average call %u bytes\n", wtalloc_stat.sysalloc_sum, wtalloc_stat.sysalloc_sum / wtalloc_stat.sysalloc_calls);
-
 
409
		TRACE2("free list %u bytes, length %u chunks\n", wtalloc_stat.freeblocks_sum, wtalloc_stat.crtfreeblocks);
-
 
410
}