Skip to content

Commit 5fd508c

Browse files
committed
Revert "page allocator: mutable references are disallowed in statics"
This reverts commit bcfc059. The mentioned compiler bug (rust-lang/rust#120450) is fixed now so we can continue to use mutable statics which doesn't point to any memory. Update rust-toolchain to the latest nightly.
1 parent fc3b264 commit 5fd508c

File tree

4 files changed

+86
-69
lines changed

4 files changed

+86
-69
lines changed

rust-toolchain

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[toolchain]
2-
channel = "nightly-2024-02-06"
2+
channel = "nightly-2024-02-17"
33
targets = ["riscv64gc-unknown-none-elf"]

src/kernel/src/memory/heap.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -269,28 +269,24 @@ mod test {
269269
const HEAP_SIZE: usize = (HEAP_PAGES - 1) * PAGE_SIZE;
270270

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

274274
struct TestAllocator;
275275
impl PageAllocator for TestAllocator {
276276
fn alloc(number_of_pages_requested: usize) -> Option<Range<NonNull<Page>>> {
277-
PAGE_ALLOC
278-
.lock()
279-
.as_mut()
280-
.unwrap()
281-
.alloc(number_of_pages_requested)
277+
PAGE_ALLOC.lock().alloc(number_of_pages_requested)
282278
}
283279

284280
fn dealloc(page: NonNull<Page>) {
285-
PAGE_ALLOC.lock().as_mut().unwrap().dealloc(page)
281+
PAGE_ALLOC.lock().dealloc(page)
286282
}
287283
}
288284

289285
fn init_allocator() {
290286
unsafe {
291-
*PAGE_ALLOC.lock() = Some(MetadataPageAllocator::new(&mut *addr_of_mut!(
292-
PAGE_ALLOC_MEMORY
293-
)));
287+
PAGE_ALLOC
288+
.lock()
289+
.init(&mut *addr_of_mut!(PAGE_ALLOC_MEMORY));
294290
}
295291
}
296292

src/kernel/src/memory/mod.rs

+4-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use core::{
2-
cell::OnceCell,
32
mem::{transmute, MaybeUninit},
43
ops::Range,
54
ptr::NonNull,
@@ -20,25 +19,17 @@ pub mod page_tables;
2019

2120
pub use page::PAGE_SIZE;
2221

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

2524
pub struct StaticPageAllocator;
2625

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

3631
fn dealloc(page: NonNull<Page>) {
37-
PAGE_ALLOCATOR
38-
.lock()
39-
.get_mut()
40-
.expect("PAGE_ALLOCATOR has to be initialized")
41-
.dealloc(page)
32+
PAGE_ALLOCATOR.lock().dealloc(page)
4233
}
4334
}
4435

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

src/kernel/src/memory/page_allocator.rs

+75-42
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
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+
};
37

48
use super::page::Page;
59

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

2832
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]) {
3041
let heap_size = memory.len();
3142
let number_of_heap_pages = heap_size / (PAGE_SIZE + 1); // We need one byte per page as metadata
3243

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

4758
metadata.iter_mut().for_each(|x| *x = PageStatus::Free);
4859

49-
let pages = heap.as_mut_ptr_range();
60+
self.metadata = metadata;
5061

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();
5563

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());
5768
}
5869

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

124135
#[cfg(test)]
125136
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;
127143

128144
use crate::memory::page_allocator::PageStatus;
129145

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

132148
static mut PAGE_ALLOC_MEMORY: [u8; PAGE_SIZE * 8] = [0; PAGE_SIZE * 8];
149+
static PAGE_ALLOC: Mutex<MetadataPageAllocator> = Mutex::new(MetadataPageAllocator::new());
133150

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)
136165
}
137166

138167
#[test_case]
139168
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));
142175
}
143176

144177
#[test_case]
145178
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();
151184
let (last, all_metadata_except_last) = allocator.metadata.split_last().unwrap();
152185
assert!(all_metadata_except_last
153186
.iter()
@@ -157,41 +190,41 @@ mod tests {
157190

158191
#[test_case]
159192
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);
163196
assert!(pages.is_none());
164197
}
165198

166199
#[test_case]
167200
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();
170203
for _ in 0..number_of_pages {
171-
assert!(allocator.alloc(1).is_some());
204+
assert!(alloc(1).is_some());
172205
}
173-
assert!(allocator.alloc(1).is_none());
206+
assert!(alloc(1).is_none());
174207
}
175208

176209
#[test_case]
177210
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..]
182215
.iter()
183216
.all(|s| *s == PageStatus::Free));
184-
let page2 = allocator.alloc(2).unwrap();
217+
let page2 = alloc(2).unwrap();
185218
assert_eq!(
186-
allocator.metadata[..3],
219+
PAGE_ALLOC.lock().metadata[..3],
187220
[PageStatus::Last, PageStatus::Used, PageStatus::Last]
188221
);
189-
assert!(allocator.metadata[3..]
222+
assert!(PAGE_ALLOC.lock().metadata[3..]
190223
.iter()
191224
.all(|s| *s == PageStatus::Free));
192-
let page3 = allocator.alloc(3).unwrap();
225+
let page3 = alloc(3).unwrap();
193226
assert_eq!(
194-
allocator.metadata[..6],
227+
PAGE_ALLOC.lock().metadata[..6],
195228
[
196229
PageStatus::Last,
197230
PageStatus::Used,
@@ -201,12 +234,12 @@ mod tests {
201234
PageStatus::Last
202235
]
203236
);
204-
assert!(allocator.metadata[6..]
237+
assert!(PAGE_ALLOC.lock().metadata[6..]
205238
.iter()
206239
.all(|s| *s == PageStatus::Free),);
207-
allocator.dealloc(page2.start);
240+
dealloc(page2);
208241
assert_eq!(
209-
allocator.metadata[..6],
242+
PAGE_ALLOC.lock().metadata[..6],
210243
[
211244
PageStatus::Last,
212245
PageStatus::Free,
@@ -216,9 +249,9 @@ mod tests {
216249
PageStatus::Last
217250
]
218251
);
219-
allocator.dealloc(page1.start);
252+
dealloc(page1);
220253
assert_eq!(
221-
allocator.metadata[..6],
254+
PAGE_ALLOC.lock().metadata[..6],
222255
[
223256
PageStatus::Free,
224257
PageStatus::Free,
@@ -228,9 +261,9 @@ mod tests {
228261
PageStatus::Last
229262
]
230263
);
231-
allocator.dealloc(page3.start);
264+
dealloc(page3);
232265
assert_eq!(
233-
allocator.metadata[..6],
266+
PAGE_ALLOC.lock().metadata[..6],
234267
[
235268
PageStatus::Free,
236269
PageStatus::Free,

0 commit comments

Comments
 (0)