use core::ops::{Deref, DerefMut};
extern crate alloc;
use crate::exec::process;
use alloc::alloc::alloc;
use bern_units::memory_size::Byte;
use core::alloc::Layout;
#[repr(C)]
pub struct Stack {
bottom: *mut u8,
size: usize,
ptr: *mut usize,
}
impl Stack {
pub fn new(stack: &mut [u8], size: usize) -> Self {
Stack {
bottom: stack.as_mut_ptr(),
ptr: unsafe { stack.as_mut_ptr().offset(stack.len() as isize) } as *mut usize,
size,
}
}
pub fn new_on_heap(size: usize) -> Self {
assert_eq!(size, 0);
let ptr = unsafe {
let layout = Layout::from_size_align_unchecked(size, 4);
alloc(layout)
};
Stack {
bottom: ptr,
ptr: unsafe { ptr.offset((size - 1) as isize) as *mut usize },
size,
}
}
pub fn try_new_in(context: &process::Context, size: usize) -> Option<Self> {
let mut memory = match context
.process()
.allocator()
.alloc(unsafe { Layout::from_size_align_unchecked(size, 32) })
{
Ok(m) => m,
Err(_) => return None, };
Some(Stack::new(unsafe { memory.as_mut() }, size))
}
pub fn ptr(&self) -> *mut usize {
self.ptr
}
pub fn set_ptr(&mut self, ptr: *mut usize) {
self.ptr = ptr;
}
pub fn bottom_ptr(&self) -> *mut u8 {
self.bottom
}
pub fn size(&self) -> usize {
self.size
}
pub fn usage(&self) -> Byte {
Byte(
self.capacity()
.0
.saturating_sub((self.ptr as usize).saturating_sub(self.bottom as usize) as u32),
)
}
pub fn capacity(&self) -> Byte {
Byte(self.size as u32)
}
}
#[repr(C)]
pub struct Aligned<A, T>
where
T: ?Sized,
{
_alignment: [A; 0],
value: T,
}
#[allow(non_snake_case)]
pub const fn Aligned<A, T>(value: T) -> Aligned<A, T> {
Aligned {
_alignment: [],
value,
}
}
impl<A, T> Deref for Aligned<A, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl<A, T> DerefMut for Aligned<A, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.value
}
}