12#include "irx_imports.h"
17IRX_ID(
"Heap_lib", 1, 1);
37 void *chunk_validation_key;
46 void *heap_validation_key;
52int _start(
int ac,
char **av)
57 return RegisterLibraryEntries(&_exp_heaplib);
69 return ll->next == ll;
75 ll->next->prev = ll->prev;
76 ll->prev->next = ll->next;
82 return ll->prev == ll->next;
89 ll2->prev = ll1->prev;
91 ll2->prev->next = ll2;
94void HeapPrepare(
void *mem,
int size)
103 if ( (
unsigned int)size >= 0x29 )
105 unsigned int calc_size;
107 chunk->chunk_validation_key = (((u8 *)chunk) - 1);
108 calc_size = (
unsigned int)(size - 16) >> 3;
109 calc_size_blks = calc_size - 1;
111 chunk->free_size = size;
112 chunk->chunk_fragment_prev = &chunk->fragment;
113 chunk->used_size = 0;
114 chunk->fragment.chunk_size_blks = calc_size_blks;
115 chunk->fragment.next_fragment = item;
116 item->chunk_size_blks = 0;
117 chunk->fragment.next_fragment->next_fragment = &chunk->fragment;
122void *heaplib_13_chunk_do_allocate(
heaplib_chunk_t *chunk,
unsigned int nbytes)
133 if ( !chunk || chunk->chunk_validation_key != (((u8 *)chunk) - 1) )
135 size_calc1 = nbytes + 7;
138 chunkfrag_prev_1 = chunk->chunk_fragment_prev;
139 size_calc2 = (size_calc1 >> 3) + 1;
140 chunkfrag_prev_2 = chunk->chunk_fragment_prev;
141 for ( fragment1 = chunkfrag_prev_2->next_fragment;; fragment1 = fragment1->next_fragment )
143 chunk_size_blks = fragment1->chunk_size_blks;
144 if ( (
int)chunk_size_blks >= (int)size_calc2 )
146 chunkfrag_prev_2 = fragment1;
147 if ( fragment1 == chunkfrag_prev_1 )
150 size_subtract = chunk_size_blks - size_calc2;
151 if ( chunk_size_blks == size_calc2 )
153 chunkfrag_prev_2->next_fragment = fragment1->next_fragment;
157 fragment1->chunk_size_blks = size_subtract;
158 fragment1 += size_subtract;
159 fragment1->chunk_size_blks = size_calc2;
161 chunk->chunk_fragment_prev = chunkfrag_prev_2;
163 result = fragment1->payload;
164 chunk->used_size += fragment1->chunk_size_blks;
174 u32 chunk_size_blks2;
176 if ( !chunk || chunk->chunk_validation_key != (((u8 *)chunk) - 1) )
181 if ( *((
heaplib_chunk_t **)ptr - 2) != chunk || (int)chunk_header->chunk_size_blks <= 0 )
186 fragment1 = chunk->chunk_fragment_prev;
187 if ( fragment1 >= chunk_header || chunk_header >= fragment1->next_fragment )
189 while ( chunk_header != fragment1 )
191 fragment2 = fragment1->next_fragment;
192 if ( fragment1 < fragment1->next_fragment )
194 if ( chunk_header < fragment1->next_fragment )
196 if ( fragment1 >= chunk_header )
199 fragment1 = fragment1->next_fragment;
200 if ( fragment2 >= chunk_header || chunk_header >= fragment2->next_fragment )
203 if ( chunk_header >= fragment1->next_fragment )
210 if ( fragment1->next_fragment < &chunk_header[chunk_header->chunk_size_blks] )
213 if ( fragment1 < chunk_header && chunk_header < &fragment1[fragment1->chunk_size_blks] )
215 chunk->used_size -= chunk_header->chunk_size_blks;
216 next_chunk = &chunk_header[chunk_header->chunk_size_blks];
218 next_chunk != fragment1->next_fragment
219 || (chunk_size_blks2 = next_chunk->chunk_size_blks, (
int)chunk_size_blks2 <= 0) )
221 chunk_header->next_fragment = fragment1->next_fragment;
225 chunk_header->chunk_size_blks += chunk_size_blks2;
226 chunk_header->next_fragment = fragment1->next_fragment->next_fragment;
228 if ( chunk_header == &fragment1[fragment1->chunk_size_blks] )
230 fragment1->chunk_size_blks += chunk_header->chunk_size_blks;
231 fragment1->next_fragment = chunk_header->next_fragment;
235 fragment1->next_fragment = chunk_header;
237 chunk->chunk_fragment_prev = fragment1;
243 return chunk && chunk->chunk_validation_key == (((u8 *)chunk) - 1) && chunk->used_size == 0;
246int HeapChunkSize(
void *chunk_)
251 return 8 * (((chunk->free_size - 16) >> 3) - chunk->used_size - 1);
254void *CreateHeap(
int heapblocksize,
int flag)
259 calc_size = 4 * ((heapblocksize + 3) >> 2);
260 heap_new = (
heaplib_heap_t *)AllocSysMemory((flag & 2) != 0, calc_size, 0);
263 heap_new->heap_validation_key = (((u8 *)heap_new) + 1);
264 if ( (flag & 1) != 0 )
265 heap_new->size2free_flags = calc_size;
267 heap_new->size2free_flags = 0;
268 heap_new->size2free_flags |= ((
unsigned int)flag >> 1) & 1;
269 linked_list_set_self(&heap_new->l);
270 HeapPrepare(&heap_new->mem_chunk, calc_size - 16);
276void DeleteHeap(
void *heap_)
283 if ( heap->heap_validation_key == (
char *)&heap->heap_validation_key + 1 )
286 heap->heap_validation_key = 0;
287 if ( item != &heap->l )
292 *(u32 *)item->payload = 0;
295 }
while ( next != &heap->l );
297 heap->mem_chunk.chunk_validation_key = 0;
302void *AllocHeapMemory(
void *heap_,
size_t nbytes)
315 if ( heap->heap_validation_key != (((u8 *)heap) + 1) )
323 result = heaplib_13_chunk_do_allocate(heap_item, nbytes);
328 size2free_flags = heap->size2free_flags;
329 if ( size2free_flags >= 4 )
331 size_rounded = 2 * (size2free_flags >> 1);
332 if ( (
int)(size_rounded - 40) < (
int)(nbytes) )
333 size_rounded = nbytes + 40;
334 heap_new = (
heaplib_ll_t *)AllocSysMemory(heap->size2free_flags & 1, size_rounded, 0);
337 BlockSize = QueryBlockSize(heap_new);
338 linked_list_add_after(heap->l.next, heap_new);
340 HeapPrepare(payload, BlockSize - 8);
341 return heaplib_13_chunk_do_allocate(payload, nbytes);
351int FreeHeapMemory(
void *heap_,
void *ptr)
362 if ( heap->heap_validation_key != (((u8 *)heap) + 1) )
365 for ( chunk_item = (
heaplib_chunk_t *)item->payload; heaplib_14_chunk_do_iterate(chunk_item, ptr);
372 if ( item !=
list_head && heaplib_12_chunk_is_valid(chunk_item) != 0 )
374 linked_list_remove(item);
375 *(u32 *)item->payload = 0;
381int HeapTotalFreeSize(
void *heap_)
393 if ( heap->heap_validation_key != (((u8 *)heap) + 1) )
395 for ( chunk_item = heap->l.next;; chunk_item = chunk_item->next )