Browse Source

Tidied up init_heap()

tags/v0.9.3
Michael Brown 19 years ago
parent
commit
42250e9b1a
1 changed files with 61 additions and 74 deletions
  1. 61
    74
      src/core/heap.c

+ 61
- 74
src/core/heap.c View File

8
 	char data[0];
8
 	char data[0];
9
 };
9
 };
10
 
10
 
11
-size_t heap_ptr, heap_top, heap_bot;
11
+/* Linker symbols */
12
+extern char _text[];
13
+extern char _end[];
12
 
14
 
13
-#define _virt_start 0
15
+static unsigned long heap_start, heap_end, heap_ptr;
16
+
17
+/*
18
+ * Find the largest contiguous area of memory that I can use for the
19
+ * heap.
20
+ *
21
+ */
22
+static void init_heap ( void ) {
23
+	unsigned int i;
24
+	unsigned long eb_start, eb_end;
25
+	unsigned long size;
14
 
26
 
15
-static void init_heap(void)
16
-{
17
-	size_t size;
18
-	size_t start, end;
19
-	unsigned i;
20
-	/* Find the largest contiguous area of memory that
21
-	 * I can use for the heap, which is organized as 
22
-	 * a stack that grows backwards through memory.
23
-	 */
24
-
25
-	/* If I have virtual address that do not equal physical addresses
26
-	 * there is a change I will try to use memory from both sides of
27
-	 * the virtual address space simultaneously, which can cause all kinds
28
-	 * of interesting problems.
29
-	 * Avoid it by logically extending etherboot.  Once I know that relocation
30
-	 * works I can just start the virtual address space at 0, and this problem goes
31
-	 * away so that is probably a better solution.
32
-	 */
33
-#if 0
34
-	start = virt_to_phys(_text);
35
-#else
36
-	/* segment wrap around is nasty don't chance it. */
37
-	start = virt_to_phys(_virt_start);
38
-#endif
39
-	end  = virt_to_phys(_end);
40
 	size = 0;
27
 	size = 0;
41
-	for(i = 0; i < meminfo.map_count; i++) {
42
-		unsigned long r_start, r_end;
43
-		if (meminfo.map[i].type != E820_RAM)
44
-			continue;
45
-		if (meminfo.map[i].addr > ULONG_MAX)
28
+	
29
+	/* Region occupied by Etherboot */
30
+	eb_start = virt_to_phys ( _text );
31
+	eb_end = virt_to_phys ( _end );
32
+
33
+	for ( i = 0 ; i < meminfo.map_count ; i++ ) {
34
+		unsigned long r_start, r_end, r_size;
35
+		unsigned long pre_eb, post_eb;
36
+
37
+		/* Get start and end addresses of the region */
38
+		if ( meminfo.map[i].type != E820_RAM )
46
 			continue;
39
 			continue;
47
-		if (meminfo.map[i].size > ULONG_MAX)
40
+		if ( meminfo.map[i].addr > ULONG_MAX )
48
 			continue;
41
 			continue;
49
-		
50
 		r_start = meminfo.map[i].addr;
42
 		r_start = meminfo.map[i].addr;
51
-		r_end = r_start + meminfo.map[i].size;
52
-		if (r_end < r_start) {
43
+		if ( r_start + meminfo.map[i].size > ULONG_MAX ) {
53
 			r_end = ULONG_MAX;
44
 			r_end = ULONG_MAX;
45
+		} else {
46
+			r_end = r_start + meminfo.map[i].size;
54
 		}
47
 		}
55
-		/* Handle areas that overlap etherboot */
56
-		if ((end > r_start) && (start < r_end)) {
57
-			/* Etherboot completely covers the region */
58
-			if ((start <= r_start) && (end >= r_end))
59
-				continue;
60
-			/* Etherboot is completely contained in the region */
61
-			if ((start > r_start) && (end < r_end)) {
62
-				/* keep the larger piece */
63
-				if ((r_end - end) >= (r_start - start)) {
64
-					r_start = end;
65
-				}
66
-				else {
67
-					r_end = start;
68
-				}
69
-			}
70
-			/* Etherboot covers one end of the region.
71
-			 * Shrink the region.
72
-			 */
73
-			else if (end >= r_end) {
74
-				r_end = start;
75
-			}
76
-			else if (start <= r_start) {
77
-				r_start = end;
48
+		
49
+		/* Avoid overlap with Etherboot.  When Etherboot is
50
+		 * completely contained within the region, choose the
51
+		 * larger of the two remaining portions.
52
+		 */
53
+		if ( ( eb_start < r_end ) && ( eb_end > r_start ) ) {
54
+			pre_eb = ( eb_start > r_start ) ?
55
+				( eb_start - r_start ) : 0;
56
+			post_eb = ( r_end > eb_end ) ?
57
+				( r_end - eb_end ) : 0;
58
+			if ( pre_eb > post_eb ) {
59
+				r_end = eb_start;
60
+			} else {
61
+				r_start = eb_end;
78
 			}
62
 			}
79
 		}
63
 		}
80
-		/* If two areas are the size prefer the greater address */
81
-		if (((r_end - r_start) > size) ||
82
-			(((r_end - r_start) == size) && (r_start > heap_top))) {
83
-			size = r_end - r_start;
84
-			heap_top = r_start;
85
-			heap_bot = r_end;
64
+
65
+		/* Use the biggest region.  Where two regions are the
66
+		 * same size, use the later region.  (Provided that
67
+		 * the memory map is laid out in a sensible order,
68
+		 * this should give us the higher region.)
69
+		 */
70
+		r_size = r_end - r_start;
71
+		if ( r_size >= size ) {
72
+			heap_start = r_start;
73
+			heap_end = r_end;
74
+			size = r_size;
86
 		}
75
 		}
87
 	}
76
 	}
88
-	if (size == 0) {
89
-		printf("init_heap: No heap found.\n");
90
-		exit(1);
91
-	}
92
-	heap_ptr = heap_bot;
77
+
78
+	ASSERT ( size != 0 );
79
+	heap_ptr = heap_end;
93
 }
80
 }
