예제 #1
0
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);
}
예제 #2
0
/* Remove the item /item/; if multiple exist, the first is deleted */
void remove_ordered_array_item(type_t item, ordered_array_t *array) {
	for (uint32 i = 0; i < array->size; i++) {
		if (lookup_ordered_array(i, array) == item) {
			/* We found it! Now remove it: */
			remove_ordered_array(i, array);
			return;
		}
	}
}
예제 #3
0
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));
}
예제 #4
0
파일: kheap.c 프로젝트: Magnus932/kernel
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);
}
예제 #5
0
파일: kheap.c 프로젝트: Magnus932/kernel
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));
}
예제 #6
0
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);
	}
}
예제 #7
0
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));
}
예제 #8
0
파일: kheap.c 프로젝트: blessed/blessOS
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);
}
예제 #9
0
파일: kheap.c 프로젝트: blessed/blessOS
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));
}
예제 #10
0
파일: vmem.c 프로젝트: TheBugEater/Kernel
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);
}
예제 #11
0
파일: vmem.c 프로젝트: TheBugEater/Kernel
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));
}