Просмотр исходного кода

Initial commit of coalesce and helping functions.

Ioannis Koutras лет назад: 13
Родитель
Сommit
4759016639
5 измененных файлов с 113 добавлено и 2 удалено
  1. 1 1
      Makefile
  2. 33 1
      block_header.c
  3. 16 0
      block_header.h
  4. 48 0
      coalesce.c
  5. 15 0
      coalesce.h

+ 1 - 1
Makefile

@@ -5,7 +5,7 @@ WARNINGS := -Wall -Wextra -pedantic -Wshadow -Wpointer-arith -Wcast-align \
 	          -Wuninitialized -Wconversion -Wstrict-prototypes
 CFLAGS := -g -O -std=c99 $(WARNINGS)
 
-OBJ = posix_lock.o other.o block_header.o sys_alloc.o dmm_init.o custom_malloc.o custom_free.o
+OBJ = posix_lock.o other.o block_header.o sys_alloc.o dmm_init.o coalesce.o custom_malloc.o custom_free.o
 
 %.o: %.c
 	$(CC) -c -o $@ $< $(CFLAGS)

+ 33 - 1
block_header.c

@@ -15,7 +15,7 @@ size_t get_size(void *ptr) {
 }
 
 void set_size(void *ptr, size_t size) {
-	get_header(ptr)->size = size;
+	get_header(ptr)->size = size << 1;
 }
 
 void set_requested_size(void *ptr, size_t size) {
@@ -25,3 +25,35 @@ void set_requested_size(void *ptr, size_t size) {
 void set_next(void *ptr, void *next_block) {
 	get_header(ptr)->next = next_block;
 }
+
+bool is_previous_free(void *ptr) {
+	return (bool) (get_header(ptr)->previous_size & 1);
+}
+
+size_t get_previous_size(void *ptr) {
+	return get_header(ptr)->previous_size >> 1;
+}
+
+void * get_previous(void *ptr) {
+	return (void *) ((char *) ptr - get_previous_size(ptr));
+}
+
+void remove_block(void *block, void *starting_node) {
+	void *current_node, *previous_node;
+
+	// If the block to be removed is the head of the list, then just point
+	// the next block as head.
+	if(current_node == starting_node) {
+		starting_node = get_next(block);
+	// Else traverse through the list until the memory block is found.
+	} else {
+		for(current_node = starting_node; current_node != NULL; 
+				current_node = get_next(current_node)) {
+			if(current_node == block) {
+				set_next(previous_node, get_next(block));
+			}
+			previous_node = current_node;
+		}
+	}
+}
+

+ 16 - 0
block_header.h

@@ -2,10 +2,12 @@
 #define BLOCK_HEADER_H
 
 #include <stddef.h>
+#include <stdbool.h>
 
 typedef struct block_header_s {
 	size_t size;
 	size_t requested_size;
+	size_t previous_size;
 	void *next;
 } block_header_t;
 
@@ -20,4 +22,18 @@ void set_requested_size(void *ptr, size_t size);
 
 void set_next(void *block, void *next_block);
 
+bool is_previous_free(void *ptr);
+
+size_t get_previous_size(void *ptr);
+
+void * get_previous(void *ptr);
+
+/**
+ * Removes a memory block from a singly linked list of memory blocks.
+ *
+ * @param *block The block to be removed.
+ * @param *starting_node The starting memory block of the list.
+ */
+void remove_block(void *block, void *starting_node);
+
 #endif /* BLOCK_HEADER_H */

+ 48 - 0
coalesce.c

@@ -0,0 +1,48 @@
+#include "coalesce.h"
+#include "block_header.h"
+#include "other.h"
+
+void * coalesce(void *ptr, heap_t *heap) {
+	void *prev;
+	int fixed_list_id, i;
+	maptable_node_t *current_maptable_node;
+
+	// If there is a negative value on max_coalesce_size, then don't do
+	// anything.
+	// FIXME To be moved in custom_free()
+	if(heap->dmm_knobs.max_coalesce_size < 0) {
+		return ptr;
+	}
+
+	// Try to coalesce with the previous memory block
+	if(is_previous_free(ptr)) {
+		prev = get_previous(ptr);
+
+		// Check if it is a block of a fixed list
+		fixed_list_id = map_size_to_list(heap, get_size(prev));
+		if(fixed_list_id != -1) {
+			// If it is, find the fixed list and remove the block
+			current_maptable_node = heap->maptable_head;
+			if(fixed_list_id != 0) {
+				for(i = 1; i < fixed_list_id; i++) {
+					current_maptable_node =
+						current_maptable_node->next;
+				}
+			}
+			remove_block(ptr, current_maptable_node->fixed_list_head);
+		} else {
+			// Or it is a block from the free list, so remove it
+			// from there
+			remove_block(ptr, heap->free_list_head);
+		}
+
+		// Set the new size
+		// Note: the rest of the header variables will be set on free().
+		set_size(prev, get_size(prev) + get_size(ptr) + HEADER_SIZE);
+
+		return prev;
+	} else {
+		return ptr;
+	}
+}
+

+ 15 - 0
coalesce.h

@@ -0,0 +1,15 @@
+#ifndef COALESCE_H
+#define COALESCE_H
+
+#include "heap.h"
+
+/**
+ * Merges a memory block with its previous one if the latter one is free.
+ *
+ * @param ptr The memory block to be checked.
+ * @param heap The heap of the memory block.
+ */
+void * coalesce(void *ptr, heap_t *heap);
+
+#endif /* COALESCE_H */
+