playdate_sys/sys/
allocator.rs

1#![cfg(not(test))]
2//! Global Allocator implementation. Depends on `allocator` feature.
3
4
5/*
6With rust-lang/rust#102318 default_alloc_error_handler has been stabilized,
7ie. the default error handler is enabled by default.
8Therefore, it's no longer necessary to provide an alloc_error_handler
9if the desired error handling is equivalent to a panic.
10TODO: think about remove `alloc_error_handler`.
11*/
12
13
14extern crate alloc;
15
16use core::alloc::{GlobalAlloc, Layout};
17use core::ffi::c_void;
18
19
20#[global_allocator]
21#[cfg(feature = "allocator")]
22pub static GLOBAL: PlaydateAllocator = PlaydateAllocator;
23
24/// Global handler for an Out Of Memory (OOM) condition
25#[alloc_error_handler]
26#[cfg(feature = "allocator")]
27fn alloc_error(layout: Layout) -> ! { panic!("Out of Memory, requested {}.", layout.size()) }
28
29
30pub struct PlaydateAllocator;
31
32unsafe impl GlobalAlloc for PlaydateAllocator {
33	#[inline]
34	unsafe fn alloc(&self, layout: Layout) -> *mut u8 { realloc(core::ptr::null_mut(), layout.size()) as *mut u8 }
35	#[inline]
36	unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { dealloc(ptr as *mut c_void); }
37	#[inline]
38	unsafe fn realloc(&self, ptr: *mut u8, _layout: Layout, new_size: usize) -> *mut u8 {
39		realloc(ptr as *mut c_void, new_size) as *mut u8
40	}
41}
42
43
44#[track_caller]
45#[allow(static_mut_refs)]
46unsafe fn realloc(ptr: *mut c_void, size: usize) -> *mut c_void {
47	// Cached pointer to the OS's realloc function.
48	static mut REALLOC: Option<unsafe extern "C" fn(ptr: *mut c_void, size: usize) -> *mut c_void> = None;
49
50	let f = REALLOC.get_or_insert_with(|| {
51		               if let Some(realloc) = crate::sys::API.as_ref().and_then(|api| (*api.system).realloc) {
52			               realloc
53		               } else {
54			               panic!("Missed API.realloc")
55		               }
56	               });
57	f(ptr, size)
58}
59
60
61#[track_caller]
62#[inline(always)]
63pub unsafe fn dealloc(ptr: *mut c_void) { realloc(ptr, 0); }