Skip to content

Commit 0f572bb

Browse files
author
Dan Cross
committed
rust: update rust, dependencies; fix errors
The ability to take a reference to a `static mut` is going to become a hard error in Rust 2024. This change attempts to get out in front of that by modifying places where we do that to make them safer. The biggest change was in the bump allocator; the implementation now is much closer to the one in the documentation for the GlobalAlloc trait, in that it takes ownership of an (aligned) array now, as opposed to wrapping a `static mut`. Signed-off-by: Dan Cross <[email protected]>
1 parent 111b22b commit 0f572bb

File tree

5 files changed

+140
-63
lines changed

5 files changed

+140
-63
lines changed

Cargo.lock

Lines changed: 29 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

theon/src/allocator.rs

Lines changed: 91 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,104 @@
55
// license that can be found in the LICENSE file or at
66
// https://opensource.org/licenses/MIT.
77

8-
use alloc::alloc::{GlobalAlloc, Layout};
9-
use core::cell::Cell;
8+
use core::cell::UnsafeCell;
9+
use core::sync::atomic::{AtomicUsize, Ordering};
1010

11-
static mut HEAP: [u8; 4 * 1024 * 1024] = [0_u8; 4 * 1024 * 1024];
11+
/// The allocator works in terms of an owned region
12+
/// of memory. We call this a Heap.
13+
pub(crate) trait Heap {
14+
fn as_mut_ptr(&mut self) -> *mut u8;
15+
fn len(&self) -> usize;
16+
}
1217

13-
pub(crate) struct BumpAlloc<'a> {
14-
heap: Cell<&'a mut [u8]>,
18+
/// A SliceHeap is a heap created by destructuring
19+
/// the elements of a mutable slice.
20+
pub(crate) struct SliceHeap {
21+
heap: *mut u8,
22+
len: usize,
1523
}
1624

