Skip to content

Commit ab4ddd1

Browse files
committed
uefi: Allocator: handle ZST
We used std::alloc::System as template. [0] https://doc.rust-lang.org/src/std/alloc.rs.html#137
1 parent bb63cd3 commit ab4ddd1

File tree

3 files changed

+67
-6
lines changed

3 files changed

+67
-6
lines changed

Diff for: uefi-test-runner/src/boot/memory.rs

+40-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ pub fn test() {
1010
global::alloc_vec();
1111
global::alloc_alignment();
1212

13-
test_memory_map();
13+
#[cfg(feature = "unstable")]
14+
{
15+
allocator_api::alloc_zst();
16+
allocator_api::alloc_normal();
17+
}
1418
}
1519

1620
/// Tests that directly use UEFI boot services to allocate memory.
@@ -133,3 +137,38 @@ mod global {
133137
}
134138
}
135139
}
140+
141+
/// Tests the `allocator_api` on the UEFI allocator.
142+
#[cfg(feature = "unstable")]
143+
mod allocator_api {
144+
use core::alloc::Layout;
145+
use uefi::allocator::Allocator;
146+
147+
pub fn alloc_zst() {
148+
let layout = Layout::from_size_align(0, 1024).unwrap();
149+
let ptr = <Allocator as core::alloc::Allocator>::allocate(&Allocator, layout).unwrap();
150+
assert_eq!(ptr.len(), 0);
151+
assert_eq!(ptr.as_ptr().cast::<u8>().align_offset(layout.align()), 0);
152+
}
153+
154+
pub fn alloc_normal() {
155+
let layout = Layout::from_size_align(64, 64).unwrap();
156+
let allocation =
157+
<Allocator as core::alloc::Allocator>::allocate(&Allocator, layout).unwrap();
158+
assert_eq!(allocation.len(), 64);
159+
assert_eq!(
160+
allocation
161+
.as_ptr()
162+
.cast::<u8>()
163+
.align_offset(layout.align()),
164+
0
165+
);
166+
167+
unsafe {
168+
core::ptr::write_bytes(allocation.as_ptr().cast::<u8>(), 42, allocation.len());
169+
}
170+
unsafe {
171+
assert_eq!(allocation.as_ref()[42], 42);
172+
}
173+
}
174+
}

Diff for: uefi-test-runner/src/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#![no_std]
44
#![no_main]
5+
#![cfg_attr(feature = "unstable", feature(allocator_api))]
56

67
#[macro_use]
78
extern crate log;

Diff for: uefi/src/allocator.rs

+26-5
Original file line numberDiff line numberDiff line change
@@ -173,13 +173,34 @@ unsafe impl GlobalAlloc for Allocator {
173173
#[cfg(feature = "unstable")]
174174
unsafe impl core::alloc::Allocator for Allocator {
175175
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
176-
let ptr = unsafe { <Allocator as GlobalAlloc>::alloc(self, layout) };
177-
NonNull::new(ptr)
178-
.ok_or(core::alloc::AllocError)
179-
.map(|ptr| NonNull::slice_from_raw_parts(ptr, layout.size()))
176+
// Stable alternative for Layout::dangling()
177+
fn dangling_for_layout(layout: Layout) -> NonNull<u8> {
178+
let align = layout.align();
179+
// SAFETY: align is non-zero, so align as usize is a valid address for a NonNull.
180+
unsafe {
181+
let ptr = align as *mut u8;
182+
NonNull::new_unchecked(ptr)
183+
}
184+
}
185+
186+
match layout.size() {
187+
0 => Ok(NonNull::slice_from_raw_parts(
188+
dangling_for_layout(layout),
189+
0,
190+
)),
191+
// SAFETY: `layout` is non-zero in size,
192+
size => {
193+
let ptr = unsafe { <Allocator as GlobalAlloc>::alloc(self, layout) };
194+
NonNull::new(ptr)
195+
.ok_or(core::alloc::AllocError)
196+
.map(|ptr| NonNull::slice_from_raw_parts(ptr, size))
197+
}
198+
}
180199
}
181200

182201
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
183-
unsafe { <Allocator as GlobalAlloc>::dealloc(self, ptr.as_ptr(), layout) }
202+
if layout.size() != 0 {
203+
unsafe { <Allocator as GlobalAlloc>::dealloc(self, ptr.as_ptr(), layout) }
204+
}
184205
}
185206
}

0 commit comments

Comments
 (0)