diff --git a/Cargo.lock b/Cargo.lock index 87f8dd73..a105c7c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4261,7 +4261,7 @@ dependencies = [ [[package]] name = "playdate-sys" -version = "0.3.5" +version = "0.3.6" dependencies = [ "arrayvec", "playdate-bindgen", diff --git a/api/sys/Cargo.toml b/api/sys/Cargo.toml index ba77f628..2378683f 100644 --- a/api/sys/Cargo.toml +++ b/api/sys/Cargo.toml @@ -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" diff --git a/api/sys/src/sys/allocator.rs b/api/sys/src/sys/allocator.rs index 69ad3e0c..d76cc6d6 100644 --- a/api/sys/src/sys/allocator.rs +++ b/api/sys/src/sys/allocator.rs @@ -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; @@ -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 *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) } diff --git a/api/sys/src/sys/proc.rs b/api/sys/src/sys/proc.rs index b2df5833..88238f19 100644 --- a/api/sys/src/sys/proc.rs +++ b/api/sys/src/sys/proc.rs @@ -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>(text: S) -> ! { if let Some(f) = unsafe { (*(*crate::sys::API).system).error } { @@ -14,9 +18,13 @@ pub fn error>(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() }