Browse Source

Add realloc, since the load buffer code requires it.

tags/v0.9.3
Michael Brown 19 years ago
parent
commit
5c8ea0b93a
2 changed files with 84 additions and 24 deletions
  1. 69
    10
      src/core/heap.c
  2. 15
    14
      src/include/heap.h

+ 69
- 10
src/core/heap.c View File

@@ -5,6 +5,7 @@
5 5
 
6 6
 struct heap_block {
7 7
 	size_t size;
8
+	unsigned int align;
8 9
 	char data[0];
9 10
 };
10 11
 
@@ -12,7 +13,7 @@ struct heap_block {
12 13
 extern char _text[];
13 14
 extern char _end[];
14 15
 
15
-static unsigned long heap_start, heap_end, heap_ptr;
16
+static physaddr_t heap_start, heap_end, heap_ptr;
16 17
 
17 18
 /*
18 19
  * Find the largest contiguous area of memory that I can use for the
@@ -21,8 +22,8 @@ static unsigned long heap_start, heap_end, heap_ptr;
21 22
  */
22 23
 static void init_heap ( void ) {
23 24
 	unsigned int i;
24
-	unsigned long eb_start, eb_end;
25
-	unsigned long size;
25
+	physaddr_t eb_start, eb_end;
26
+	physaddr_t size;
26 27
 
27 28
 	size = 0;
28 29
 	
@@ -31,8 +32,8 @@ static void init_heap ( void ) {
31 32
 	eb_end = virt_to_phys ( _end );
32 33
 
33 34
 	for ( i = 0 ; i < meminfo.map_count ; i++ ) {
34
-		unsigned long r_start, r_end, r_size;
35
-		unsigned long pre_eb, post_eb;
35
+		physaddr_t r_start, r_end, r_size;
36
+		physaddr_t pre_eb, post_eb;
36 37
 
37 38
 		/* Get start and end addresses of the region */
38 39
 		if ( meminfo.map[i].type != E820_RAM )
@@ -84,14 +85,19 @@ static void init_heap ( void ) {
84 85
  * Allocate a block from the heap.
85 86
  *
86 87
  */
88
+static inline physaddr_t block_alloc_addr ( physaddr_t heap_ptr,
89
+					    size_t size, unsigned int align ) {
90
+	return ( ( ( heap_ptr - size ) & ~( align - 1 ) )
91
+		 - sizeof ( struct heap_block ) );
92
+}
93
+
87 94
 void * emalloc ( size_t size, unsigned int align ) {
88
-	physaddr_t addr;
89 95
 	struct heap_block *block;
96
+	physaddr_t addr;
90 97
 	
91 98
 	ASSERT ( ( align & ( align - 1 ) ) == 0 );
92
-	
93
-	addr = ( ( ( heap_ptr - size ) & ~( align - 1 ) )
94
-		 - sizeof ( struct heap_block ) );
99
+
100
+	addr = block_alloc_addr ( heap_ptr, size, align );
95 101
 	if ( addr < heap_start ) {
96 102
 		DBG ( "HEAP no space for %x bytes (alignment %d) in [%x,%x)\n",
97 103
 		      size, align, heap_start, heap_ptr );
@@ -100,6 +106,7 @@ void * emalloc ( size_t size, unsigned int align ) {
100 106
 
101 107
 	block = phys_to_virt ( addr );
102 108
 	block->size = ( heap_ptr - addr );
109
+	block->align = align;
103 110
 	DBG ( "HEAP allocated %x bytes (alignment %d) at %x [%x,%x)\n",
104 111
 	      size, align, virt_to_phys ( block->data ), addr, heap_ptr );
105 112
 	heap_ptr = addr;
@@ -119,6 +126,10 @@ void * emalloc_all ( size_t *size ) {
119 126
  * Free a heap block
120 127
  *
121 128
  */
129
+static inline physaddr_t block_free_addr ( size_t size ) {
130
+	return heap_ptr + size;
131
+}
132
+
122 133
 void efree ( void *ptr ) {
123 134
 	struct heap_block *block;
124 135
 
@@ -126,7 +137,7 @@ void efree ( void *ptr ) {
126 137
 	
127 138
 	block = ( struct heap_block * )
128 139
 		( ptr - offsetof ( struct heap_block, data ) );
129
-	heap_ptr += block->size;
140
+	heap_ptr = block_free_addr ( block->size );
130 141
 
131 142
 	DBG ( "HEAP freed %x [%x,%x)\n", virt_to_phys ( ptr ),
132 143
 	      virt_to_phys ( block ), heap_ptr );
@@ -145,4 +156,52 @@ void efree_all ( void ) {
145 156
 	heap_ptr = heap_end;
146 157
 }
147 158
 
159
+/*
160
+ * Resize a heap block
161
+ *
162
+ */
163
+void * erealloc ( void *ptr, size_t size ) {
164
+	struct heap_block *old_block;
165
+	size_t old_size;
166
+	unsigned int old_align;
167
+	physaddr_t new_addr;
168
+	size_t move_size;
169
+	
170
+	/* Get descriptor of the old block */
171
+	old_block = ( struct heap_block * )
172
+		( ptr - offsetof ( struct heap_block, data ) );
173
+	old_size = old_block->size;
174
+	old_align = old_block->align;
175
+
176
+	/* Check that allocation is going to succeed */
177
+	new_addr = block_alloc_addr ( block_free_addr ( old_size ),
178
+				      size, old_align );
179
+	if ( new_addr < heap_start ) {
180
+		DBG ( "HEAP no space for %x bytes (alignment %d) in [%x,%x)\n",
181
+		      size, align, heap_start, block_free_addr ( old_size ) );
182
+		return NULL;
183
+	}
184
+
185
+	/* Free the old block */
186
+	efree ( ptr );
187
+
188
+	/* Move the data.  Do this *before* allocating the new block,
189
+	 * because the new block's descriptor may overwrite the old
190
+	 * block's data, if the new block is smaller than the old
191
+	 * block.
192
+	 */
193
+	move_size = size + sizeof ( struct heap_block );
194
+	if ( old_size < move_size )
195
+		move_size = old_size;
196
+	memmove ( phys_to_virt ( new_addr ), old_block, move_size );
197
+
198
+	/* Allocate the new block.  This must succeed, because we
199
+	 * already checked that there was sufficient space.
200
+	 */
201
+	ptr = emalloc ( size, old_align );
202
+	ASSERT ( ptr != NULL );
203
+
204
+	return ptr;
205
+}
206
+
148 207
 INIT_FN ( INIT_HEAP, init_heap, efree_all, NULL );

+ 15
- 14
src/include/heap.h View File

@@ -12,14 +12,6 @@
12 12
  */
13 13
 extern void * emalloc ( size_t size, unsigned int align );
14 14
 
15
-/*
16
- * Allocate a block, with no particular alignment requirements.
17
- *
18
- */
19
-static inline void * malloc ( size_t size ) {
20
-	return emalloc ( size, sizeof ( void * ) );
21
-}
22
-
23 15
 /*
24 16
  * Allocate all remaining space on the heap
25 17
  *
@@ -36,10 +28,6 @@ extern void * emalloc_all ( size_t *size );
36 28
  */
37 29
 extern void efree ( void *ptr );
38 30
 
39
-static inline void free ( void *ptr ) {
40
-	efree ( ptr );
41
-}
42
-
43 31
 /*
44 32
  * Free all allocated blocks on the heap
45 33
  *
@@ -54,9 +42,22 @@ extern void efree_all ( void );
54 42
  * corruption will occur.
55 43
  *
56 44
  */
57
-static inline void * erealloc ( void *ptr, size_t size, unsigned int align ) {
45
+extern void * erealloc ( void *ptr, size_t size );
46
+
47
+/*
48
+ * Allocate, free, and resize blocks without caring about alignment
49
+ *
50
+ */
51
+static inline void * malloc ( size_t size ) {
52
+	return emalloc ( size, sizeof ( void * ) );
53
+}
54
+
55
+static inline void free ( void *ptr ) {
58 56
 	efree ( ptr );
59
-	return emalloc ( size, align );
57
+}
58
+
59
+static inline void * realloc ( void *ptr, size_t size ) {
60
+	return erealloc ( ptr, size );
60 61
 }
61 62
 
62 63
 /*

Loading…
Cancel
Save