1
+ #include "paging.h"
2
+ #include "printf.h"
3
+ #include "kmisc.h"
4
+ #include "misc.h"
5
+
6
+ // Functions used by the kernel & drivers
7
+
8
+ // TODO: This might all go out the window in favor of conditionally-compiling misc.c functions; I haven't decided yet.
9
+
10
+ extern uint32_t memoryNextAvailableAddress ;
11
+ extern uint32_t pagedMemoryAvailable ;
12
+
13
+ // TODO: Change this to a more robust scheme (?)
14
+ ALLOCATION_ARRAY kallocationArray = { 0 };
15
+ unsigned int knextAllocationSlot = 0 ;
16
+
17
+ // Very, very basic support for freeing memory:
18
+ ALLOCATION_ARRAY kfreeMemoryArray = { 0 };
19
+ unsigned int knextFreeMemorySlot = 0 ;
20
+
21
+ #ifdef DEBUG_MEM
22
+ #define noFileName "FILENAME NOT SET";
23
+ char * dbgMemFilename = noFileName ;
24
+ int dbgMemLineNumber = 0 ;
25
+ char * dbgFreeFilename = noFileName ;
26
+ int dbgFreeLineNumber = 0 ;
27
+ #endif
28
+
29
+ inline void addAllocationToKFreeMemoryArray (int allocationIndex )
30
+ {
31
+ // Try to add this memory to the free memory array
32
+ if (knextFreeMemorySlot == MAX_ALLOCATIONS )
33
+ {
34
+ kprintf ("NSLFM" );
35
+ return ;
36
+ }
37
+
38
+ kfreeMemoryArray .address [knextFreeMemorySlot ] = kallocationArray .address [allocationIndex ];
39
+ kfreeMemoryArray .size [knextFreeMemorySlot ] = kallocationArray .size [allocationIndex ];
40
+ kfreeMemoryArray .inUse [knextFreeMemorySlot ++ ] = true;
41
+ }
42
+
43
+ // Allocate some kernel memory. Mostly this is meant to be used by drivers.
44
+ // This will be mapped into every tasks page space and will be allocated contiguously
45
+ // TODO: Is it better to have this crazy scheme with the two functions, or just modify malloc to make sure
46
+ // it never reuses user-space memory when called from the kernel?
47
+
48
+ void * kmalloc (size_t size )
49
+ {
50
+ if (knextAllocationSlot >= MAX_ALLOCATIONS )
51
+ {
52
+ kprintf ("Maximum memory allocations exceeded!\n" );
53
+ return NULL ;
54
+ }
55
+
56
+ #ifdef DEBUG_MEM
57
+ kallocationArray .lineNumber [knextAllocationSlot ] = dbgMemLineNumber ;
58
+ strncpy (kallocationArray .filename [knextAllocationSlot ], dbgMemFilename , MAX_DEBUG_FILENAME_LENGTH );
59
+ dbgMemFilename = noFileName ;
60
+ dbgMemLineNumber = 0 ;
61
+ #endif
62
+
63
+ // See if there's freed memory available to reallocate (first fit algorithm; memory will end up wasted)
64
+ for (size_t i = 0 ; i < knextFreeMemorySlot ; ++ i )
65
+ {
66
+ if (kfreeMemoryArray .size [i ] >= size )
67
+ {
68
+ // We found a piece of free memory we can reuse
69
+
70
+ // Keep track of the memory in our allocations array
71
+ kallocationArray .address [knextAllocationSlot ] = kfreeMemoryArray .address [i ];
72
+ kallocationArray .size [knextAllocationSlot ] = kfreeMemoryArray .size [i ];
73
+ kallocationArray .inUse [knextAllocationSlot ] = true;
74
+
75
+ // We want to keep kfreeMemoryArray from fragmenting, so we'll copy
76
+ // last used free memory entry of the array to the i position and decrease
77
+ // the used portion of the array by one
78
+ -- knextFreeMemorySlot ;
79
+ if (knextFreeMemorySlot )
80
+ {
81
+ kfreeMemoryArray .address [i ] = kfreeMemoryArray .address [knextFreeMemorySlot ];
82
+ kfreeMemoryArray .size [i ] = kfreeMemoryArray .size [knextFreeMemorySlot ];
83
+ }
84
+ // The last entry is no longer in use
85
+ kfreeMemoryArray .inUse [knextFreeMemorySlot ] = false;
86
+
87
+ #ifdef DEBUG_MEM
88
+ //printf("Reusing freed memory from slot %d, (reuse #%d)\n", i, ++reuses);
89
+ #endif
90
+ return (void * )kallocationArray .address [knextAllocationSlot ++ ];
91
+ }
92
+ }
93
+
94
+ uint32_t availableAddress = memoryNextAvailableAddress ;
95
+
96
+ #ifdef DEBUG_MEM
97
+ printf ("Allocating new %d bytes\n" , size );
98
+ #endif
99
+
100
+ //if(debugLevel)
101
+ //printf("size: %d\nadrress: %d\n", size, memoryNextAvailableAddress);
102
+
103
+ /*terminal_writestring("Paged memory available: ");
104
+ terminal_print_int(pagedMemoryAvailable);
105
+ terminal_newline();*/
106
+
107
+ // see if we need to allocate a page
108
+ if (size > pagedMemoryAvailable )
109
+ {
110
+ // TODO: Support dynamic page granularity, not just large pages
111
+ unsigned int pagesToAllocate = size / FOUR_MEGABYTES ;
112
+
113
+ // check for remainder from division
114
+ if (pagesToAllocate * FOUR_MEGABYTES < size )
115
+ ++ pagesToAllocate ;
116
+
117
+ // Allocate the pages
118
+ unsigned int pagesAllocated ;
119
+ KPageAllocator (pagesToAllocate , & pagesAllocated , & availableAddress );
120
+
121
+ // We need to ensure the pages are in order
122
+ if (!availableAddress || (pagesAllocated < pagesToAllocate ))
123
+ {
124
+ kprintf ("Returning NULL, %d pages allocated out of %d\n" , pagesAllocated , pagesToAllocate );
125
+ // TODO: Free allocated pages
126
+ return NULL ;
127
+ }
128
+
129
+ // TODO: see if the page we allocated follows the previous page
130
+ // for now, we'll just ignore the old allocated memory
131
+ pagedMemoryAvailable = pagesAllocated * FOUR_MEGABYTES ;
132
+
133
+ memoryNextAvailableAddress = availableAddress ;
134
+ }
135
+
136
+ pagedMemoryAvailable -= size ;
137
+ availableAddress = memoryNextAvailableAddress ;
138
+ memoryNextAvailableAddress += size ;
139
+
140
+ // Keep track of the memory in our allocations array
141
+ kallocationArray .address [knextAllocationSlot ] = availableAddress ;
142
+ kallocationArray .size [knextAllocationSlot ] = size ;
143
+ kallocationArray .inUse [knextAllocationSlot ++ ] = true;
144
+
145
+ return (void * )availableAddress ;
146
+ }
147
+
148
+ void kfree (void * ptr )
149
+ {
150
+ // Find this pointer in the allocation array
151
+ for (size_t i = 0 ; i < knextAllocationSlot ; ++ i )
152
+ {
153
+ if (kallocationArray .address [i ] == (uint32_t )ptr )
154
+ {
155
+ if (kallocationArray .inUse [i ])
156
+ {
157
+ addAllocationToKFreeMemoryArray (i );
158
+
159
+ // We want to keep the allocation array from being fragmented, so we
160
+ // copy the final entry in allocation array to the i position and
161
+ // decrease the size of the allocation array
162
+ -- knextAllocationSlot ;
163
+ if (knextAllocationSlot )
164
+ {
165
+ kallocationArray .address [i ] = kallocationArray .address [knextAllocationSlot ];
166
+ kallocationArray .size [i ] = kallocationArray .size [knextAllocationSlot ];
167
+ }
168
+
169
+ kallocationArray .inUse [knextAllocationSlot ] = false;
170
+ }
171
+ else
172
+ {
173
+ kprintf ("free() called to free already-freed pointer, 0x%lX\n" , ptr );
174
+ }
175
+
176
+ return ;
177
+ }
178
+ }
179
+
180
+ kprintf ("free() called with invalid pointer: 0x%lX" , ptr );
181
+ #ifdef DEBUG_MEM
182
+ printf (" from %s, line %d\n" , dbgFreeFilename , dbgFreeLineNumber );
183
+ dbgFreeFilename = noFileName ;
184
+ dbgFreeLineNumber = 0 ;
185
+ //for (;;)
186
+ // __halt();
187
+ #else
188
+ kprintf ("\n" );
189
+ #endif
190
+ }
0 commit comments