Rev 864 | Rev 888 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 864 | Rev 886 | ||
---|---|---|---|
Line 11... | Line 11... | ||
11 | link_t adj; |
11 | link_t adj; |
12 | addr_t base; |
12 | addr_t base; |
13 | size_t size; |
13 | size_t size; |
14 | void* parent; |
14 | void* parent; |
15 | u32_t reserved; |
15 | u32_t state; |
16 | }md_t; |
16 | }md_t; |
17 | 17 | ||
Line -... | Line 18... | ||
- | 18 | #define MD_FREE 1 |
|
- | 19 | #define MD_USED 2 |
|
- | 20 | ||
18 | typedef struct { |
21 | typedef struct { |
19 | SPINLOCK_DECLARE(lock); /**< this lock protects everything below */ |
22 | SPINLOCK_DECLARE(lock); /**< this lock protects everything below */ |
Line 20... | Line 23... | ||
20 | 23 | ||
21 | u32_t availmask; |
24 | u32_t availmask; |
- | 25 | link_t free[32]; |
|
- | 26 | ||
22 | link_t list[32]; |
27 | link_t used; |
Line -... | Line 28... | ||
- | 28 | }heap_t; |
|
23 | }heap_t; |
29 | |
24 | 30 | ||
Line -... | Line 31... | ||
- | 31 | slab_cache_t *md_slab; |
|
25 | slab_cache_t *md_slab; |
32 | slab_cache_t *phm_slab; |
26 | slab_cache_t *phm_slab; |
33 | |
Line -... | Line 34... | ||
- | 34 | ||
- | 35 | heap_t lheap; |
|
27 | 36 | heap_t sheap; |
|
28 | heap_t lheap; |
37 | |
Line 29... | Line 38... | ||
29 | heap_t sheap; |
38 | |
30 | 39 | ||
Line 31... | Line 40... | ||
31 | static inline void _set_lmask(count_t idx) |
40 | static inline void _set_lmask(count_t idx) |
32 | { asm volatile ("bts DWORD PTR [_lheap], %0"::"r"(idx):"cc"); } |
41 | { asm volatile ("bts %0, _lheap"::"r"(idx):"cc"); } |
Line 33... | Line 42... | ||
33 | 42 | ||
34 | static inline void _reset_lmask(count_t idx) |
43 | static inline void _reset_lmask(count_t idx) |
Line 35... | Line 44... | ||
35 | { asm volatile ("btr DWORD PTR [_lheap], %0"::"r"(idx):"cc"); } |
44 | { asm volatile ("btr %0, _lheap"::"r"(idx):"cc"); } |
36 | 45 | ||
37 | static inline void _set_smask(count_t idx) |
46 | static inline void _set_smask(count_t idx) |
Line 52... | Line 61... | ||
52 | ASSERT((size & 0x3FFFFF) == 0); |
61 | ASSERT((size & 0x3FFFFF) == 0); |
53 | 62 | ||
Line 54... | Line 63... | ||
54 | for (i = 0; i < 32; i++) |
63 | for (i = 0; i < 32; i++) |
55 | { |
64 | { |
56 | list_initialize(&lheap.list[i]); |
65 | list_initialize(&lheap.free[i]); |
57 | list_initialize(&sheap.list[i]); |
66 | list_initialize(&sheap.free[i]); |
58 | }; |
67 | }; |
Line -... | Line 68... | ||
- | 68 | ||
- | 69 | list_initialize(&lheap.used); |
|
- | 70 | list_initialize(&sheap.used); |
|
- | 71 | ||
59 | 72 | ||
Line 60... | Line 73... | ||
60 | md_slab = slab_cache_create(sizeof(md_t), 32,NULL,NULL,SLAB_CACHE_MAGDEFERRED); |
73 | md_slab = slab_cache_create(sizeof(md_t), 32,NULL,NULL,SLAB_CACHE_MAGDEFERRED); |
Line 61... | Line 74... | ||
61 | 74 | ||
62 | md = (md_t*)slab_alloc(md_slab,0); |
75 | md = (md_t*)slab_alloc(md_slab,0); |
63 | 76 | ||
64 | list_initialize(&md->adj); |
77 | list_initialize(&md->adj); |
65 | md->base = base; |
78 | md->base = base; |
Line 66... | Line 79... | ||
66 | md->size = size; |
79 | md->size = size; |
67 | md->parent = NULL; |
80 | md->parent = NULL; |
68 | md->reserved = 0; |
81 | md->state = MD_FREE; |
Line 69... | Line 82... | ||
69 | 82 | ||
Line 91... | Line 104... | ||
91 | if(mask) |
104 | if(mask) |
92 | { |
105 | { |
93 | if(idx0 == 31) |
106 | if(idx0 == 31) |
94 | { |
107 | { |
95 | md_t *tmp = (md_t*)lheap.list[31].next; |
108 | md_t *tmp = (md_t*)lheap.free[31].next; |
96 | while((link_t*)tmp != &lheap.list[31]) |
109 | while((link_t*)tmp != &lheap.free[31]) |
97 | { |
110 | { |
98 | if(tmp->size >= size) |
111 | if(tmp->size >= size) |
99 | { |
112 | { |
100 | DBG("remove large tmp %x\n", tmp); |
113 | DBG("remove large tmp %x\n", tmp); |
Line 108... | Line 121... | ||
108 | else |
121 | else |
109 | { |
122 | { |
110 | idx0 = _bsf(mask); |
123 | idx0 = _bsf(mask); |
111 | 124 | ||
Line 112... | Line 125... | ||
112 | ASSERT( !list_empty(&lheap.list[idx0])) |
125 | ASSERT( !list_empty(&lheap.free[idx0])) |
Line 113... | Line 126... | ||
113 | 126 | ||
114 | md = (md_t*)lheap.list[idx0].next; |
127 | md = (md_t*)lheap.free[idx0].next; |
115 | }; |
128 | }; |
116 | } |
129 | } |
117 | else |
130 | else |
Line -... | Line 131... | ||
- | 131 | return NULL; |
|
- | 132 | ||
118 | return NULL; |
133 | ASSERT(md->state == MD_FREE); |
119 | 134 | ||
120 | list_remove((link_t*)md); |
135 | list_remove((link_t*)md); |
Line 121... | Line 136... | ||
121 | if(list_empty(&lheap.list[idx0])) |
136 | if(list_empty(&lheap.free[idx0])) |
122 | _reset_lmask(idx0); |
137 | _reset_lmask(idx0); |
123 | 138 | ||
124 | if(md->size > size) |
139 | if(md->size > size) |
Line 125... | Line 140... | ||
125 | { |
140 | { |
126 | count_t idx1; |
141 | count_t idx1; |
Line 127... | Line 142... | ||
127 | md_t *new_md = (md_t*)slab_alloc(md_slab,0); |
142 | md_t *new_md = (md_t*)slab_alloc(md_slab,0); /* FIXME check */ |
128 | 143 | ||
- | 144 | link_initialize(&new_md->link); |
|
Line 129... | Line 145... | ||
129 | link_initialize(&new_md->link); |
145 | list_insert(&new_md->adj, &md->adj); |
130 | list_insert(&new_md->adj, &md->adj); |
146 | |
Line 131... | Line 147... | ||
131 | 147 | new_md->base = md->base; |
|
Line 132... | Line 148... | ||
132 | new_md->base = md->base; |
148 | new_md->size = size; |
133 | new_md->size = size; |
149 | new_md->state = MD_USED; |
Line 134... | Line 150... | ||
134 | 150 | ||
135 | md->base+= size; |
151 | md->base+= size; |
- | 152 | md->size-= size; |
|
- | 153 | ||
136 | md->size-= size; |
154 | idx1 = (md->size>>22) - 1 < 32 ? (md->size>>22) - 1 : 31; |
137 | 155 | ||
Line 138... | Line 156... | ||
138 | idx1 = (md->size>>22) - 1 < 32 ? (md->size>>22) - 1 : 31; |
156 | list_prepend(&md->link, &lheap.free[idx1]); |
139 | 157 | _set_lmask(idx1); |
|
Line 166... | Line 184... | ||
166 | if(mask) |
184 | if(mask) |
167 | { |
185 | { |
168 | if(idx0 == 31) |
186 | if(idx0 == 31) |
169 | { |
187 | { |
- | 188 | ASSERT( !list_empty(&sheap.free[31])); |
|
- | 189 | ||
170 | md_t *tmp = (md_t*)sheap.list[31].next; |
190 | md_t *tmp = (md_t*)sheap.free[31].next; |
171 | while((link_t*)tmp != &sheap.list[31]) |
191 | while((link_t*)tmp != &sheap.free[31]) |
172 | { |
192 | { |
173 | if(tmp->size >= size) |
193 | if(tmp->size >= size) |
174 | { |
194 | { |
175 | md = tmp; |
195 | md = tmp; |
176 | break; |
196 | break; |
Line 180... | Line 200... | ||
180 | } |
200 | } |
181 | else |
201 | else |
182 | { |
202 | { |
183 | idx0 = _bsf(mask); |
203 | idx0 = _bsf(mask); |
184 | ASSERT( !list_empty(&sheap.list[idx0])) |
204 | |
- | 205 | ASSERT( !list_empty(&sheap.free[idx0])); |
|
185 | md = (md_t*)sheap.list[idx0].next; |
206 | |
- | 207 | md = (md_t*)sheap.free[idx0].next; |
|
186 | } |
208 | } |
187 | }; |
209 | }; |
188 | 210 | ||
Line 189... | Line 211... | ||
189 | if(md) |
211 | if(md) |
190 | { |
212 | { |
191 | DBG("remove md %x\n", md); |
213 | DBG("remove md %x\n", md); |
Line -... | Line 214... | ||
- | 214 | ||
- | 215 | ASSERT(md->state==MD_FREE); |
|
192 | 216 | ||
193 | list_remove((link_t*)md); |
217 | list_remove((link_t*)md); |
194 | if(list_empty(&sheap.list[idx0])) |
218 | if(list_empty(&sheap.free[idx0])) |
195 | _reset_smask(idx0); |
219 | _reset_smask(idx0); |
196 | } |
220 | } |
197 | else |
221 | else |
198 | { |
222 | { |
Line 206... | Line 230... | ||
206 | safe_sti(efl); |
230 | safe_sti(efl); |
207 | return NULL; |
231 | return NULL; |
208 | }; |
232 | }; |
209 | 233 | ||
Line 210... | Line 234... | ||
210 | md = (md_t*)slab_alloc(md_slab,0); |
234 | md = (md_t*)slab_alloc(md_slab,0); /* FIXME check */ |
- | 235 | ||
211 | link_initialize(&md->link); |
236 | link_initialize(&md->link); |
212 | list_initialize(&md->adj); |
237 | list_initialize(&md->adj); |
213 | md->base = lmd->base; |
238 | md->base = lmd->base; |
214 | md->size = lmd->size; |
239 | md->size = lmd->size; |
215 | md->parent = lmd; |
240 | md->parent = lmd; |
216 | md->reserved = 0; |
241 | md->state = MD_USED; |
217 | }; |
242 | }; |
Line 218... | Line 243... | ||
218 | 243 | ||
219 | if(md->size > size) |
244 | if(md->size > size) |
220 | { |
245 | { |
221 | count_t idx1; |
246 | count_t idx1; |
Line 222... | Line 247... | ||
222 | md_t *new_md = (md_t*)slab_alloc(md_slab,0); |
247 | md_t *new_md = (md_t*)slab_alloc(md_slab,0); /* FIXME check */ |
223 | 248 | ||
Line 224... | Line 249... | ||
224 | link_initialize(&new_md->link); |
249 | link_initialize(&new_md->link); |
225 | list_insert(&new_md->adj, &md->adj); |
250 | list_insert(&new_md->adj, &md->adj); |
226 | 251 | ||
227 | new_md->base = md->base; |
252 | new_md->base = md->base; |
Line 228... | Line 253... | ||
228 | new_md->size = size; |
253 | new_md->size = size; |
229 | new_md->parent = md->parent; |
254 | new_md->parent = md->parent; |
- | 255 | new_md->state = MD_USED; |
|
Line 230... | Line 256... | ||
230 | new_md->reserved = 0; |
256 | |
Line 231... | Line 257... | ||
231 | 257 | md->base+= size; |
|
Line 232... | Line 258... | ||
232 | md->base+= size; |
258 | md->size-= size; |
233 | md->size-= size; |
259 | md->state = MD_FREE; |
234 | 260 | ||
235 | idx1 = (md->size>>12) - 1 < 32 ? (md->size>>12) - 1 : 31; |
261 | idx1 = (md->size>>12) - 1 < 32 ? (md->size>>12) - 1 : 31; |
236 | 262 | ||
237 | DBG("insert md %x, base %x size %x idx %x\n", md,md->base, md->size,idx1); |
263 | DBG("insert md %x, base %x size %x idx %x\n", md,md->base, md->size,idx1); |
238 | 264 | ||
239 | if( idx1 < 31) |
265 | if( idx1 < 31) |
240 | list_prepend(&md->link, &sheap.list[idx1]); |
266 | list_prepend(&md->link, &sheap.free[idx1]); |
Line 241... | Line 267... | ||
241 | else |
267 | else |
242 | { |
268 | { |
243 | if( list_empty(&sheap.list[31])) |
269 | if( list_empty(&sheap.free[31])) |
244 | list_prepend(&md->link, &sheap.list[31]); |
270 | list_prepend(&md->link, &sheap.free[31]); |
245 | else |
271 | else |
246 | { |
272 | { |
Line 260... | Line 286... | ||
260 | 286 | ||
Line 261... | Line 287... | ||
261 | safe_sti(efl); |
287 | safe_sti(efl); |
Line 262... | Line 288... | ||
262 | 288 | ||
263 | return new_md; |
289 | return new_md; |
- | 290 | }; |
|
- | 291 | ||
- | 292 | md->state = MD_USED; |
|
264 | } |
293 | |
- | 294 | safe_sti(efl); |
|
265 | safe_sti(efl); |
295 | |
266 | return md; |
296 | return md; |
Line -... | Line 297... | ||
- | 297 | } |
|
- | 298 | ||
- | 299 | void __fastcall free_small_md(md_t *md) |
|
- | 300 | { |
|
- | 301 | eflags_t efl ; |
|
- | 302 | md_t *fd; |
|
- | 303 | md_t *bk; |
|
- | 304 | count_t idx; |
|
- | 305 | ||
- | 306 | efl = safe_cli(); |
|
- | 307 | spinlock_lock(&sheap.lock); |
|
- | 308 | ||
- | 309 | if( !list_empty(&md->adj)) |
|
- | 310 | { |
|
- | 311 | bk = (md_t*)md->adj.prev; |
|
- | 312 | fd = (md_t*)md->adj.next; |
|
- | 313 | ||
- | 314 | if(fd->state == MD_FREE) |
|
- | 315 | { |
|
- | 316 | idx = (fd->size>>12) - 1 < 32 ? (fd->size>>12) - 1 : 31; |
|
- | 317 | ||
- | 318 | list_remove((link_t*)fd); |
|
- | 319 | if(list_empty(&sheap.free[idx])) |
|
- | 320 | _reset_smask(idx); |
|
- | 321 | ||
- | 322 | md->size+= fd->size; |
|
- | 323 | md->adj.next = fd->adj.next; |
|
- | 324 | md->adj.next->prev = (link_t*)md; |
|
- | 325 | slab_free(md_slab, fd); |
|
- | 326 | }; |
|
- | 327 | if(bk->state == MD_FREE) |
|
- | 328 | { |
|
- | 329 | idx = (bk->size>>12) - 1 < 32 ? (bk->size>>12) - 1 : 31; |
|
- | 330 | ||
- | 331 | list_remove((link_t*)bk); |
|
- | 332 | if(list_empty(&sheap.free[idx])) |
|
- | 333 | _reset_smask(idx); |
|
- | 334 | ||
- | 335 | bk->size+= md->size; |
|
- | 336 | bk->adj.next = md->adj.next; |
|
- | 337 | bk->adj.next->prev = (link_t*)bk; |
|
- | 338 | slab_free(md_slab, md); |
|
- | 339 | md = fd; |
|
- | 340 | }; |
|
- | 341 | }; |
|
- | 342 | ||
- | 343 | md->state = MD_FREE; |
|
- | 344 | ||
- | 345 | idx = (md->size>>12) - 1 < 32 ? (md->size>>12) - 1 : 31; |
|
- | 346 | ||
- | 347 | _set_smask(idx); |
|
- | 348 | ||
- | 349 | if( idx < 31) |
|
- | 350 | list_prepend(&md->link, &sheap.free[idx]); |
|
- | 351 | else |
|
- | 352 | { |
|
- | 353 | if( list_empty(&sheap.free[31])) |
|
- | 354 | list_prepend(&md->link, &sheap.free[31]); |
|
- | 355 | else |
|
- | 356 | { |
|
- | 357 | md_t *tmp = (md_t*)sheap.free[31].next; |
|
- | 358 | ||
- | 359 | while((link_t*)tmp != &sheap.free[31]) |
|
- | 360 | { |
|
- | 361 | if(md->base < tmp->base) |
|
- | 362 | break; |
|
- | 363 | tmp = (md_t*)tmp->link.next; |
|
- | 364 | } |
|
- | 365 | list_insert(&md->link, &tmp->link); |
|
- | 366 | }; |
|
- | 367 | }; |
|
- | 368 | spinlock_unlock(&sheap.lock); |
|
- | 369 | safe_sti(efl); |
|
- | 370 | ||
- | 371 | }; |
|
- | 372 | ||
- | 373 | ||
- | 374 | #define page_tabs 0xDF800000 |
|
267 | } |
375 | |
268 | 376 | /* |
|
269 | phismem_t* __fastcall phis_alloc(count_t count) |
377 | phismem_t* __fastcall phis_alloc(count_t count) |
270 | { |
378 | { |
271 | phismem_t *phm; |
379 | phismem_t *phm; |
Line 287... | Line 395... | ||
287 | 395 | ||
Line 288... | Line 396... | ||
288 | return phm; |
396 | return phm; |
289 | } |
397 | } |
Line 290... | Line -... | ||
290 | - | ||
291 | #define page_tabs 0xDF800000 |
- | |
292 | 398 | ||
293 | void map_phm(addr_t base, phismem_t *phm, u32_t mapflags) |
399 | void map_phm(addr_t base, phismem_t *phm, u32_t mapflags) |
294 | { |
400 | { |
295 | count_t count; |
401 | count_t count; |
Line 315... | Line 421... | ||
315 | frame+= 4096; |
421 | frame+= 4096; |
316 | } |
422 | } |
317 | } |
423 | } |
318 | }; |
424 | }; |
319 | 425 | */ |
|
- | 426 | ||
Line 320... | Line 427... | ||
320 | void* __fastcall mem_alloc(size_t size, u32_t flags) |
427 | void * __fastcall mem_alloc(size_t size, u32_t flags) |
321 | { |
428 | { |
322 | md_t *md; |
- | |
323 | phismem_t *phm; |
429 | eflags_t efl; |
Line 324... | Line 430... | ||
324 | 430 | ||
Line 325... | Line -... | ||
325 | size = (size+4095)&~4095; |
- | |
326 | - | ||
327 | md = find_small_md(size); |
- | |
328 | if( md ) |
- | |
329 | { |
431 | md_t *md; |
330 | phm = phis_alloc(size>>12); |
- | |
331 | map_phm(md->base , phm, flags); |
- | |
332 | return (void*)md->base; |
- | |
333 | } |
- | |
Line 334... | Line -... | ||
334 | return NULL; |
- | |
335 | }; |
- | |
336 | 432 | ||
Line 337... | Line 433... | ||
337 | void * __fastcall heap_alloc(size_t size, u32_t flags) |
433 | DBG("\nmem_alloc: %x bytes\n", size); |
Line 338... | Line 434... | ||
338 | { |
434 | |
Line 339... | Line 435... | ||
339 | md_t *md; |
435 | ASSERT(size != 0); |
340 | 436 | ||
- | 437 | size = (size+4095)&~4095; |
|
- | 438 | ||
341 | size = (size+4095)&~4095; |
439 | md = find_small_md(size); |
342 | 440 | ||
343 | md = find_small_md(size); |
441 | if( md ) |
344 | 442 | { |
|
Line 354... | Line 452... | ||
354 | u32_t order; |
452 | u32_t order; |
355 | addr_t frame; |
453 | addr_t frame; |
356 | size_t size; |
454 | size_t size; |
357 | 455 | ||
Line 358... | Line 456... | ||
358 | asm volatile ("bsr %0, %1":"=&r"(order):"r"(tmp):"cc"); |
456 | asm volatile ("bsr %1, %0":"=&r"(order):"r"(tmp):"cc"); |
359 | asm volatile ("btr %0, %1" :"=r"(tmp):"r"(order):"cc"); |
457 | asm volatile ("btr %1, %0" :"=r"(tmp):"r"(order):"cc"); |
Line 360... | Line 458... | ||
360 | 458 | ||
Line 361... | Line 459... | ||
361 | frame = core_alloc(order) | flags; |
459 | frame = core_alloc(order) | flags; /* FIXME check */ |
362 | 460 | ||
363 | size = (1 << order); |
461 | size = (1 << order); |
364 | while(size--) |
462 | while(size--) |
365 | { |
463 | { |
366 | *pte++ = frame; |
464 | *pte++ = frame; |
367 | frame+= 4096; |
465 | frame+= 4096; |
368 | }; |
466 | }; |
- | 467 | }; |
|
- | 468 | }; |
|
- | 469 | ||
- | 470 | efl = safe_cli(); |
|
- | 471 | spinlock_lock(&sheap.lock); |
|
- | 472 | ||
- | 473 | if( list_empty(&sheap.used) ) |
|
- | 474 | list_prepend(&md->link, &sheap.used); |
|
- | 475 | else |
|
- | 476 | { |
|
- | 477 | md_t *tmp = (md_t*)sheap.used.next; |
|
- | 478 | ||
- | 479 | while((link_t*)tmp != &sheap.used) |
|
- | 480 | { |
|
- | 481 | if(md->base < tmp->base) |
|
- | 482 | break; |
|
- | 483 | tmp = (md_t*)tmp->link.next; |
|
- | 484 | } |
|
- | 485 | list_insert(&md->link, &tmp->link); |
|
- | 486 | }; |
|
- | 487 | ||
- | 488 | spinlock_unlock(&sheap.lock); |
|
369 | }; |
489 | safe_sti(efl); |
370 | }; |
490 | |
371 | DBG("alloc_heap: %x size %x\n\n",md->base, size); |
491 | DBG("allocate: %x size %x\n\n",md->base, size); |
372 | return (void*)md->base; |
492 | return (void*)md->base; |
373 | }; |
493 | }; |
Line -... | Line 494... | ||
- | 494 | return NULL; |
|
- | 495 | }; |
|
- | 496 | ||
- | 497 | void __fastcall mem_free(void *mem) |
|
- | 498 | { |
|
- | 499 | eflags_t efl; |
|
- | 500 | ||
- | 501 | md_t *tmp; |
|
- | 502 | md_t *md = NULL; |
|
- | 503 | ||
- | 504 | DBG("mem_free: %x\n",mem); |
|
- | 505 | ||
- | 506 | ASSERT( mem != 0 ); |
|
- | 507 | ASSERT( ((addr_t)mem & 0xFFF) == 0 ); |
|
- | 508 | ASSERT( ! list_empty(&sheap.used)); |
|
- | 509 | ||
- | 510 | efl = safe_cli(); |
|
- | 511 | ||
- | 512 | tmp = (md_t*)sheap.used.next; |
|
- | 513 | ||
- | 514 | while((link_t*)tmp != &sheap.used) |
|
- | 515 | { |
|
- | 516 | if( tmp->base == (addr_t)mem ) |
|
- | 517 | { |
|
- | 518 | md = tmp; |
|
- | 519 | break; |
|
Line -... | Line 520... | ||
- | 520 | }; |
|
- | 521 | tmp = (md_t*)tmp->link.next; |
|
- | 522 | } |
|
- | 523 | ||
- | 524 | if( md ) |
|
- | 525 | { |
|
- | 526 | DBG("\tmd: %x base: %x size: %x\n",md, md->base, md->size); |
|
- | 527 | ||
- | 528 | ASSERT(md->state == MD_USED); |
|
- | 529 | ||
- | 530 | count_t tmp = md->size >> 12; |
|
- | 531 | addr_t *pte = &((addr_t*)page_tabs)[md->base>>12]; |
|
- | 532 | ||
- | 533 | while(tmp--) |
|
- | 534 | { |
|
- | 535 | *pte++ = 0; |
|
- | 536 | asm volatile ( |
|
- | 537 | "invlpg (%0)" |
|
- | 538 | : |
|
- | 539 | :"r" (mem) ); |
|
- | 540 | mem+= 4096; |
|
- | 541 | }; |
|
- | 542 | list_remove((link_t*)md); |
|
- | 543 | free_small_md( md ); |
|
- | 544 | } |
|
- | 545 | else |
|
- | 546 | { |
|
- | 547 | DBG("\tERROR: invalid base address: %x\n", mem); |