|
|
@@ -112,6 +112,60 @@ void * best_fit_on_freelist(heap_t *heap, size_t requested_size) {
|
|
|
return best_block;
|
|
|
}
|
|
|
|
|
|
+void * good_fit_on_freelist(heap_t *heap, size_t requested_size, float fit_percentage) {
|
|
|
+ void *current_block, *previous_block;
|
|
|
+ void *best_block, *best_previous_block;
|
|
|
+ size_t best_size, block_size;
|
|
|
+
|
|
|
+ current_block = NULL;
|
|
|
+ previous_block = NULL;
|
|
|
+ best_previous_block = NULL;
|
|
|
+ best_block = NULL;
|
|
|
+ best_size = (size_t) -1; /* SIZE_MAX */
|
|
|
+ block_size = 0;
|
|
|
+
|
|
|
+ for(current_block = heap->free_list_head; current_block != NULL;
|
|
|
+ current_block = get_next(current_block)) {
|
|
|
+ block_size = get_size(current_block);
|
|
|
+ if(block_size >= requested_size) {
|
|
|
+ if(block_size < best_size) {
|
|
|
+ best_block = current_block;
|
|
|
+ best_size = get_size(current_block);
|
|
|
+ best_previous_block = previous_block;
|
|
|
+ /* If the block size fits the relaxed requirements, then there
|
|
|
+ * is no need to keep searching for a better sized block */
|
|
|
+ if(fit_percentage * best_size <= requested_size) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ previous_block = current_block;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Remove the block from the list */
|
|
|
+ /* Note: remove_block() is not used because the block is already found */
|
|
|
+ if(best_block != NULL) {
|
|
|
+ if(best_block == heap->free_list_head) {
|
|
|
+ heap->free_list_head = get_next(best_block);
|
|
|
+#ifdef BLOCKS_IN_DLL
|
|
|
+ if(heap->free_list_head != NULL) {
|
|
|
+ set_previous(heap->free_list_head, NULL);
|
|
|
+ }
|
|
|
+#endif /* BLOCKS_IN_DLL */
|
|
|
+ } else {
|
|
|
+ set_next(best_previous_block, get_next(best_block));
|
|
|
+#ifdef BLOCKS_IN_DLL
|
|
|
+ if(get_next(best_block) != NULL) {
|
|
|
+ set_previous(get_next(best_block), best_previous_block);
|
|
|
+ }
|
|
|
+#endif /* BLOCKS_IN_DLL */
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return best_block;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* \details In order to remove a block from a singly linked list, we need to
|
|
|
* keep track of the previous block as well: The previous block must point to
|