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 | }>> |