Skip to content

Commit 58315b0

Browse files
committed
page allocator: mutable references are disallowed in statics
Since the recent compiler version mutable references are disallowed in statics, even behind Send-Types like mutexes. I created already a bug report but I'm not sure if this is easily fixed (rust-lang/rust#120450 (comment)) Therefore, we use OnceCell in our static page allocator or the option type in our test setup.
1 parent e677f04 commit 58315b0

File tree

4 files changed

+68
-86
lines changed

4 files changed

+68
-86
lines changed

src/kernel/src/main.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#![feature(nonzero_ops)]
77
#![feature(custom_test_frameworks)]
88
#![feature(const_mut_refs)]
9-
#![feature(offset_of)]
109
#![feature(option_take_if)]
1110
#![feature(non_null_convenience)]
1211
#![feature(pointer_is_aligned)]

src/kernel/src/memory/heap.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -272,24 +272,28 @@ mod test {
272272
const HEAP_SIZE: usize = (HEAP_PAGES - 1) * PAGE_SIZE;
273273

274274
static mut PAGE_ALLOC_MEMORY: [u8; PAGE_SIZE * HEAP_PAGES] = [0; PAGE_SIZE * HEAP_PAGES];
275-
static PAGE_ALLOC: Mutex<MetadataPageAllocator> = Mutex::new(MetadataPageAllocator::new());
275+
static PAGE_ALLOC: Mutex<Option<MetadataPageAllocator>> = Mutex::new(None);
276276

277277
struct TestAllocator;
278278
impl PageAllocator for TestAllocator {
279279
fn alloc(number_of_pages_requested: usize) -> Option<Range<NonNull<Page>>> {
280-
PAGE_ALLOC.lock().alloc(number_of_pages_requested)
280+
PAGE_ALLOC
281+
.lock()
282+
.as_mut()
283+
.unwrap()
284+
.alloc(number_of_pages_requested)
281285
}
282286

283287
fn dealloc(page: NonNull<Page>) {
284-
PAGE_ALLOC.lock().dealloc(page)
288+
PAGE_ALLOC.lock().as_mut().unwrap().dealloc(page)
285289
}
286290
}
287291

288292
fn init_allocator() {
289293
unsafe {
290-
PAGE_ALLOC
291-
.lock()
292-
.init(&mut *addr_of_mut!(PAGE_ALLOC_MEMORY));
294+
*PAGE_ALLOC.lock() = Some(MetadataPageAllocator::new(&mut *addr_of_mut!(
295+
PAGE_ALLOC_MEMORY
296+
)));
293297
}
294298
}
295299

src/kernel/src/memory/mod.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::{
2+
cell::OnceCell,
23
mem::{transmute, MaybeUninit},
34
ops::Range,
45
ptr::NonNull,
@@ -19,17 +20,25 @@ pub mod page_tables;
1920

2021
pub use page::PAGE_SIZE;
2122

22-
static PAGE_ALLOCATOR: Mutex<MetadataPageAllocator> = Mutex::new(MetadataPageAllocator::new());
23+
static PAGE_ALLOCATOR: Mutex<OnceCell<MetadataPageAllocator>> = Mutex::new(OnceCell::new());
2324

2425
pub struct StaticPageAllocator;
2526

2627
impl PageAllocator for StaticPageAllocator {
2728
fn alloc(number_of_pages_requested: usize) -> Option<Range<NonNull<Page>>> {
28-
PAGE_ALLOCATOR.lock().alloc(number_of_pages_requested)
29+
PAGE_ALLOCATOR
30+
.lock()
31+
.get_mut()
32+
.expect("PAGE_ALLOCATOR has to be initialized")
33+
.alloc(number_of_pages_requested)
2934
}
3035

3136
fn dealloc(page: NonNull<Page>) {
32-
PAGE_ALLOCATOR.lock().dealloc(page)
37+
PAGE_ALLOCATOR
38+
.lock()
39+
.get_mut()
40+
.expect("PAGE_ALLOCATOR has to be initialized")
41+
.dealloc(page)
3342
}
3443
}
3544

@@ -39,5 +48,8 @@ pub fn init_page_allocator(heap_start: usize, heap_size: usize) {
3948
elem.write(0);
4049
}
4150
let initialized_memory = unsafe { transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(memory) };
42-
PAGE_ALLOCATOR.lock().init(initialized_memory);
51+
PAGE_ALLOCATOR
52+
.lock()
53+
.set(MetadataPageAllocator::new(initialized_memory))
54+
.expect("PAGE_ALLOCATOR has to be uninitialized");
4355
}

src/kernel/src/memory/page_allocator.rs

Lines changed: 42 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
use crate::{debug, memory::PAGE_SIZE};
2-
use core::{
3-
fmt::Debug,
4-
ops::Range,
5-
ptr::{null_mut, NonNull},
6-
};
2+
use core::{fmt::Debug, ops::Range, ptr::NonNull};
73

84
use super::page::Page;
95

@@ -30,14 +26,7 @@ impl<'a> Debug for MetadataPageAllocator<'a> {
3026
}
3127

3228
impl<'a> MetadataPageAllocator<'a> {
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]) {
29+
pub(super) fn new(memory: &'a mut [u8]) -> Self {
4130
let heap_size = memory.len();
4231
let number_of_heap_pages = heap_size / (PAGE_SIZE + 1); // We need one byte per page as metadata
4332

@@ -57,14 +46,14 @@ impl<'a> MetadataPageAllocator<'a> {
5746

5847
metadata.iter_mut().for_each(|x| *x = PageStatus::Free);
5948

60-
self.metadata = metadata;
61-
62-
self.pages = heap.as_mut_ptr_range();
49+
let pages = heap.as_mut_ptr_range();
6350

6451
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());
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());
55+
56+
Self { metadata, pages }
6857
}
6958

