Mercurial > lcfOS
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 |