use crate::nixl::{MemType, NixlCompatible, NixlDescriptor};
use crate::{MemoryDescriptor, StorageKind};
use std::any::Any;
use std::fmt;
pub struct ExternalDeviceMemory {
ptr: *const u8,
size: usize,
device_id: u64,
}
unsafe impl Send for ExternalDeviceMemory {}
unsafe impl Sync for ExternalDeviceMemory {}
impl ExternalDeviceMemory {
#[inline]
pub unsafe fn new(ptr: *const u8, size: usize, device_id: u64) -> Self {
Self {
ptr,
size,
device_id,
}
}
#[inline]
pub fn as_ptr(&self) -> *const u8 {
self.ptr
}
#[inline]
pub fn device_id(&self) -> u64 {
self.device_id
}
}
impl fmt::Debug for ExternalDeviceMemory {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ExternalDeviceMemory")
.field("ptr", &format_args!("{:p}", self.ptr))
.field("size", &self.size)
.field("device_id", &self.device_id)
.finish()
}
}
impl MemoryDescriptor for ExternalDeviceMemory {
#[inline]
fn addr(&self) -> usize {
self.ptr as usize
}
#[inline]
fn size(&self) -> usize {
self.size
}
#[inline]
fn storage_kind(&self) -> StorageKind {
StorageKind::Device(self.device_id as u32)
}
fn as_any(&self) -> &dyn Any {
self
}
fn nixl_descriptor(&self) -> Option<NixlDescriptor> {
None
}
}
impl NixlCompatible for ExternalDeviceMemory {
fn nixl_params(&self) -> (*const u8, usize, MemType, u64) {
(self.ptr, self.size, MemType::Vram, self.device_id)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_external_device_memory_traits() {
let ptr = 0x1000 as *const u8;
let size = 1024;
let device_id = 0;
let external = unsafe { ExternalDeviceMemory::new(ptr, size, device_id) };
assert_eq!(external.addr(), 0x1000);
assert_eq!(external.size(), 1024);
assert_eq!(external.storage_kind(), StorageKind::Device(0));
assert!(external.nixl_descriptor().is_none());
let (p, s, mem_type, dev) = external.nixl_params();
assert_eq!(p as usize, 0x1000);
assert_eq!(s, 1024);
assert_eq!(mem_type, MemType::Vram);
assert_eq!(dev, 0);
}
}