Subversion Repositories Kolibri OS

Rev

Rev 7520 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 7520 Rev 7537
Line 14... Line 14...
14
 
14
 
Line 15... Line 15...
15
#define UINT_MAX  (4294967295U)
15
#define UINT_MAX  (4294967295U)
16
 
16
 
-
 
17
#ifndef NDEBUG
-
 
18
#include 
-
 
19
#	ifdef __TINYC__
-
 
20
#		include 
-
 
21
#		define TRACE1(s, a) { char buf[400]; sprintf(buf, s, a); debug_out_str(buf); }
17
#ifndef NDEBUG
22
#		define TRACE2(s, a, b) { char buf[400]; sprintf(buf, s, a, b); debug_out_str(buf); }
18
#include 
23
#	else
-
 
24
#		define TRACE1(s, a) printf(s, a)
19
#	define TRACE1(s, a) printf(s, a)
25
#		define TRACE2(s, a, b) printf(s, a, b)
20
#	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
Line -... Line 29...
-
 
29
#	define TRACE2(s, a, b) (void)0
-
 
30
#endif
-
 
31
 
23
#	define TRACE2(s, a, b) (void)0
32
 
24
#endif
33
 
Line 25... Line 34...
25
 
34
 
26
// get address, fromwhere function was called
35
// get address, fromwhere function was called
Line 43... Line 52...
43
 
52
 
44
 
53
 
45
static char *__freebase = NULL; 	// begin of free area
54
static char *__freebase = NULL; 	// begin of free area
-
 
55
static char *__freetop = NULL;		// after last byte of free area
-
 
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;
46
static char *__freetop = NULL;		// after last byte of free area
65
	uint32_t	sysalloc_sum;
-
 
66
	
-
 
67
	uint32_t	crtfreeblocks; // number of free blocks, checking corruptions
Line 47... Line 68...
47
static struct hdrfree *__firstfree = NULL;	// ptr to first node in dual-link list
68
	uint32_t	freeblocks_sum;
48
static unsigned __crtfreeblocks = 0; // number of free blocks, checking corruptions
69
} wtalloc_stat;
49
 
70
 
50
 
71
 
51
void *wtmalloc(size_t sz)
72
void *wtmalloc(size_t sz)
Line -... Line 73...
-
 
73
{
-
 
74
	struct hdrfree *fndnode, *newnode;
-
 
75
	sz = (sizeof(struct hdrused) + sz + 15) & ~15; // align 16bytes
-
 
76
//TRACE1("_call alloc(%d)\n", sz);
-
 
77
 
52
{
78
	//statistics
53
	struct hdrfree *fndnode, *newnode;
79
	wtalloc_stat.malloc_calls++;
54
	sz = (sizeof(struct hdrused) + sz + 15) & ~15; // align 16bytes
80
	if (sz > wtalloc_stat.malloc_max) wtalloc_stat.malloc_max = sz;
55
//TRACE1("_call alloc(%d)\n", sz);
81
	wtalloc_stat.malloc_sum += sz;
56
	
82
	
Line 72... Line 98...
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;
Line 82... Line 109...
82
			
109
			
83
			if (fndnode->next)
110
			if (fndnode->next)
Line 84... Line 111...
84
				fndnode->next->prev = newnode;
111
				fndnode->next->prev = newnode;
85
			
112
			
86
			//перед может быть не нода, а 1й указатель
-
 
87
			if (!fndnode->prev)
-
 
88
				__firstfree = newnode;
113
			//перед может быть не нода, а 1й указатель
-
 
114
			if (fndnode->prev)
-
 
115
				newnode->prev->next = newnode;
89
			else
116
			else
90
				newnode->prev->next = newnode;
117
				__firstfree = newnode;
91
		} else // nothing to split, just exclude
118
		} else // nothing to split, just exclude
Line 92... Line 119...
92
		{
119
		{
-
 
120
//TRACE1("alloc(%d) remove freenode\n", sz);
93
//TRACE1("alloc(%d) remove freenode\n", sz);
121
 
94
 
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;
-
 
98
			//перед может быть не нода, а 1й указатель
-
 
99
			if (!fndnode->prev)
125
				fndnode->next->prev = fndnode->prev;
-
 
126
			//перед может быть не нода, а 1й указатель
-
 
127
			if (fndnode->prev)
100
				__firstfree = fndnode->next;
128
				fndnode->prev->next = fndnode->next;
Line 101... Line 129...
101
			else
129
			else
102
				fndnode->prev->next = fndnode->next;
130
				__firstfree = fndnode->next;
103
		}
131
		}
Line 110... Line 138...
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
 
Line 116... Line 151...
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);
Line 131... Line 166...
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
Line 147... Line 183...
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);
Line -... Line 187...
-
 
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;
Line 153... Line 201...
153
}
201
}
154
 
202
 
155
void wtfree(void *ptr)
203
void wtfree(void *ptr)
Line -... Line 204...
-
 
204
{
-
 
205
	if (!ptr) return;
156
{
206
 
157
	if (!ptr) return;
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
-
 
216
	struct hdrfree *newnode = (struct hdrfree*)((char*)ptr - 8);
-
 
217
	newnode->mark = c_free;
-
 
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);
166
	struct hdrfree *newnode = (struct hdrfree*)((char*)ptr - 8);
288
	wtalloc_stat.crtfreeblocks++;
167
	newnode->mark = c_free;
289
	wtalloc_stat.freeblocks_sum += newnode->size;
168
	//size stays
290
 
169
	newnode->next = __firstfree;
291
	newnode->next = __firstfree;
170
	newnode->prev = NULL;
292
	newnode->prev = NULL;
171
	if (__firstfree)
-
 
172
		__firstfree->prev = newnode;
-
 
173
	__firstfree = newnode;
293
	if (__firstfree)
Line 174... Line 294...
174
	__crtfreeblocks++;
294
		__firstfree->prev = newnode;
175
//TRACE1("free to freenode\n", 0);
295
	__firstfree = newnode;
Line 190... Line 310...
190
	}
310
	}
191
#endif
311
#endif
Line 192... Line 312...
192
 
312
 
Line -... Line 313...
-
 
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;
193
	if (oldptr->size - 8 >= sz) return ptr; // enough room in this block, ex from freelist
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);
Line 200... Line 331...
200
		return newptr;
331
		return newptr;
Line 235... Line 366...
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
}
Line -... Line 378...
-
 
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;
-
 
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);