#[used]
#[export_name = "ZISK_BUMP_HEAP_POS"]
static mut HEAP_POS: usize = 0;
#[used]
#[export_name = "ZISK_BUMP_HEAP_TOP"]
static mut HEAP_TOP: usize = 0;
#[cfg(zisk_guest)]
#[no_mangle]
#[warn(dead_code)]
pub unsafe extern "C" fn init_sys_alloc() {
let (bottom, top) = sys_alloc_heap_bounds();
unsafe {
HEAP_POS = bottom;
HEAP_TOP = top;
};
}
#[cfg(all(zisk_guest, zisk_staticlib))]
#[no_mangle]
#[warn(dead_code)]
pub unsafe extern "C" fn reset_sys_alloc() {
let (bottom, top) = sys_alloc_heap_bounds();
unsafe {
HEAP_POS = bottom;
HEAP_TOP = top;
#[cfg(feature = "alloc-stats")]
{
HEAP_BOTTOM = bottom;
}
};
}
#[cfg(all(zisk_guest, zisk_staticlib, feature = "alloc-stats"))]
static mut HEAP_BOTTOM: usize = 0;
#[cfg(all(zisk_guest, zisk_staticlib, feature = "alloc-stats"))]
static mut HEAP_MAX_USED: usize = 0;
#[cfg(all(zisk_guest, zisk_staticlib, feature = "alloc-stats"))]
#[no_mangle]
pub unsafe extern "C" fn update_max_used_sys_alloc() {
unsafe {
let used = HEAP_POS.saturating_sub(HEAP_BOTTOM);
if used > HEAP_MAX_USED {
HEAP_MAX_USED = used;
}
}
}
#[cfg(all(zisk_guest, zisk_staticlib, feature = "alloc-stats"))]
#[no_mangle]
pub unsafe extern "C" fn get_max_used_sys_alloc() -> usize {
unsafe { HEAP_MAX_USED }
}
#[cfg(all(zisk_guest, zisk_staticlib, feature = "alloc-stats"))]
pub unsafe fn print_max_used_sys_alloc() {
use crate::ziskos::{sys_write, sys_write_u64};
let prefix = b"ziskos-isolated-allocator use: ";
let suffix = b" bytes\n";
unsafe {
sys_write(1, prefix.as_ptr(), prefix.len());
sys_write_u64(get_max_used_sys_alloc() as u64, false);
sys_write(1, suffix.as_ptr(), suffix.len());
}
}
#[cfg(all(zisk_guest, not(zisk_staticlib)))]
unsafe fn sys_alloc_heap_bounds() -> (usize, usize) {
extern "C" {
static _heap_bottom: u8;
static _heap_top: u8;
}
unsafe { (&_heap_bottom as *const u8 as usize, &_heap_top as *const u8 as usize) }
}
#[cfg(all(zisk_guest, zisk_staticlib))]
unsafe fn sys_alloc_heap_bounds() -> (usize, usize) {
const HEAP_SIZE: usize = 8 * 1024 * 1024;
#[allow(dead_code)]
#[repr(align(8))]
struct Heap([u8; HEAP_SIZE]);
static mut HEAP: Heap = Heap([0; HEAP_SIZE]);
let start = core::ptr::addr_of_mut!(HEAP) as usize;
(start, start + HEAP_SIZE)
}
#[cfg(zisk_guest)]
#[no_mangle]
#[inline(never)]
pub unsafe extern "C" fn sys_alloc_aligned(bytes: usize, align: usize) -> *mut u8 {
inline_bump_alloc_aligned(bytes, align)
}
#[cfg(zisk_guest)]
#[inline(always)]
pub unsafe fn inline_bump_alloc_aligned(bytes: usize, align: usize) -> *mut u8 {
let mut heap_pos = unsafe { HEAP_POS };
debug_assert!(align.is_power_of_two(), "align must be a power of two");
let offset = heap_pos & (align - 1);
if offset != 0 {
heap_pos = heap_pos.checked_add(align - offset).expect("heap_pos alignment overflow");
}
let ptr = heap_pos as *mut u8;
heap_pos = heap_pos.checked_add(bytes).expect("allocation size overflow");
if unsafe { HEAP_TOP } < heap_pos {
panic!("OOM limit of heap with bump allocator");
}
unsafe { HEAP_POS = heap_pos };
ptr
}
#[cfg(zisk_guest)]
use core::ptr;
#[cfg(zisk_guest)]
#[no_mangle]
static mut SINK: u64 = 0;
#[cfg(zisk_guest)]
#[no_mangle]
#[inline(never)]
pub unsafe extern "C" fn sys_alloc_log(op: u64, ptr: *mut u8, bytes: usize, align: usize) {
unsafe {
ptr::write_volatile(&raw mut SINK, bytes as u64 + op + (ptr as u64 & 0x02) + align as u64);
}
}