Pārlūkot izejas kodu

Tidied up init_heap()

tags/v0.9.3
Michael Brown 19 gadus atpakaļ
vecāks
revīzija
42250e9b1a
1 mainītis faili ar 61 papildinājumiem un 74 dzēšanām
  1. 61
    74
      src/core/heap.c

+ 61
- 74
src/core/heap.c Parādīt failu

@@ -8,88 +8,75 @@ struct heap_block {
8 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 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 39
 			continue;
47
-		if (meminfo.map[i].size > ULONG_MAX)
40
+		if ( meminfo.map[i].addr > ULONG_MAX )
48 41
 			continue;
49
-		
50 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 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,7 +91,7 @@ void * emalloc ( size_t size, unsigned int align ) {
104 91
 	
105 92
 	addr = ( ( ( heap_ptr - size ) & ~( align - 1 ) )
106 93
 		 - sizeof ( struct heap_block ) );
107
-	if ( addr < heap_top ) {
94
+	if ( addr < heap_start ) {
108 95
 		return NULL;
109 96
 	}
110 97
 
@@ -119,7 +106,7 @@ void * emalloc ( size_t size, unsigned int align ) {
119 106
  *
120 107
  */
121 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 110
 	return emalloc ( *size, sizeof ( void * ) );
124 111
 }
125 112
 
@@ -136,7 +123,7 @@ void efree ( void *ptr ) {
136 123
 		( ptr - offsetof ( struct heap_block, data ) );
137 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,7 +131,7 @@ void efree ( void *ptr ) {
144 131
  *
145 132
  */
146 133
 void efree_all ( void ) {
147
-	heap_ptr = heap_bot;
134
+	heap_ptr = heap_end;
148 135
 }
149 136
 
150 137
 INIT_FN ( INIT_HEAP, init_heap, efree_all, NULL );

Notiek ielāde…
Atcelt
Saglabāt