1
1
use crate :: { debug, memory:: PAGE_SIZE } ;
2
- use core:: { fmt:: Debug , ops:: Range , ptr:: NonNull } ;
2
+ use core:: {
3
+ fmt:: Debug ,
4
+ ops:: Range ,
5
+ ptr:: { null_mut, NonNull } ,
6
+ } ;
3
7
4
8
use super :: page:: Page ;
5
9
@@ -26,7 +30,14 @@ impl<'a> Debug for MetadataPageAllocator<'a> {
26
30
}
27
31
28
32
impl < ' a > MetadataPageAllocator < ' a > {
29
- pub ( super ) fn new ( memory : & ' a mut [ u8 ] ) -> Self {
33
+ pub ( super ) const fn new ( ) -> Self {
34
+ Self {
35
+ metadata : & mut [ ] ,
36
+ pages : null_mut ( ) ..null_mut ( ) ,
37
+ }
38
+ }
39
+
40
+ pub ( super ) fn init ( & mut self , memory : & ' a mut [ u8 ] ) {
30
41
let heap_size = memory. len ( ) ;
31
42
let number_of_heap_pages = heap_size / ( PAGE_SIZE + 1 ) ; // We need one byte per page as metadata
32
43
@@ -46,14 +57,14 @@ impl<'a> MetadataPageAllocator<'a> {
46
57
47
58
metadata. iter_mut ( ) . for_each ( |x| * x = PageStatus :: Free ) ;
48
59
49
- let pages = heap . as_mut_ptr_range ( ) ;
60
+ self . metadata = metadata ;
50
61
51
- debug ! ( "Page allocator initalized" ) ;
52
- debug ! ( "Metadata start:\t \t {:p}" , metadata) ;
53
- debug ! ( "Heap start:\t \t {:p}" , pages. start) ;
54
- debug ! ( "Number of pages:\t {}\n " , metadata. len( ) ) ;
62
+ self . pages = heap. as_mut_ptr_range ( ) ;
55
63
56
- Self { metadata, pages }
64
+ debug ! ( "Page allocator initalized" ) ;
65
+ debug ! ( "Metadata start:\t \t {:p}" , self . metadata) ;
66
+ debug ! ( "Heap start:\t \t {:p}" , self . pages. start) ;
67
+ debug ! ( "Number of pages:\t {}\n " , self . total_heap_pages( ) ) ;
57
68
}
58
69
59
70
fn total_heap_pages ( & self ) -> usize {
@@ -123,31 +134,53 @@ pub trait PageAllocator {
123
134
124
135
#[ cfg( test) ]
125
136
mod tests {
126
- use core:: ptr:: addr_of_mut;
137
+ use core:: {
138
+ ops:: Range ,
139
+ ptr:: { addr_of_mut, NonNull } ,
140
+ } ;
141
+
142
+ use common:: mutex:: Mutex ;
127
143
128
144
use crate :: memory:: page_allocator:: PageStatus ;
129
145
130
- use super :: { MetadataPageAllocator , PAGE_SIZE } ;
146
+ use super :: { MetadataPageAllocator , Page , PAGE_SIZE } ;
131
147
132
148
static mut PAGE_ALLOC_MEMORY : [ u8 ; PAGE_SIZE * 8 ] = [ 0 ; PAGE_SIZE * 8 ] ;
149
+ static PAGE_ALLOC : Mutex < MetadataPageAllocator > = Mutex :: new ( MetadataPageAllocator :: new ( ) ) ;
133
150
134
- fn create_allocator ( ) -> MetadataPageAllocator < ' static > {
135
- unsafe { MetadataPageAllocator :: new ( & mut * addr_of_mut ! ( PAGE_ALLOC_MEMORY ) ) }
151
+ fn init_allocator ( ) {
152
+ unsafe {
153
+ PAGE_ALLOC
154
+ . lock ( )
155
+ . init ( & mut * addr_of_mut ! ( PAGE_ALLOC_MEMORY ) ) ;
156
+ }
157
+ }
158
+
159
+ fn alloc ( number_of_pages : usize ) -> Option < Range < NonNull < Page > > > {
160
+ PAGE_ALLOC . lock ( ) . alloc ( number_of_pages)
161
+ }
162
+
163
+ fn dealloc ( pages : Range < NonNull < Page > > ) {
164
+ PAGE_ALLOC . lock ( ) . dealloc ( pages. start )
136
165
}
137
166
138
167
#[ test_case]
139
168
fn clean_start ( ) {
140
- let allocator = create_allocator ( ) ;
141
- assert ! ( allocator. metadata. iter( ) . all( |s| * s == PageStatus :: Free ) ) ;
169
+ init_allocator ( ) ;
170
+ assert ! ( PAGE_ALLOC
171
+ . lock( )
172
+ . metadata
173
+ . iter( )
174
+ . all( |s| * s == PageStatus :: Free ) ) ;
142
175
}
143
176
144
177
#[ test_case]
145
178
fn exhaustion_allocation ( ) {
146
- let mut allocator = create_allocator ( ) ;
147
- let number_of_pages = allocator . total_heap_pages ( ) ;
148
- let _pages = allocator . alloc ( number_of_pages) . unwrap ( ) ;
149
- assert ! ( allocator . alloc( 1 ) . is_none( ) ) ;
150
- let allocator = allocator ;
179
+ init_allocator ( ) ;
180
+ let number_of_pages = PAGE_ALLOC . lock ( ) . total_heap_pages ( ) ;
181
+ let _pages = alloc ( number_of_pages) . unwrap ( ) ;
182
+ assert ! ( alloc( 1 ) . is_none( ) ) ;
183
+ let allocator = PAGE_ALLOC . lock ( ) ;
151
184
let ( last, all_metadata_except_last) = allocator. metadata . split_last ( ) . unwrap ( ) ;
152
185
assert ! ( all_metadata_except_last
153
186
. iter( )
@@ -157,41 +190,41 @@ mod tests {
157
190
158
191
#[ test_case]
159
192
fn beyond_capacity ( ) {
160
- let mut allocator = create_allocator ( ) ;
161
- let number_of_pages = allocator . total_heap_pages ( ) ;
162
- let pages = allocator . alloc ( number_of_pages + 1 ) ;
193
+ init_allocator ( ) ;
194
+ let number_of_pages = PAGE_ALLOC . lock ( ) . total_heap_pages ( ) ;
195
+ let pages = alloc ( number_of_pages + 1 ) ;
163
196
assert ! ( pages. is_none( ) ) ;
164
197
}
165
198
166
199
#[ test_case]
167
200
fn all_single_allocations ( ) {
168
- let mut allocator = create_allocator ( ) ;
169
- let number_of_pages = allocator . total_heap_pages ( ) ;
201
+ init_allocator ( ) ;
202
+ let number_of_pages = PAGE_ALLOC . lock ( ) . total_heap_pages ( ) ;
170
203
for _ in 0 ..number_of_pages {
171
- assert ! ( allocator . alloc( 1 ) . is_some( ) ) ;
204
+ assert ! ( alloc( 1 ) . is_some( ) ) ;
172
205
}
173
- assert ! ( allocator . alloc( 1 ) . is_none( ) ) ;
206
+ assert ! ( alloc( 1 ) . is_none( ) ) ;
174
207
}
175
208
176
209
#[ test_case]
177
210
fn metadata_integrity ( ) {
178
- let mut allocator = create_allocator ( ) ;
179
- let page1 = allocator . alloc ( 1 ) . unwrap ( ) ;
180
- assert_eq ! ( allocator . metadata[ 0 ] , PageStatus :: Last ) ;
181
- assert ! ( allocator . metadata[ 1 ..]
211
+ init_allocator ( ) ;
212
+ let page1 = alloc ( 1 ) . unwrap ( ) ;
213
+ assert_eq ! ( PAGE_ALLOC . lock ( ) . metadata[ 0 ] , PageStatus :: Last ) ;
214
+ assert ! ( PAGE_ALLOC . lock ( ) . metadata[ 1 ..]
182
215
. iter( )
183
216
. all( |s| * s == PageStatus :: Free ) ) ;
184
- let page2 = allocator . alloc ( 2 ) . unwrap ( ) ;
217
+ let page2 = alloc ( 2 ) . unwrap ( ) ;
185
218
assert_eq ! (
186
- allocator . metadata[ ..3 ] ,
219
+ PAGE_ALLOC . lock ( ) . metadata[ ..3 ] ,
187
220
[ PageStatus :: Last , PageStatus :: Used , PageStatus :: Last ]
188
221
) ;
189
- assert ! ( allocator . metadata[ 3 ..]
222
+ assert ! ( PAGE_ALLOC . lock ( ) . metadata[ 3 ..]
190
223
. iter( )
191
224
. all( |s| * s == PageStatus :: Free ) ) ;
192
- let page3 = allocator . alloc ( 3 ) . unwrap ( ) ;
225
+ let page3 = alloc ( 3 ) . unwrap ( ) ;
193
226
assert_eq ! (
194
- allocator . metadata[ ..6 ] ,
227
+ PAGE_ALLOC . lock ( ) . metadata[ ..6 ] ,
195
228
[
196
229
PageStatus :: Last ,
197
230
PageStatus :: Used ,
@@ -201,12 +234,12 @@ mod tests {
201
234
PageStatus :: Last
202
235
]
203
236
) ;
204
- assert ! ( allocator . metadata[ 6 ..]
237
+ assert ! ( PAGE_ALLOC . lock ( ) . metadata[ 6 ..]
205
238
. iter( )
206
239
. all( |s| * s == PageStatus :: Free ) , ) ;
207
- allocator . dealloc ( page2. start ) ;
240
+ dealloc ( page2) ;
208
241
assert_eq ! (
209
- allocator . metadata[ ..6 ] ,
242
+ PAGE_ALLOC . lock ( ) . metadata[ ..6 ] ,
210
243
[
211
244
PageStatus :: Last ,
212
245
PageStatus :: Free ,
@@ -216,9 +249,9 @@ mod tests {
216
249
PageStatus :: Last
217
250
]
218
251
) ;
219
- allocator . dealloc ( page1. start ) ;
252
+ dealloc ( page1) ;
220
253
assert_eq ! (
221
- allocator . metadata[ ..6 ] ,
254
+ PAGE_ALLOC . lock ( ) . metadata[ ..6 ] ,
222
255
[
223
256
PageStatus :: Free ,
224
257
PageStatus :: Free ,
@@ -228,9 +261,9 @@ mod tests {
228
261
PageStatus :: Last
229
262
]
230
263
) ;
231
- allocator . dealloc ( page3. start ) ;
264
+ dealloc ( page3) ;
232
265
assert_eq ! (
233
- allocator . metadata[ ..6 ] ,
266
+ PAGE_ALLOC . lock ( ) . metadata[ ..6 ] ,
234
267
[
235
268
PageStatus :: Free ,
236
269
PageStatus :: Free ,
0 commit comments