94
 
81
 
95
 /*
82
 /*
104
 	
91
 	
105
 	addr = ( ( ( heap_ptr - size ) & ~( align - 1 ) )
92
 	addr = ( ( ( heap_ptr - size ) & ~( align - 1 ) )
106
 		 - sizeof ( struct heap_block ) );
93
 		 - sizeof ( struct heap_block ) );
107
-	if ( addr < heap_top ) {
94
+	if ( addr < heap_start ) {
108
 		return NULL;
95
 		return NULL;
109
 	}
96
 	}
110
 
97
 
119
  *
106
  *
120
  */
107
  */
121
 void * emalloc_all ( size_t *size ) {
108
 void * emalloc_all ( size_t *size ) {
122
-	*size = heap_ptr - heap_top - sizeof ( struct heap_block );
109
+	*size = heap_ptr - heap_start - sizeof ( struct heap_block );
123
 	return emalloc ( *size, sizeof ( void * ) );
110
 	return emalloc ( *size, sizeof ( void * ) );
124
 }
111
 }
125
 
112
 
136
 		( ptr - offsetof ( struct heap_block, data ) );
123
 		( ptr - offsetof ( struct heap_block, data ) );
137
 	heap_ptr += block->size;
124
 	heap_ptr += block->size;
138
 
125
 
139
-	ASSERT ( heap_ptr <= heap_bot );
126
+	ASSERT ( heap_ptr <= heap_end );
140
 }
127
 }
141
 
128
 
142
 /*
129
 /*
144
  *
131
  *
145
  */
132
  */
146
 void efree_all ( void ) {
133
 void efree_all ( void ) {
147
-	heap_ptr = heap_bot;
134
+	heap_ptr = heap_end;
148
 }
135
 }
149
 
136
 
150
 INIT_FN ( INIT_HEAP, init_heap, efree_all, NULL );
137
 INIT_FN ( INIT_HEAP, init_heap, efree_all, NULL );

Loading…
Cancel
Save