7059
fn total_heap_pages(&self) -> usize {
@@ -134,53 +123,31 @@ pub trait PageAllocator {
134123

135124
#[cfg(test)]
136125
mod tests {
137-
use core::{
138-
ops::Range,
139-
ptr::{addr_of_mut, NonNull},
140-
};
141-
142-
use common::mutex::Mutex;
126+
use core::ptr::addr_of_mut;
143127

144128
use crate::memory::page_allocator::PageStatus;
145129

146-
use super::{MetadataPageAllocator, Page, PAGE_SIZE};
130+
use super::{MetadataPageAllocator, PAGE_SIZE};
147131

148132
static mut PAGE_ALLOC_MEMORY: [u8; PAGE_SIZE * 8] = [0; PAGE_SIZE * 8];
149-
static PAGE_ALLOC: Mutex<MetadataPageAllocator> = Mutex::new(MetadataPageAllocator::new());
150133

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)
134+
fn create_allocator() -> MetadataPageAllocator<'static> {
135+
unsafe { MetadataPageAllocator::new(&mut *addr_of_mut!(PAGE_ALLOC_MEMORY)) }
165136
}
166137

167138
#[test_case]
168139
fn clean_start() {
169-
init_allocator();
170-
assert!(PAGE_ALLOC
171-
.lock()
172-
.metadata
173-
.iter()
174-
.all(|s| *s == PageStatus::Free));
140+
let allocator = create_allocator();
141+
assert!(allocator.metadata.iter().all(|s| *s == PageStatus::Free));
175142
}
176143

177144
#[test_case]
178145
fn exhaustion_allocation() {
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();
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;
184151
let (last, all_metadata_except_last) = allocator.metadata.split_last().unwrap();
185152
assert!(all_metadata_except_last
186153
.iter()
@@ -190,41 +157,41 @@ mod tests {
190157

191158
#[test_case]
192159
fn beyond_capacity() {
193-
init_allocator();
194-
let number_of_pages = PAGE_ALLOC.lock().total_heap_pages();
195-
let pages = alloc(number_of_pages + 1);
160+
let mut allocator = create_allocator();
161+
let number_of_pages = allocator.total_heap_pages();
162+
let pages = allocator.alloc(number_of_pages + 1);
196163
assert!(pages.is_none());
197164
}
198165

199166
#[test_case]
200167
fn all_single_allocations() {
201-
init_allocator();
202-
let number_of_pages = PAGE_ALLOC.lock().total_heap_pages();
168+
let mut allocator = create_allocator();
169+
let number_of_pages = allocator.total_heap_pages();
203170
for _ in 0..number_of_pages {
204-
assert!(alloc(1).is_some());
171+
assert!(allocator.alloc(1).is_some());
205172
}
206-
assert!(alloc(1).is_none());
173+
assert!(allocator.alloc(1).is_none());
207174
}
208175

209176
#[test_case]
210177
fn metadata_integrity() {
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..]
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..]
215182
.iter()
216183
.all(|s| *s == PageStatus::Free));
217-
let page2 = alloc(2).unwrap();
184+
let page2 = allocator.alloc(2).unwrap();
218185
assert_eq!(
219-
PAGE_ALLOC.lock().metadata[..3],
186+
allocator.metadata[..3],
220187
[PageStatus::Last, PageStatus::Used, PageStatus::Last]
221188
);
222-
assert!(PAGE_ALLOC.lock().metadata[3..]
189+
assert!(allocator.metadata[3..]
223190
.iter()
224191
.all(|s| *s == PageStatus::Free));
225-
let page3 = alloc(3).unwrap();
192+
let page3 = allocator.alloc(3).unwrap();
226193
assert_eq!(
227-
PAGE_ALLOC.lock().metadata[..6],
194+
allocator.metadata[..6],
228195
[
229196
PageStatus::Last,
230197
PageStatus::Used,
@@ -234,12 +201,12 @@ mod tests {
234201
PageStatus::Last
235202
]
236203
);
237-
assert!(PAGE_ALLOC.lock().metadata[6..]
204+
assert!(allocator.metadata[6..]
238205
.iter()
239206
.all(|s| *s == PageStatus::Free),);
240-
dealloc(page2);
207+
allocator.dealloc(page2.start);
241208
assert_eq!(
242-
PAGE_ALLOC.lock().metadata[..6],
209+
allocator.metadata[..6],
243210
[
244211
PageStatus::Last,
245212
PageStatus::Free,
@@ -249,9 +216,9 @@ mod tests {
249216
PageStatus::Last
250217
]
251218
);
252-
dealloc(page1);
219+
allocator.dealloc(page1.start);
253220
assert_eq!(
254-
PAGE_ALLOC.lock().metadata[..6],
221+
allocator.metadata[..6],
255222
[
256223
PageStatus::Free,
257224
PageStatus::Free,
@@ -261,9 +228,9 @@ mod tests {
261228
PageStatus::Last
262229
]
263230
);
264-
dealloc(page3);
231+
allocator.dealloc(page3.start);
265232
assert_eq!(
266-
PAGE_ALLOC.lock().metadata[..6],
233+
allocator.metadata[..6],
267234
[
268235
PageStatus::Free,
269236
PageStatus::Free,

0 commit comments

Comments
 (0)