comparison cos/kernel/malloc.c @ 40:24ce177e01e8

Added more malloc stuff. Added mem usage
author windel
date Tue, 24 Jan 2012 17:54:16 +0100
parents 7e3bdcb391dc
children
comparison
equal deleted inserted replaced
37:5c20bd53cccd 40:24ce177e01e8
3 // ================= Placement malloc: 3 // ================= Placement malloc:
4 // Assume here that nothing gets ever kfree'd. This makes it simple! 4 // Assume here that nothing gets ever kfree'd. This makes it simple!
5 5
6 uint64_t placement_address = (uint64_t)&kernel_end; 6 uint64_t placement_address = (uint64_t)&kernel_end;
7 7
8 void* kmalloc_int(uint64_t size)
9 {
10 uint64_t tmp = placement_address;
11 placement_address += size;
12 return (void*)tmp;
13 }
14
15 void* kmalloc_aligned_int(uint64_t size)
16 {
17 if ( (placement_address | 0xFFF) != 0 )
18 {
19 placement_address &= ~(0xFFF);
20 placement_address += 0x1000;
21 }
22 uint64_t tmp = placement_address;
23 placement_address += size;
24 return (void*)tmp;
25 }
26
27
28 // ================= Other malloc 8 // ================= Other malloc
29 // TODO: move this to user space? 9 // TODO: move this to user space?
30 10
31 #define HEAP_MAGIC 0xc0ffee 11 #define HEAP_MAGIC 0xc0ffee
32 #define HEAP_START 0x400000
33 #define HEAP_SIZE 0x200000
34 #define HEAP_INUSE 1 12 #define HEAP_INUSE 1
35 #define HEAP_FREE 0 13 #define HEAP_FREE 0
36
37 typedef struct {
38 uint64_t magic;
39 uint64_t state;
40 uint64_t size;
41 } heap_t;
42 14
43 /* 15 /*
44 malloc and free divide the chunks of memory present at the heap 16 malloc and free divide the chunks of memory present at the heap
45 of the kernel into smaller parts. 17 of the kernel into smaller parts.
46 The heap is located at: 0x 18 The heap is located at: 0x
47 */ 19 */
48 20
49 static heap_t* kernel_heap = (heap_t*) 0x400000; // 4 MB - 6 MB is heap 21 static heap_t* kernel_heap = 0;
22
23 void expand_heap(heap_t *heap, uint64_t newsize);
24
50 /* Allocates 'size' bytes and returns the pointer if succesfull. 25 /* Allocates 'size' bytes and returns the pointer if succesfull.
26 Before the kernel is initialized, placement malloc is used.
51 Kernelpanic in case of failure.. 27 Kernelpanic in case of failure..
52 */ 28 */
29 static void* kmalloc_int(uint64_t size, uint64_t aligned)
30 {
31 // Check if there exists a kernel heap. If not, use placement malloc for now.
32 if (kernel_heap == 0)
33 {
34 // Before that the heap is initialized, use placement malloc
35 if (aligned == 1)
36 {
37 // Align placement address
38 if ( (placement_address | 0xFFF) != 0 )
39 {
40 placement_address &= ~(0xFFF);
41 placement_address += 0x1000;
42 }
43 }
44 uint64_t tmp = placement_address;
45 placement_address += size;
46 return (void*)tmp;
47 }
48 else
49 {
50 // We have a kernel heap, search the heap for a block of suitable size.
53 51
54 void* kmalloc(uint64_t size) 52 // Start at the beginning of our heap and search a free block:
53 heap_header_t *current = kernel_heap->first_block;
54 while (current->magic == HEAP_MAGIC)
55 {
56 if ((current->state == HEAP_FREE) && (current->size >= size))
57 {
58 // We found a hole with suitable size. Determine if split is of any use.
59
60 // Insert a heap header if required:
61 if (current->size > size + sizeof(heap_t) + 1)
62 {
63 // Calculate location of the inserted header:
64 heap_header_t *newheader = (heap_header_t*) (((uint64_t)current)+size+sizeof(heap_header_t));
65
66 // Set the new header fields:
67 newheader->size = current->size - size - sizeof(heap_header_t);
68 newheader->state = HEAP_FREE;
69 newheader->magic = HEAP_MAGIC;
70
71 // Set the size of this block
72 current->size = size;
73 }
74 else
75 {
76 // We allocate this whole block
77 // Mark block as used:
78 current->state = HEAP_INUSE;
79 }
80 // Calculate the size of the block:
81 char *address = ((char*)current)+sizeof(heap_header_t);
82 return address;
83
84 }
85 // Goto next heap block:
86 current = (heap_header_t*)(((uint64_t) current) + current->size + sizeof(heap_header_t));
87 }
88
89 // We did not find a block large enough. Expand the heap and try again.
90 expand_heap(kernel_heap, 0x10000000);
91 return kmalloc_int(size, aligned);
92 }
93 }
94
95 // Convenient wrappers:
96 void* kmalloc(uint64_t size)
55 { 97 {
56 return kmalloc_int(size); 98 return kmalloc_int(size, 0);
99 }
57 100
58 // Start at the beginning of our heap and search a free block: 101 void* kmalloc_a(uint64_t size)
59 heap_t *current = kernel_heap; 102 {
60 while (current->magic == HEAP_MAGIC) 103 return kmalloc_int(size, 1);
61 {
62 if ((current->state == HEAP_FREE) && (current->size >= size))
63 {
64 // Mark block as used:
65 current->state = HEAP_INUSE;
66
67 // Insert a heap header if required:
68 if (current->size > size + sizeof(heap_t) + 1)
69 {
70 // Calculate location of the inserted header:
71 heap_t *newheader = (heap_t*) (((char*)current)+size+sizeof(heap_t));
72
73 // Set the new header fields:
74 newheader->size = current->size - size - sizeof(heap_t);
75 newheader->state = HEAP_FREE;
76 newheader->magic = HEAP_MAGIC;
77
78 // Set the size of this block
79 current->size = size;
80 }
81 else
82 {
83 // We allocate this whole block
84 }
85 // Calculate the size of the block:
86 char *address = ((char*)current)+sizeof(heap_t);
87 return address;
88
89 }
90 // Goto next heap block:
91 current = (heap_t*)(((char*) current) + current->size + sizeof(heap_t));
92 }
93 return 0x0;
94 } 104 }
95 105
96 void kfree(void* ptr) 106 void kfree(void* ptr)
97 { 107 {
98 printf("Free address %x\n", ptr); 108 printf("Free address %x\n", ptr);
109 if (kernel_heap == 0)
110 {
111 return;
112 }
113 else
114 {
115 // TODO
116 }
117 // TODO: free blocks:
99 } 118 }
100 119
101 void init_heap(void) 120 heap_t* create_heap(uint64_t location, uint64_t size)
102 { 121 {
103 // Initialize the kernel heap: 122 // Make sure that the new heap location is mapped into the address space:
104 kernel_heap->magic = HEAP_MAGIC; 123 uint64_t i = 0;
105 kernel_heap->state = HEAP_FREE; 124 while (i < size)
106 kernel_heap->size = HEAP_SIZE - sizeof(heap_t); 125 {
126 alloc_frame( get_page(location + i, kernel_map));
127 i += 0x1000;
128 }
129
130 // create new heap structure:
131 heap_t* h = (heap_t*)kmalloc(sizeof(heap_t));
132
133 // Create one big hole:
134 h->first_block = (heap_header_t*)location; // Place header at beginning of heap
135 h->first_block->magic = HEAP_MAGIC;
136 h->first_block->state = HEAP_FREE;
137 h->first_block->size = size - sizeof(heap_header_t);
138 return h;
107 } 139 }
108 140
141 // Make the total heap bigger:
142 void expand_heap(heap_t *heap, uint64_t newsize)
143 {
144 uint64_t oldsize = heap->end_address - heap->start_address;
145 if (newsize < oldsize)
146 {
147 panic("Cannot expand heap to a smaller size\n");
148 }
149
150 uint64_t i = oldsize;
151 while (i < newsize)
152 {
153 alloc_frame( get_page(heap->start_address + i, kernel_map));
154 i += 0x1000;
155 }
156 }
157