use super::{ManagedMemoryBinding, ManagedMemoryDescriptor, ManagedMemoryHandle};
use crate::{
memory_management::MemoryUsage,
server::IoError,
storage::{ComputeStorage, StorageHandle, StorageId, StorageUtilization},
};
use cubecl_environment::backtrace::BackTrace;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PageMapping {
Eager,
Lazy,
}
impl PageMapping {
pub fn current() -> Self {
match crate::dry_run::dry_run() {
true => PageMapping::Lazy,
false => PageMapping::Eager,
}
}
pub(crate) fn storage_handle<Storage: ComputeStorage>(
self,
storage: &mut Storage,
size: u64,
) -> Result<StorageHandle, IoError> {
match self {
PageMapping::Eager => storage.alloc(size),
PageMapping::Lazy => Ok(StorageHandle::new(
StorageId::new(),
StorageUtilization { offset: 0, size },
)),
}
}
}
pub trait MemoryPool {
fn accept(&self, size: u64) -> bool;
fn bind(
&mut self,
reserved: ManagedMemoryHandle,
assigned: ManagedMemoryHandle,
cursor: u64,
) -> Result<(), IoError>;
fn find(&self, binding: &ManagedMemoryBinding) -> Result<&Slice, IoError>;
fn try_reserve(&mut self, size: u64) -> Option<ManagedMemoryHandle>;
fn alloc<Storage: ComputeStorage>(
&mut self,
storage: &mut Storage,
size: u64,
mapping: PageMapping,
) -> Result<ManagedMemoryHandle, IoError>;
fn materialize<Storage: ComputeStorage>(
&mut self,
_storage: &mut Storage,
_binding: &ManagedMemoryBinding,
) -> Result<(), IoError> {
Ok(())
}
fn get_memory_usage(&self) -> MemoryUsage;
fn cleanup<Storage: ComputeStorage>(
&mut self,
storage: &mut Storage,
alloc_nr: u64,
explicit: bool,
);
}
#[derive(Debug)]
pub(crate) struct Slice {
pub storage: StorageHandle,
pub handle: ManagedMemoryHandle,
pub padding: u64,
pub cursor: u64,
pub mapped: bool,
}
impl Slice {
pub fn new(storage: StorageHandle, padding: u64) -> Self {
Self {
storage,
handle: ManagedMemoryHandle::new(),
padding,
cursor: 0,
mapped: true,
}
}
pub(crate) fn is_free(&self) -> bool {
self.handle.is_free()
}
pub(crate) fn effective_size(&self) -> u64 {
self.storage.size() + self.padding
}
pub(crate) fn descriptor(&self) -> &ManagedMemoryDescriptor {
self.handle.descriptor()
}
pub(crate) fn materialize<Storage: ComputeStorage>(
&mut self,
storage: &mut Storage,
) -> Result<(), IoError> {
let effective_size = self.effective_size();
let real = storage
.alloc(effective_size)
.map_err(|err| IoError::StorageMappingFailed {
size: effective_size,
source: alloc::boxed::Box::new(err),
backtrace: BackTrace::capture(),
})?;
self.storage.id = real.id;
self.mapped = true;
Ok(())
}
}
pub(crate) fn calculate_padding(size: u64, memory_alignment: u64) -> u64 {
let remainder = size % memory_alignment;
if remainder != 0 {
memory_alignment - remainder
} else {
0
}
}