17-
impl<'a> BumpAlloc<'a> {
18-
pub fn new(arena: &'a mut [u8]) -> BumpAlloc<'a> {
19-
BumpAlloc { heap: Cell::new(arena) }
25+
impl SliceHeap {
26+
pub fn new(arena: &mut [u8]) -> SliceHeap {
27+
SliceHeap { heap: arena.as_mut_ptr(), len: arena.len() }
28+
}
29+
}
30+
impl Heap for SliceHeap {
31+
fn as_mut_ptr(&mut self) -> *mut u8 {
32+
self.heap
33+
}
34+
fn len(&self) -> usize {
35+
self.len
2036
}
2137
}
2238

23-
unsafe impl GlobalAlloc for BumpAlloc<'_> {
24-
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
25-
let heap = self.heap.take();
26-
let ptr = heap.as_mut_ptr();
27-
let offset = ptr.align_offset(layout.align());
28-
if offset > heap.len() || offset + layout.size() > heap.len() {
29-
return core::ptr::null_mut();
30-
}
31-
let ptr = ptr.wrapping_add(offset);
32-
let heap = &mut heap[offset + layout.size()..];
33-
self.heap.replace(heap);
34-
ptr
39+
/// A Bump Allocator takes ownership of an object of
40+
/// some type that implements Heap, and maintains a
41+
/// cursor into that object. The cursor denotes the
42+
/// point between allocated and unallocated memory in
43+
/// the underlying Heap.
44+
pub(crate) struct BumpAlloc<T: Heap> {
45+
arena: UnsafeCell<T>,
46+
cursor: AtomicUsize,
47+
}
48+
49+
impl<T: Heap> BumpAlloc<T> {
50+
pub(crate) const fn new(arena: T) -> BumpAlloc<T> {
51+
BumpAlloc { arena: UnsafeCell::new(arena), cursor: AtomicUsize::new(0) }
52+
}
53+
54+
/// Allocates the given number of bytes with the given
55+
/// alignment. Returns `None` if the allocation cannot
56+
/// be satisfied, otherwise returns `Some` of a mutable
57+
/// slice referring to the allocated memory.
58+
pub(crate) fn alloc_bytes(&self, align: usize, size: usize) -> Option<&mut [u8]> {
59+
let heap = unsafe { &mut *self.arena.get() };
60+
let base = heap.as_mut_ptr();
61+
let mut offset = 0;
62+
self.cursor
63+
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |current| {
64+
let ptr = base.wrapping_add(current);
65+
let adjust = ptr.align_offset(align);
66+
offset = current.checked_add(adjust).expect("alignment overflow");
67+
let next = offset.checked_add(size).expect("size overflow");
68+
(next <= heap.len()).then_some(next)
69+
})
70+
.ok()?;
71+
let ptr = base.wrapping_add(offset);
72+
Some(unsafe { core::slice::from_raw_parts_mut(ptr, size) })
3573
}
36-
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
3774
}
3875

39-
#[global_allocator]
40-
static mut BUMP_ALLOCATOR: BumpAlloc<'static> = BumpAlloc { heap: Cell::new(unsafe { &mut HEAP }) };
76+
mod global {
77+
use super::{BumpAlloc, Heap};
78+
use alloc::alloc::{GlobalAlloc, Layout};
79+
use core::ptr;
80+
81+
const GLOBAL_HEAP_SIZE: usize = 4 * 1024 * 1024;
82+
83+
/// A GlobalHeap is an aligned wrapper around an
84+
/// owned buffer that implements the Heap trait.
85+
#[repr(C, align(4096))]
86+
struct GlobalHeap([u8; GLOBAL_HEAP_SIZE]);
87+
88+
impl Heap for GlobalHeap {
89+
fn as_mut_ptr(&mut self) -> *mut u8 {
90+
self.0.as_mut_ptr()
91+
}
92+
fn len(&self) -> usize {
93+
GLOBAL_HEAP_SIZE
94+
}
95+
}
96+
97+
unsafe impl<T: Heap> GlobalAlloc for BumpAlloc<T> {
98+
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
99+
self.alloc_bytes(layout.align(), layout.size())
100+
.map_or(ptr::null_mut(), |p| p.as_mut_ptr())
101+
}
102+
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
103+
}
104+
105+
#[global_allocator]
106+
static mut BUMP_ALLOCATOR: BumpAlloc<GlobalHeap> =
107+
BumpAlloc::new(GlobalHeap([0u8; GLOBAL_HEAP_SIZE]));
108+
}

theon/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ fn load(name: &str, typ: BinaryType, bytes: &[u8], region: Range<HPA>) -> Result
245245
let base = theon::vaddr(region.start).cast_mut();
246246
let len = unsafe { theon::vaddr(region.end).sub_ptr(theon::vaddr(region.start)) };
247247
let heap = unsafe { core::slice::from_raw_parts_mut(base, len) };
248+
let heap = allocator::SliceHeap::new(heap);
248249
let bump = allocator::BumpAlloc::new(heap);
249250
let allocate = || {
250251
use alloc::alloc::GlobalAlloc;

theon/src/x86_64/pc/init.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,24 @@
66
// https://opensource.org/licenses/MIT.
77

88
use crate::x86_64::pc::multiboot1;
9-
10-
static mut IDT: arch::idt::IDT = arch::idt::IDT::empty();
11-
static mut GDT: arch::gdt::GDT = arch::gdt::GDT::empty();
12-
static mut TSS: arch::tss::TSS = arch::tss::TSS::empty();
9+
use core::ptr;
10+
use core::sync::atomic::{AtomicBool, Ordering};
1311

1412
pub(crate) fn start(mbinfo_phys: u64) -> multiboot1::Multiboot1 {
13+
static INITED: AtomicBool = AtomicBool::new(false);
14+
if INITED.swap(false, Ordering::SeqCst) {
15+
panic!("double init");
16+
}
17+
static mut IDT: arch::idt::IDT = arch::idt::IDT::empty();
18+
static mut GDT: arch::gdt::GDT = arch::gdt::GDT::empty();
19+
static mut TSS: arch::tss::TSS = arch::tss::TSS::empty();
20+
1521
uart::panic_println!("\nBooting Hypatia...");
1622
unsafe {
1723
IDT.init(arch::trap::stubs());
18-
arch::idt::load(&mut IDT);
19-
GDT.init(&TSS);
20-
arch::gdt::load(&mut GDT);
24+
arch::idt::load(&mut *ptr::addr_of_mut!(IDT));
25+
GDT.init(&*ptr::addr_of!(TSS));
26+
arch::gdt::load(&mut *ptr::addr_of_mut!(GDT));
2127
}
2228
multiboot1::init(mbinfo_phys)
2329
}

theon/src/x86_64/pc/multiboot1.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use crate::theon;
99
use crate::x86_64::memory;
1010
use alloc::vec::Vec;
11+
use core::ptr;
1112
use multiboot::information::{MemoryManagement, MemoryType, Multiboot, PAddr};
1213

1314
unsafe fn phys_to_slice(phys_addr: PAddr, len: usize) -> Option<&'static [u8]> {
@@ -35,8 +36,6 @@ impl MemoryManagement for MM {
3536
}
3637
}
3738

38-
static mut MULTIBOOT_MM: MM = MM {};
39-
4039
fn theon_region() -> memory::Region {
4140
let start = 0x0000_0000_0010_0000_u64;
4241
let phys_end = unsafe { theon::end_addr().sub_ptr(theon::VZERO) } as u64;
@@ -97,8 +96,11 @@ pub(crate) struct Multiboot1 {
9796

9897
impl Multiboot1 {
9998
pub(crate) fn new(mbinfo_phys: u64) -> Multiboot1 {
100-
let multiboot =
101-
unsafe { Multiboot::from_ptr(mbinfo_phys as PAddr, &mut MULTIBOOT_MM).unwrap() };
99+
let multiboot = unsafe {
100+
static mut MULTIBOOT_MM: MM = MM {};
101+
let ptr = ptr::addr_of_mut!(MULTIBOOT_MM);
102+
Multiboot::from_ptr(mbinfo_phys as PAddr, &mut *ptr).unwrap()
103+
};
102104
Multiboot1 { multiboot }
103105
}
104106

0 commit comments

Comments
 (0)