Skip to content

Commit

Permalink
Merge pull request #337: Fix panic & error, improve allocator (#335
Browse files Browse the repository at this point in the history
…, #336)

- Fix `abort` and `panic` to do not crash simulator process (#335)
- Improve global allocator, cache fn-ptr to OS's `realloc` (#336)
  • Loading branch information
boozook committed May 4, 2024
2 parents bc61d14 + 74cf93d commit 182ea6d
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/sys/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "playdate-sys"
version = "0.3.5"
version = "0.3.6"
build = "src/build.rs"
readme = "README.md"
description = "Low-level Playdate API bindings"
Expand Down
24 changes: 14 additions & 10 deletions api/sys/src/sys/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub static GLOBAL: PlaydateAllocator = PlaydateAllocator;
/// Global handler for an Out Of Memory (OOM) condition
#[alloc_error_handler]
#[cfg(feature = "allocator")]
fn alloc_error(_layout: Layout) -> ! { panic!("Out of Memory") }
fn alloc_error(layout: Layout) -> ! { panic!("Out of Memory, requested {}.", layout.size()) }


pub struct PlaydateAllocator;
Expand All @@ -42,13 +42,17 @@ unsafe impl GlobalAlloc for PlaydateAllocator {
}


fn realloc(ptr: *mut c_void, size: usize) -> *mut c_void {
unsafe {
if let Some(api) = crate::sys::API.as_ref() {
if let Some(f) = (*api.system).realloc {
return f(ptr, size);
}
}
}
panic!("realloc")
#[track_caller]
unsafe fn realloc(ptr: *mut c_void, size: usize) -> *mut c_void {
// Cached pointer to the OS's realloc function.
static mut REALLOC: Option<unsafe extern "C" fn(ptr: *mut c_void, size: usize) -> *mut c_void> = None;

let f = REALLOC.get_or_insert_with(|| {
if let Some(realloc) = crate::sys::API.as_ref().and_then(|api| (*api.system).realloc) {
realloc
} else {
panic!("Missed API.realloc")
}
});
f(ptr, size)
}
18 changes: 13 additions & 5 deletions api/sys/src/sys/proc.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
//! Process API. Abort and abort with error message.

/// Executes the undefined instruction (UDF) and causes a CPU-level exception.
/// See [`core::intrinsics::abort()`]
/// See [`core::intrinsics::abort()`].
#[track_caller]
#[inline(always)]
pub fn abort() -> ! { core::intrinsics::abort() }


/// Stops the program execution with custom system-level error.
///
/// In case of missed [`crate::sys::API`] (doesn't set) uses [`abort`].
#[track_caller]
pub fn error<S: AsRef<str>>(text: S) -> ! {
if let Some(f) = unsafe { (*(*crate::sys::API).system).error } {
Expand All @@ -14,9 +18,13 @@ pub fn error<S: AsRef<str>>(text: S) -> ! {
} else {
unsafe { f(text.as_ref().as_ptr() as *mut core::ffi::c_char) }
}
loop {
// This is unreachable or the device,
// `API.system.error` interrupts the execution.
// But simulator doesn't stops on `error`, so just spin-loop here.
}
} else {
// In case of `crate::sys::API` is missed (doesn't set) just abort the process.
abort()
}
// Next line is mostly unreachable,
// but in some cases such as some versions of simulator doesn't stops on `error`,
// especially in case of `crate::sys::API` isn't filled.
abort()
}

0 comments on commit 182ea6d

Please sign in to comment.