|  | // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint | 
|  | #![allow(static_mut_refs)] | 
|  |  | 
|  | use crate::alloc::{GlobalAlloc, Layout, System}; | 
|  |  | 
|  | #[cfg(not(test))] | 
|  | #[unsafe(export_name = "_ZN16__rust_internals3std3sys4xous5alloc8DLMALLOCE")] | 
|  | static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::Dlmalloc::new(); | 
|  |  | 
|  | #[cfg(test)] | 
|  | unsafe extern "Rust" { | 
|  | #[link_name = "_ZN16__rust_internals3std3sys4xous5alloc8DLMALLOCE"] | 
|  | static mut DLMALLOC: dlmalloc::Dlmalloc; | 
|  | } | 
|  |  | 
|  | #[stable(feature = "alloc_system_type", since = "1.28.0")] | 
|  | unsafe impl GlobalAlloc for System { | 
|  | #[inline] | 
|  | unsafe fn alloc(&self, layout: Layout) -> *mut u8 { | 
|  | // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. | 
|  | // Calling malloc() is safe because preconditions on this function match the trait method preconditions. | 
|  | let _lock = lock::lock(); | 
|  | unsafe { DLMALLOC.malloc(layout.size(), layout.align()) } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { | 
|  | // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. | 
|  | // Calling calloc() is safe because preconditions on this function match the trait method preconditions. | 
|  | let _lock = lock::lock(); | 
|  | unsafe { DLMALLOC.calloc(layout.size(), layout.align()) } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { | 
|  | // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. | 
|  | // Calling free() is safe because preconditions on this function match the trait method preconditions. | 
|  | let _lock = lock::lock(); | 
|  | unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { | 
|  | // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. | 
|  | // Calling realloc() is safe because preconditions on this function match the trait method preconditions. | 
|  | let _lock = lock::lock(); | 
|  | unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) } | 
|  | } | 
|  | } | 
|  |  | 
|  | mod lock { | 
|  | use crate::sync::atomic::Ordering::{Acquire, Release}; | 
|  | use crate::sync::atomic::{Atomic, AtomicI32}; | 
|  |  | 
|  | static LOCKED: Atomic<i32> = AtomicI32::new(0); | 
|  |  | 
|  | pub struct DropLock; | 
|  |  | 
|  | pub fn lock() -> DropLock { | 
|  | loop { | 
|  | if LOCKED.swap(1, Acquire) == 0 { | 
|  | return DropLock; | 
|  | } | 
|  | crate::os::xous::ffi::do_yield(); | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Drop for DropLock { | 
|  | fn drop(&mut self) { | 
|  | let r = LOCKED.swap(0, Release); | 
|  | debug_assert_eq!(r, 1); | 
|  | } | 
|  | } | 
|  | } |