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
 
5
 
6
 struct heap_block {
6
 struct heap_block {
7
 	size_t size;
7
 	size_t size;
8
+	unsigned int align;
8
 	char data[0];
9
 	char data[0];
9
 };
10
 };
10
 
11
 
12
 extern char _text[];
13
 extern char _text[];
13
 extern char _end[];
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
  * Find the largest contiguous area of memory that I can use for the
19
  * Find the largest contiguous area of memory that I can use for the
21
  */
22
  */
22
 static void init_heap ( void ) {
23
 static void init_heap ( void ) {
23
 	unsigned int i;
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
 	size = 0;
28
 	size = 0;
28
 	
29
 	
31
 	eb_end = virt_to_phys ( _end );
32
 	eb_end = virt_to_phys ( _end );
32
 
33
 
33
 	for ( i = 0 ; i < meminfo.map_count ; i++ ) {
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
 		/* Get start and end addresses of the region */
38
 		/* Get start and end addresses of the region */
38
 		if ( meminfo.map[i].type != E820_RAM )
39
 		if ( meminfo.map[i].type != E820_RAM )
84
  * Allocate a block from the heap.
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
 void * emalloc ( size_t size, unsigned int align ) {
94
 void * emalloc ( size_t size, unsigned int align ) {
88
-	physaddr_t addr;
89
 	struct heap_block *block;
95
 	struct heap_block *block;
96
+	physaddr_t addr;
90
 	
97
 	
91
 	ASSERT ( ( align & ( align - 1 ) ) == 0 );
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
 	if ( addr < heap_start ) {
101
 	if ( addr < heap_start ) {
96
 		DBG ( "HEAP no space for %x bytes (alignment %d) in [%x,%x)\n",
102
 		DBG ( "HEAP no space for %x bytes (alignment %d) in [%x,%x)\n",
97
 		      size, align, heap_start, heap_ptr );
103
 		      size, align, heap_start, heap_ptr );
100
 
106
 
101
 	block = phys_to_virt ( addr );
107
 	block = phys_to_virt ( addr );
102
 	block->size = ( heap_ptr - addr );
108
 	block->size = ( heap_ptr - addr );
109
+	block->align = align;
103
 	DBG ( "HEAP allocated %x bytes (alignment %d) at %x [%x,%x)\n",
110
 	DBG ( "HEAP allocated %x bytes (alignment %d) at %x [%x,%x)\n",
104
 	      size, align, virt_to_phys ( block->data ), addr, heap_ptr );
111
 	      size, align, virt_to_phys ( block->data ), addr, heap_ptr );
105
 	heap_ptr = addr;
112
 	heap_ptr = addr;
119
  * Free a heap block
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
 void efree ( void *ptr ) {
133
 void efree ( void *ptr ) {
123
 	struct heap_block *block;
134
 	struct heap_block *block;
124
 
135
 
126
 	
137
 	
127
 	block = ( struct heap_block * )
138
 	block = ( struct heap_block * )
128
 		( ptr - offsetof ( struct heap_block, data ) );
139
 		( ptr - offsetof ( struct heap_block, data ) );
129
-	heap_ptr += block->size;
140
+	heap_ptr = block_free_addr ( block->size );
130
 
141
 
131
 	DBG ( "HEAP freed %x [%x,%x)\n", virt_to_phys ( ptr ),
142
 	DBG ( "HEAP freed %x [%x,%x)\n", virt_to_phys ( ptr ),
132
 	      virt_to_phys ( block ), heap_ptr );
143
 	      virt_to_phys ( block ), heap_ptr );
145
 	heap_ptr = heap_end;
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
 INIT_FN ( INIT_HEAP, init_heap, efree_all, NULL );
207
 INIT_FN ( INIT_HEAP, init_heap, efree_all, NULL );

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

12
  */
12
  */
13
 extern void * emalloc ( size_t size, unsigned int align );
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
  * Allocate all remaining space on the heap
16
  * Allocate all remaining space on the heap
25
  *
17
  *
36
  */
28
  */
37
 extern void efree ( void *ptr );
29
 extern void efree ( void *ptr );
38
 
30
 
39
-static inline void free ( void *ptr ) {
40
-	efree ( ptr );
41
-}
42
-
43
 /*
31
 /*
44
  * Free all allocated blocks on the heap
32
  * Free all allocated blocks on the heap
45
  *
33
  *
54
  * corruption will occur.
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
 	efree ( ptr );
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