heap_t *create_heap(uint32_t start, uint32_t end_addr, uint32_t max, bool supervisor, bool readonly) { heap_t *heap = (heap_t *) kmalloc(sizeof(heap_t)); // All our assumptions are made on startAddress and endAddress being page-aligned. ASSERT(start % 0x1000 == 0); ASSERT(end_addr % 0x1000 == 0); // Initialise the index. heap->index = place_ordered_array((void*) start, HEAP_INDEX_SIZE, &header_t_less_than); // Shift the start address forward to resemble where we can start putting data. start += sizeof(type_t) * HEAP_INDEX_SIZE; // Make sure the start address is page-aligned. if((start & 0xFFFFF000) != 0) { start &= 0xFFFFF000; start += 0x1000; } // Write the start, end and max addresses into the heap structure. heap->start_address = start; heap->end_address = end_addr; heap->max_address = max; heap->supervisor = supervisor; heap->readonly = readonly; // We start off with one large hole in the index. header_t *hole = (header_t *)start; hole->size = end_addr-start; hole->magic = HEAP_MAGIC; hole->is_hole = 1; insert_ordered_array((void*) hole, &heap->index); return heap; }
heap_t* create_heap(u32int start, u32int end, u32int max) { heap_t *heap = (heap_t *)kmalloc(sizeof(heap_t)); ASSERT(start % 0x1000 == 0); ASSERT(end % 0x1000 == 0); heap->index = place_ordered_array((void *)start, HEAP_INDEX_SIZE, header_less_than); start += sizeof(type_t) * HEAP_INDEX_SIZE; if (start & ~0xfffff000) { start &= 0xfffff000; start += 0x1000; } heap->start_address = start; heap->end_address = end; heap->max_address = max; header_t *hole = (header_t *)start; hole->size = end - start; hole->magic = HEAP_MAGIC; hole->is_hole = 1; insert_ordered_array((type_t)hole, &heap->index); return heap; }
heap* create_heap(u32int start, u32int end_addr) { heap* h = (heap*)start; // Initialise the index. h->index = create_ordered_array((void*)(start + sizeof(heap)), HEAP_INDEX_SIZE); // Shift the start address forward to resemble where we can start putting data. start += sizeof (u32int*)*HEAP_INDEX_SIZE + sizeof(heap); // Write the start, end and max addresses into the heap structure. h->start_address = start; h->end_address = end_addr; // We start off with one large hole in the index. header *hole = (header*) start; hole->size = end_addr - start; hole->magic = HEAP_MAGIC; hole->is_hole = 1; footer *foot = (footer*)(start + end_addr - start - sizeof(footer)); foot->head = hole; foot->magic = HEAP_MAGIC; insert_ordered_array((u32int) hole, &h->index); return h; }
void free(void* p, heap* h) { // Exit gracefully for null pointers. if (p == NULL) return; // Get the header and footer associated with this pointer. header *head = (header*) ((u32int) p - sizeof (header)); footer *foot = (footer*) ((u32int) head + head->size - sizeof (footer)); // Sanity checks. if(!(head->magic == HEAP_MAGIC && foot->magic == HEAP_MAGIC)) { print_msg("Memory error\n"); return; } // Make us a hole. head->is_hole = 1; // Do we want to add this head into the 'free holes' index? char do_add = 1; // Unify left // If the thing immediately to the left of us is a foot... footer *test_foot = (footer*) ((u32int) head - sizeof (footer)); if (test_foot->magic == HEAP_MAGIC && test_foot->head->is_hole) { u32int cache_size = head->size; // Cache our current size. head = test_foot->head; // Rewrite our head with the new one. foot->head = head; // Rewrite our foot to point to the new head. head->size += cache_size; // Change the size. do_add = 0; // Since this head is already in the index, we don't want to add it again. } // Unify right // If the thing immediately to the right of us is a head... header *test_head = (header*) ((u32int) foot + sizeof (footer)); if (test_head->magic == HEAP_MAGIC && test_head->is_hole) { head->size += test_head->size; // Increase our size. test_foot = (footer*) ((u32int) test_head + // Rewrite it's foot to point to our head. test_head->size - sizeof (footer)); test_foot->head = head; // Find and remove this head from the index. u32int iterator = 0; while ((iterator < h->index.size) && (lookup_ordered_array(iterator, &h->index) != (u32int) test_head)) iterator++; // Make sure we actually found the item. if(iterator >= h->index.size) { print_msg("Iterator behind heap size"); return; } // Remove it. remove_ordered_array(iterator, &h->index); } if (do_add == 1) insert_ordered_array((u32int) head, &h->index); }
void* alloc(u32int size, heap* h) { u32int new_size = size + sizeof (header) + sizeof (footer); s32int iterator = find_smallest_hole(new_size, h); if (iterator == -1) // If we didn't find a suitable hole { print_msg("No enough memory space\n"); return NULL; } header *orig_hole_header = (header *) lookup_ordered_array(iterator, &h->index); u32int orig_hole_pos = (u32int) orig_hole_header; u32int orig_hole_size = orig_hole_header->size; // Here we work out if we should split the hole we found into two parts. // Is the original hole size - requested hole size less than the overhead for adding a new hole? if (orig_hole_size - new_size < sizeof (header) + sizeof (footer)) { // Then just increase the requested size to the size of the hole we found. size += orig_hole_size - new_size; new_size = orig_hole_size; } remove_ordered_array(iterator, &h->index); // we make sure all the header and footer attributes are correct, along with magic numbers header *block_header = (header *) orig_hole_pos; block_header->magic = HEAP_MAGIC; block_header->is_hole = 0; block_header->size = new_size; footer *block_footer = (footer *) (orig_hole_pos + sizeof (header) + size); block_footer->magic = HEAP_MAGIC; block_footer->head = block_header; // We may need to write a new hole after the allocated block. // We do this only if the new hole would have positive size... if (orig_hole_size - new_size > 0) { header *hole_header = (header *) (orig_hole_pos + sizeof (header) + size + sizeof (footer)); hole_header->magic = HEAP_MAGIC; hole_header->is_hole = 1; hole_header->size = orig_hole_size - new_size; footer *hole_footer = (footer *) ((u32int) hole_header + orig_hole_size - new_size - sizeof (footer)); if ((u32int) hole_footer < h->end_address) { hole_footer->magic = HEAP_MAGIC; hole_footer->head = hole_header; } // Put the new hole in the index; insert_ordered_array((u32int) hole_header, &h->index); } return (void *) ((u32int) block_header + sizeof (header)); }
vmem_heap_t* create_heap(addr start, addr end_addr, addr max, unsigned char supervisor, unsigned char readonly) { struct vmem_heap* heap = (struct vmem_heap*)kmalloc(sizeof(struct vmem_heap)); /* All of our assumptions are made on start and end being page-aligned */ ASSERT(start % 0x1000 == 0); ASSERT(end_addr % 0x1000 == 0); /* Initalize the index */ heap->index = place_ordered_array((void*)start, VMEM_INDEX_SIZE, &vmem_header_less_than); /* Shift the start address forward to resemble where we can start putting data */ start += sizeof(type_t) * VMEM_INDEX_SIZE; /* Make sure the start address is page aligned */ if (start & 0xFFFFF000 != 0) { start &= 0xFFFFF000; start += 0x1000; } /* Write the start, end and max addresses into the heap structure */ heap->start_address = start; heap->end_address = end_addr; heap->max_address = max; heap->supervisor = supervisor; heap->readonly = readonly; /* We start off with one large hole in the index */ struct vmem_header* hole = (struct vmem_header*)start; hole->size = end_addr - start; hole->magic = VMEM_MAGIC; hole->is_hole = 1; insert_ordered_array((void*)hole, &heap->index); return heap; }
heap_t *create_heap(u32 start, u32 end_addr, u32 max, u8 supervisor, u8 readonly) { heap_t *heap = (heap_t *)kmalloc(sizeof(heap_t)); /* Initialize the index */ heap->index = place_ordered_array((void *)start, HEAP_INDEX_SIZE, header_t_less_than); start += HEAP_INDEX_SIZE * sizeof(type_t); heap->start_address = start; heap->end_address = end_addr; heap->max_address = max; heap->supervisor = supervisor; heap->readonly = readonly; /* We start off with one large hole in the index */ header_t *hole = (header_t *)start; hole->size = end_addr - start; hole->magic = HEAP_MAGIC; hole->is_hole = 1; insert_ordered_array((void *)hole, &heap->index); return heap; }
void free(void *p, heap_t *heap) { /* * Exit gracefully for null pointers. */ if (!p) return; /* * Get the header and footer associated with this * pointer. */ header_t *header = (header_t *)((u32)p - sizeof(header_t)); footer_t *footer = (footer_t *)((u32)header + header->size - sizeof(footer_t)); /* * Check the magic numbers of both the header * and footer. If they do not match this is a bogus * pointer passed. */ if (header->magic != HEAP_MAGIC) return; if (footer->magic != HEAP_MAGIC) return; /* * Make us a hole. */ header->is_hole = 1; /* * Do we want to add this header into the "free holes" * index? */ u8 do_add = 1; /* * Unify left. If the thing immediately to the left of us * is a footer. */ footer_t *test_footer = (footer_t *)((u32)header - sizeof(footer_t)); if (test_footer->magic == HEAP_MAGIC && test_footer->header->is_hole) { /* * Cache our current size. */ u32 cache_size = header->size; /* * Rewrite our header with the new one. */ header = test_footer->header; /* * Rewrite our footer to point to the new * header. */ footer->header = header; /* * Change the size of the new header. */ header->size += cache_size; /* * Since this header is already in the index, we dont * want to add it again. */ do_add = 0; } /* * Unify right. If the thing immediately to the right of us * is a header. */ header_t *test_header = (header_t *)((u32)footer + sizeof(footer_t)); if (test_header->magic == HEAP_MAGIC && test_header->is_hole) { /* * Increase our current size. */ header->size += test_header->size; /* * Rewrite its footer to point to our header. */ test_footer = (footer_t *)((u32)test_header + test_header->size - sizeof(footer_t)); footer = test_footer; footer->header = header; /* * Find and remove test_header from the index. */ u32 i = 0; while (i < heap->index.size && lookup_ordered_array(i, &heap->index) != (void *)test_header) i++; /* * Make sure we actually found the item. Error * debugging will be added later. For now just * return. */ if (i == heap->index.size) return; /* * Remove the pointer from the index list. */ remove_ordered_array(i, &heap->index); } /* * If there was no unification, or there was a * unify right, but not left, simply add the block of * memory into the index list. */ if (do_add) insert_ordered_array((void *)header, &heap->index); }
void *alloc(u32 size, u8 page_align, heap_t *heap) { /* * Make sure we take the size of the header/footer * into account. */ u32 new_size = size + sizeof(header_t) + sizeof(footer_t); /* * Find the smallest hole that will fit */ s32 i = find_smallest_hole(new_size, page_align, heap); if (i == -1) { /* * If we didnt find a suitable hole */ u32 old_length = heap->end_address - heap->start_address; u32 old_end_address = heap->end_address; expand(old_length + new_size, heap); u32 new_length = heap->end_address - heap->start_address; /* * Find the endmost header. Not endmost in size, but in * location. */ u32 i = 0, idx = -1, value = 0x0; while (i < heap->index.size) { u32 tmp = (u32)lookup_ordered_array(i, &heap->index); if (tmp > value) { value = tmp; idx = i; } i++; } /* * If we didnt find any headers, we need to add one */ if (idx == -1) { header_t *header = (header_t *)old_end_address; header->magic = HEAP_MAGIC; header->size = new_length - old_length; header->is_hole = 1; footer_t *footer = (footer_t *)(old_end_address + header->size - sizeof(footer_t)); footer->magic = HEAP_MAGIC; footer->header = header; insert_ordered_array((void *)header, &heap->index); } else { /* * The last header needs adjusting */ header_t *header = lookup_ordered_array(idx, &heap->index); header->size += new_length - old_length; /* Rewrite the footer */ footer_t *footer = (footer_t *)((u32)header + header->size - sizeof(footer_t)); footer->header = header; footer->magic = HEAP_MAGIC; } /* * We now have enough space. Recurse call the function * again. */ return alloc(size, page_align, heap); } header_t *orig_hole_header = (header_t *)lookup_ordered_array(i, &heap->index); u32 orig_hole_pos = (u32)orig_hole_header; u32 orig_hole_size = orig_hole_header->size; if (orig_hole_size - new_size < sizeof(header_t) + sizeof(footer_t)) { size += orig_hole_size - new_size; new_size = orig_hole_size; } // If we need to page-align the data, do it now and make a new hole in front of our block. if (page_align && orig_hole_pos&0xFFFFF000) { u32 new_location = orig_hole_pos + 0x1000 /* page size */ - (orig_hole_pos&0xFFF) - sizeof(header_t); header_t *hole_header = (header_t *)orig_hole_pos; hole_header->size = 0x1000 /* page size */ - (orig_hole_pos&0xFFF) - sizeof(header_t); hole_header->magic = HEAP_MAGIC; hole_header->is_hole = 1; footer_t *hole_footer = (footer_t *) ( (u32)new_location - sizeof(footer_t) ); hole_footer->magic = HEAP_MAGIC; hole_footer->header = hole_header; orig_hole_pos = new_location; orig_hole_size = orig_hole_size - hole_header->size; } else { // Else we don't need this hole any more, delete it from the index. remove_ordered_array(i, &heap->index); } header_t *block_header = (header_t *)orig_hole_pos; block_header->magic = HEAP_MAGIC; block_header->is_hole = 0; block_header->size = new_size; footer_t *block_footer = (footer_t *)(orig_hole_pos + sizeof(header_t) + size); block_footer->magic = HEAP_MAGIC; block_footer->header = block_header; /* * We may need to write a new hole after the allocated block. * We do this only if the new hole would have a positive size */ if (orig_hole_size - new_size > 0) { header_t *hole_header = (header_t *)(orig_hole_pos + sizeof(header_t) + size + sizeof(footer_t)); hole_header->magic = HEAP_MAGIC; hole_header->is_hole = 1; hole_header->size = orig_hole_size - new_size; footer_t *hole_footer = (footer_t *)((u32)hole_header + orig_hole_size - new_size - sizeof(footer_t)); hole_footer->magic = HEAP_MAGIC; hole_footer->header = hole_header; if ((u32)hole_footer < heap->end_address) { hole_footer->magic = HEAP_MAGIC; hole_footer->header = hole_header; } /* * Put the new hole into the index. */ insert_ordered_array((void *)hole_header, &heap->index); } return (void *)((u32)block_header + sizeof(header_t)); }
void free(void *p, heap_t *heap) { // Exit gracefully for null pointers. if (p == 0) { return; } // Get the header and footer associated with this pointer. header_t *header = (header_t*) ((uint32_t) p - sizeof(header_t)); footer_t *footer = (footer_t*) ((uint32_t) header + header->size - sizeof(footer_t)); // Sanity checks. ASSERT(header->magic == HEAP_MAGIC); ASSERT(footer->magic == HEAP_MAGIC); // Make us a hole. header->is_hole = 1; // Do we want to add this header into the 'free holes' index? bool do_add = true; // Unify left // If the thing immediately to the left of us is a footer... footer_t *test_footer = (footer_t*) ((uint32_t) header - sizeof(footer_t)); if(test_footer->magic == HEAP_MAGIC && test_footer->header->is_hole == 1) { uint32_t cache_size = header->size; // Cache our current size. header = test_footer->header; // Rewrite our header with the new one. footer->header = header; // Rewrite our footer to point to the new header. header->size += cache_size; // Change the size. do_add = false; // Since this header is already in the index, we don't want to add it again. } // Unify right // If the thing immediately to the right of us is a header... header_t *test_header = (header_t*) ((uint32_t) footer + sizeof(footer_t)); if(test_header->magic == HEAP_MAGIC && test_header->is_hole) { header->size += test_header->size; // Increase our size. // Rewrite its footer to point to our header. test_footer = (footer_t*) ((uint32_t) test_header + test_header->size - sizeof(footer_t)); footer = test_footer; // Find and remove this header from the index. uint32_t iterator = 0; while((iterator < heap->index.size) && (lookup_ordered_array(iterator, &heap->index) != (void*)test_header)) { iterator++; } // Make sure we actually found the item. ASSERT(iterator < heap->index.size); // Remove it. remove_ordered_array(iterator, &heap->index); } /* // If the footer location is the end address, we can contract. if ((uint32_t)footer+sizeof(footer_t) == heap->end_address) { uint32_t old_length = heap->end_address-heap->start_address; uint32_t new_length = contract((uint32_t) header - heap->start_address, heap); // Check how big we will be after resizing. if (header->size - (old_length-new_length) > 0) { // We will still exist, so resize us. header->size -= old_length-new_length; footer = (footer_t*) ((uint32_t) header + header->size - sizeof(footer_t)); footer->magic = HEAP_MAGIC; footer->header = header; } else { // We will no longer exist. Remove us from the index. uint32_t iterator = 0; while ((iterator < heap->index.size) && (lookup_ordered_array(iterator, &heap->index) != (void*) test_header)) { iterator++; } // If we didn't find ourselves, we have nothing to remove. if (iterator < heap->index.size) { remove_ordered_array(iterator, &heap->index); } } }*/ // If required, add us to the index. if(do_add == true) { insert_ordered_array((void*) header, &heap->index); } }
void *alloc(uint32_t size, bool page_align, heap_t *heap) { // Make sure we take the size of header/footer into account. uint32_t new_size = size + sizeof(header_t) + sizeof(footer_t); // Find the smallest hole that will fit. int32_t iterator = find_smallest_hole(new_size, page_align, heap); if (iterator == -1) { // If we didn't find a suitable hole // Save some previous data. uint32_t old_length = heap->end_address - heap->start_address; uint32_t old_end_address = heap->end_address; // We need to allocate some more space. expand(old_length+new_size, heap, size); uint32_t new_length = heap->end_address-heap->start_address; // Find the endmost header. (Not endmost in size, but in location). iterator = 0; // Vars to hold the index of, and value of, the endmost header found so far. uint32_t idx = -1; uint32_t value = 0x0; while(iterator < heap->index.size) { uint32_t tmp = (uint32_t) lookup_ordered_array(iterator, &heap->index); if(tmp > value) { value = tmp; idx = iterator; } iterator++; } // If we didn't find ANY headers, we need to add one. if(idx == -1) { header_t *header = (header_t *)old_end_address; header->magic = HEAP_MAGIC; header->size = new_length - old_length; header->is_hole = 1; footer_t *footer = (footer_t *) (old_end_address + header->size - sizeof(footer_t)); footer->magic = HEAP_MAGIC; footer->header = header; insert_ordered_array((void*) header, &heap->index); } else { // The last header needs adjusting. header_t *header = lookup_ordered_array(idx, &heap->index); header->size += new_length - old_length; // Rewrite the footer. footer_t *footer = (footer_t *) ((uint32_t) header + header->size - sizeof(footer_t)); footer->header = header; footer->magic = HEAP_MAGIC; } // We now have enough space. Recurse, and call the function again. return alloc(size, page_align, heap); } header_t *orig_hole_header = (header_t *) lookup_ordered_array(iterator, &heap->index); uint32_t orig_hole_pos = (uint32_t) orig_hole_header; uint32_t orig_hole_size = orig_hole_header->size; // Here we work out if we should split the hole we found into two parts. // Is the original hole size - requested hole size less than the overhead for adding a new hole? if(orig_hole_size-new_size < sizeof(header_t) + sizeof(footer_t)) { // Then just increase the requested size to the size of the hole we found. size += orig_hole_size-new_size; new_size = orig_hole_size; } // If we need to page-align the data, do it now and make a new hole in front of our block. if(page_align && orig_hole_pos & 0xFFFFF000) { uint32_t new_location = orig_hole_pos + 0x1000 /* page size */ - (orig_hole_pos&0xFFF) - sizeof(header_t); header_t *hole_header = (header_t *)orig_hole_pos; hole_header->size = 0x1000 /* page size */ - (orig_hole_pos&0xFFF) - sizeof(header_t); hole_header->magic = HEAP_MAGIC; hole_header->is_hole = 1; footer_t *hole_footer = (footer_t *) ((uint32_t) new_location - sizeof(footer_t)); hole_footer->magic = HEAP_MAGIC; hole_footer->header = hole_header; orig_hole_pos = new_location; orig_hole_size = orig_hole_size - hole_header->size; } else { // Else we don't need this hole any more, delete it from the index. remove_ordered_array(iterator, &heap->index); } // Overwrite the original header... header_t *block_header = (header_t *)orig_hole_pos; block_header->magic = HEAP_MAGIC; block_header->is_hole = 0; block_header->size = new_size; // ...And the footer footer_t *block_footer = (footer_t *) (orig_hole_pos + sizeof(header_t) + size); block_footer->magic = HEAP_MAGIC; block_footer->header = block_header; // We may need to write a new hole after the allocated block. // We do this only if the new hole would have positive size... if(orig_hole_size - new_size > 0) { header_t *hole_header = (header_t *) (orig_hole_pos + sizeof(header_t) + size + sizeof(footer_t)); hole_header->magic = HEAP_MAGIC; hole_header->is_hole = 1; hole_header->size = orig_hole_size - new_size; footer_t *hole_footer = (footer_t *) ((uint32_t) hole_header + orig_hole_size - new_size - sizeof(footer_t)); if ((uint32_t)hole_footer < heap->end_address) { hole_footer->magic = HEAP_MAGIC; hole_footer->header = hole_header; } // Put the new hole in the index; insert_ordered_array((void*) hole_header, &heap->index); } // ...And we're done! return (void *) ((uint32_t) block_header+sizeof(header_t)); }
void free(void *p, heap_t *heap) { if (!p) return; header_t *header = (header_t *)((u32int)p - sizeof(header_t)); footer_t *footer = (footer_t *)((u32int)header + header->size - sizeof(footer_t)); ASSERT(header->magic == HEAP_MAGIC); ASSERT(footer->magic == HEAP_MAGIC); header->is_hole = 1; char do_add = 1; // Unify left footer_t *test_footer = (footer_t *)((u32int)header - sizeof(footer_t)); if (test_footer->magic == HEAP_MAGIC && test_footer->header->is_hole == 1) { u32int cache_size = header->size; header = test_footer->header; footer->header = header; header->size += cache_size; do_add = 0; } // Unify right header_t *test_header = (header_t *)((u32int)footer + sizeof(footer_t)); if (test_header->magic == HEAP_MAGIC && test_header->is_hole) { header->size += test_header->size; test_footer = (footer_t *)((u32int)test_header + test_header->size - sizeof(footer_t)); footer = test_footer; u32int iterator = 0; while ((iterator < heap->index.size) && (lookup_ordered_array(iterator, &heap->index) != (void *)test_header)) { iterator++; } ASSERT(iterator < heap->index.size); remove_ordered_array(iterator, &heap->index); } if ((u32int)footer + sizeof(footer_t) == heap->end_address) { u32int old_length = heap->end_address - heap->start_address; u32int new_length = contract((u32int)header - heap->start_address, heap); if (header->size - (old_length - new_length) > 0) { header->size -= old_length - new_length; footer = (footer_t *)((u32int)header + header->size - sizeof(footer_t)); footer->magic = HEAP_MAGIC; footer->header = header; } else { u32int iterator = 0; while ((iterator < heap->index.size) && (lookup_ordered_array(iterator, &heap->index) != (void *)test_header)) { iterator++; } if (iterator < heap->index.size) remove_ordered_array(iterator, &heap->index); } } if (do_add) insert_ordered_array((void *)header, &heap->index); }
void* alloc(u32int size, u8int page_align, heap_t *heap) { u32int new_size = size + sizeof(header_t) + sizeof(footer_t); s32int iterator = find_smallest_hole(new_size, page_align, heap); // no suitable hole found if (iterator == -1) { u32int old_length = heap->end_address - heap->start_address; u32int old_end_address = heap->end_address; expand(old_length + new_size, heap); u32int new_length = heap->end_address - heap->start_address; iterator = 0; u32int idx = -1; u32int value = 0x0; while ((u32int)iterator < heap->index.size) { u32int tmp = (u32int)lookup_ordered_array(iterator, &heap->index); if (tmp > value) { value = tmp; idx = iterator; } iterator++; } if ((s32int)idx == -1) { header_t *header = (header_t *)old_end_address; header->magic = HEAP_MAGIC; header->size = new_length - old_length; header->is_hole = 1; footer_t *footer = (footer_t *)(old_end_address + header->size - sizeof(footer_t)); footer->magic = HEAP_MAGIC; footer->header = header; insert_ordered_array((void *)header, &heap->index); } else { header_t *header = lookup_ordered_array(idx, &heap->index); header->size += new_length - old_length; footer_t *footer = (footer_t *)((u32int)header + header->size - sizeof(footer_t)); footer->header = header; footer->magic = HEAP_MAGIC; } return alloc(size, page_align, heap); } header_t *orig_hole_header = (header_t *)lookup_ordered_array(iterator, &heap->index); u32int orig_hole_pos = (u32int)orig_hole_header; u32int orig_hole_size = orig_hole_header->size; if (orig_hole_size - new_size < sizeof(header_t) + sizeof(footer_t)) { size += orig_hole_size - new_size; new_size = orig_hole_size; } if (page_align && orig_hole_pos & ~0xfffff000) { u32int new_location = orig_hole_pos + 0x1000 - (orig_hole_pos & 0xfff) - sizeof(header_t); header_t *hole_header = (header_t *)orig_hole_pos; hole_header->size = 0x1000 - (orig_hole_pos & 0xfff) - sizeof(header_t); hole_header->magic = HEAP_MAGIC; hole_header->is_hole = 1; footer_t *hole_footer = (footer_t *)((u32int)new_location - sizeof(footer_t)); hole_footer->magic = HEAP_MAGIC; hole_footer->header = hole_header; orig_hole_pos = new_location; orig_hole_size -= hole_header->size; } else { remove_ordered_array(iterator, &heap->index); } header_t *block_header = (header_t *)orig_hole_pos; block_header->magic = HEAP_MAGIC; block_header->is_hole = 0; block_header->size = new_size; footer_t *block_footer = (footer_t *)(orig_hole_pos + sizeof(header_t) + size); block_footer->magic = HEAP_MAGIC; block_footer->header = block_header; if (orig_hole_size - new_size > 0) { header_t *hole_header = (header_t *)(orig_hole_pos + sizeof(header_t) + sizeof(footer_t) + size); hole_header->magic = HEAP_MAGIC; hole_header->is_hole = 1; hole_header->size = orig_hole_size - new_size; footer_t *hole_footer = (footer_t *)((u32int)hole_header + orig_hole_size - new_size - sizeof(footer_t)); if ((u32int)hole_footer < heap->end_address) { hole_footer->magic = HEAP_MAGIC; hole_footer->header = hole_header; } insert_ordered_array((void *)hole_header, &heap->index); } return (void *)((u32int)block_header + sizeof(header_t)); }
void vfree(void *p, struct vmem_heap* heap) { /* Exit gracefully for null pointers */ if (p == 0) return; /* Get the header and footer associated with this pointer */ struct vmem_header* header = (struct vmem_header*)((addr)p - sizeof(struct vmem_header)); struct vmem_footer* footer = (struct vmem_footer*)((addr)header + header->size - sizeof(struct vmem_footer)); /* Sanity checks */ ASSERT(header->magic == VMEM_MAGIC); ASSERT(footer->magic == VMEM_MAGIC); /* Make us a hole */ header->is_hole = 0; /* Do we want to add this header to the free holes index */ char do_add = 1; /* Unify left */ struct vmem_footer* test_footer = (struct vmem_footer*)((addr)header - sizeof(struct vmem_footer)); if (test_footer->magic == VMEM_MAGIC && test_footer->header->is_hole == 1) { addr cache_size = header->size; /* Cache our current size */ header = test_footer->header; /* Rewrite our header with the new one */ footer->header = header; /* Rewrite our footer to point to the new header */ header->size += cache_size; /* Change the size */ do_add = 0; /* Since this header is already in the index, we don't want to add it */ } /* Unify right */ struct vmem_header* test_header = (struct vmem_header*)((addr)footer + sizeof(struct vmem_footer)); if (test_header->magic == VMEM_MAGIC && test_header->is_hole) { header->size += test_header->size; /* Increase our size */ test_footer = (struct vmem_footer*)((addr)test_header + test_header->size - sizeof(struct vmem_footer)); footer = test_footer; /* Find and remove this kernel from the index */ unsigned int iterator = 0; while ((iterator < heap->index.size) && (lookup_ordered_array(iterator, &heap->index) != (void*)test_header)) iterator++; /* Make sure we actually found the item */ ASSERT(iterator < heap->index.size); /* Remove it */ remove_ordered_array(iterator, &heap->index); } /* If the footer location is the end address, we can contract */ if ((addr)footer + sizeof(struct vmem_footer) == heap->end_address) { addr old_length = heap->end_address - heap->start_address; addr new_length = contract((addr)header - heap->start_address, heap); /* Check how big we will be after resizing */ if (header->size - (old_length - new_length) > 0) { /* We will still exist, so resize us */ header->size -= old_length - new_length; footer = (struct vmem_footer*)((addr)header + header->size - sizeof(struct vmem_footer)); footer->magic = VMEM_MAGIC; footer->header = header; } else { /* We will no longer exist, remove us from the index */ unsigned int iterator = 0; while ((iterator < heap->index.size) && (lookup_ordered_array(iterator, &heap->index) != (void*)test_header)) iterator++; /* If we didn't find ourselves, we have nothing to remove */ if (iterator < heap->index.size) remove_ordered_array(iterator, &heap->index); } } /* Add ourselves if we need to */ if (do_add == 1) insert_ordered_array((void*)header, &heap->index); }
void* vmalloc(addr size, unsigned char page_align, struct vmem_heap* heap) { /* Make sure we take the size of the header / footer into account */ addr new_size = size + sizeof(struct vmem_header) + sizeof(struct vmem_footer); /* Find the smallest hole that will fit */ signed int iterator = find_smallest_hole(new_size, page_align, heap); if (iterator == -1) /* If we didn't find a suitable hole */ { /* Save some previous data */ addr old_length = heap->end_address - heap->start_address; addr old_end_address = heap->end_address; /* We need to allocate some more space */ expand(old_length + new_size, heap); addr new_length = heap->end_address - heap->start_address; /* Find the endmost header (not endmost in size, but in location) */ iterator = 0; /* Vars to hold the index of, and value of, the endmost header found so far */ addr idx = -1; addr value = 0x0; while (iterator < heap->index.size) { addr tmp = (addr)lookup_ordered_array(iterator, &heap->index); if (tmp > value) { value = tmp; idx = iterator; } iterator++; } /* If we didn't find any headers, we need to add one */ if (idx == -1) { struct vmem_header* header = (struct vmem_header*)old_end_address; header->magic = VMEM_MAGIC; header->size = new_length - old_length; header->is_hole = 1; struct vmem_footer* footer = (struct vmem_footer*)(old_end_address + header->size - sizeof(struct vmem_footer)); footer->magic = VMEM_MAGIC; footer->header = header; insert_ordered_array((void*)header, &heap->index); } else { /* The last header needs adjusting */ struct vmem_header* header = lookup_ordered_array(idx, &heap->index); header->size += new_length - old_length; /* Rewrite the footer */ struct vmem_footer* footer = (struct vmem_footer*)((addr)header + header->size - sizeof(struct vmem_footer)); footer->header = header; footer->magic = VMEM_MAGIC; } } struct vmem_header* orig_hole_header = (struct vmem_header*)lookup_ordered_array(iterator, &heap->index); addr orig_hole_pos = (addr)orig_hole_header; addr orig_hole_size = orig_hole_header->size; /* Here we work out if we should split the hole we found into two parts. * Is the original hole size - requested hole size less than the overhead for adding a new hole? */ if (orig_hole_size - new_size < sizeof(struct vmem_header) + sizeof(struct vmem_footer)) { /* Then just increase the requested size to the size of the hole we found */ size += orig_hole_size - new_size; new_size = orig_hole_size; } /* If we need to page-align the data, do it now and make a new hole in front of our block */ if (page_align && (orig_hole_pos & 0xFFFFF000)) { addr new_location = orig_hole_pos + 0x1000 /* page size */ - (orig_hole_pos & 0xFFF) - sizeof(struct vmem_header); struct vmem_header* hole_header = (struct vmem_header*)orig_hole_pos; hole_header->size = 0x1000 /* page size */ - (orig_hole_pos & 0xFFF) - sizeof(struct vmem_header); hole_header->magic = VMEM_MAGIC; hole_header->is_hole = 1; struct vmem_footer* hole_footer = (struct vmem_footer*)((addr)new_location - sizeof(struct vmem_footer)); hole_footer->magic = VMEM_MAGIC; hole_footer->header = hole_header; orig_hole_pos = new_location; orig_hole_size = orig_hole_size - hole_header->size; } else { /* Else we don't need this hole any more, delete it from the index */ remove_ordered_array(iterator, &heap->index); } /* Overwrite the original header... */ struct vmem_header* block_header = (struct vmem_header*)orig_hole_pos; block_header->magic = VMEM_MAGIC; block_header->is_hole = 0; block_header->size = new_size; /* ... and the footer */ struct vmem_footer* block_footer = (struct vmem_footer*)(orig_hole_pos + sizeof(struct vmem_header) + size); block_footer->magic = VMEM_MAGIC; block_footer->header = block_header; /* We may need to write a new hole after the allocated block. * We do this only if the new hole would have positive size */ if (orig_hole_size - new_size > 0) { struct vmem_header* hole_header = (struct vmem_header*)(orig_hole_pos + sizeof(struct vmem_header) + size + sizeof(struct vmem_footer)); hole_header->magic = VMEM_MAGIC; hole_header->is_hole = 1; hole_header->size = orig_hole_size - new_size; struct vmem_footer* hole_footer = (struct vmem_footer*)((addr)hole_header + orig_hole_size - new_size - sizeof(struct vmem_footer)); if ((addr)hole_footer < heap->end_address) { hole_footer->magic = VMEM_MAGIC; hole_footer->header = hole_header; } /* Put the new hole in the array */ insert_ordered_array((void*)hole_header, &heap->index); } /* ... and we're done! */ return (void*)((addr)block_header + sizeof(struct vmem_header)); }