Compare commits
10 Commits
536fb4cac3
...
9ec0b728c2
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ec0b728c2 | |||
| 0200b3c913 | |||
| 18f1a1b9a6 | |||
| 7c336c8769 | |||
| 72b2e58244 | |||
| f8d497f3e1 | |||
| 5cd37dfc93 | |||
| e649e2b595 | |||
| 6edbb046fa | |||
| d409a38eca |
@@ -110,6 +110,11 @@ impl Allocator {
|
||||
|
||||
// TODO: Consolidate chunks
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn get_offset(&self, ptr: *const u8) -> usize {
|
||||
let allocator = BUMP_ALLOCATOR.lock().unwrap();
|
||||
allocator.get_offset(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -3,10 +3,10 @@ use std::{
|
||||
usize,
|
||||
};
|
||||
|
||||
use libc::{c_char, c_void, ftruncate, memfd_create, mmap, MAP_SHARED, PROT_READ, PROT_WRITE};
|
||||
use libc::{c_char, c_void, ftruncate, mmap, perror, syscall, SYS_memfd_secret, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE};
|
||||
|
||||
pub(crate) const MEMFD_INITIAL_SIZE: usize = 1024 * 1024 * 4;
|
||||
const MMAP_SIZE: usize = 1024 * 1024 * 1024;
|
||||
pub(crate) const MEMFD_INITIAL_SIZE: usize = 1024 * 1024;
|
||||
const MMAP_SIZE: usize = 1024 * 1024;
|
||||
|
||||
pub(crate) static BUMP_ALLOCATOR: LazyLock<Mutex<BumpAllocator>> =
|
||||
LazyLock::new(|| unsafe { Mutex::new(BumpAllocator::new()) });
|
||||
@@ -26,7 +26,10 @@ impl BumpAllocator {
|
||||
unsafe fn new() -> Self {
|
||||
assert!(MMAP_SIZE >= MEMFD_INITIAL_SIZE);
|
||||
|
||||
let data_fd = memfd_create("data\x00".as_ptr() as *const c_char, 0);
|
||||
let data_fd = syscall(SYS_memfd_secret, 0) as i32;
|
||||
if data_fd <= 0 {
|
||||
perror("memfd secret\x00".as_ptr() as *const c_char);
|
||||
}
|
||||
|
||||
assert!(data_fd > 0);
|
||||
|
||||
@@ -41,7 +44,7 @@ impl BumpAllocator {
|
||||
0,
|
||||
) as *mut u8;
|
||||
|
||||
assert_ne!(start_of_mem, 0 as *mut u8);
|
||||
assert_ne!(start_of_mem, MAP_FAILED as *mut u8);
|
||||
|
||||
let end_of_mem = start_of_mem.byte_add(MEMFD_INITIAL_SIZE);
|
||||
|
||||
@@ -55,7 +58,7 @@ impl BumpAllocator {
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn alloc(&mut self, size: usize) -> Option<*mut u8> {
|
||||
pub(crate) unsafe fn alloc(&mut self, size: usize) -> Option<*mut u8> {
|
||||
let new_head = self.head.byte_add(size);
|
||||
|
||||
if new_head > self.end_of_mem {
|
||||
@@ -75,13 +78,26 @@ impl BumpAllocator {
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn dealloc(&mut self) {
|
||||
pub(crate) fn dealloc(&mut self) {
|
||||
self.number_of_allocated_chunks -= 1;
|
||||
|
||||
if self.number_of_allocated_chunks == 0 {
|
||||
self.head = self.start_of_mem;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn get_offset(&self, ptr: *const u8) -> usize {
|
||||
let offset = ptr.byte_offset_from(self.start_of_mem);
|
||||
|
||||
debug_assert!(offset >= 0);
|
||||
debug_assert!(offset < self.end_of_mem.byte_offset_from(self.start_of_mem));
|
||||
|
||||
offset as usize
|
||||
}
|
||||
|
||||
pub(crate) fn get_fd(&self) -> i32 {
|
||||
self.backing_fd
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
#![feature(test)]
|
||||
#![feature(lazy_cell)]
|
||||
|
||||
use bump_allocator::BUMP_ALLOCATOR;
|
||||
|
||||
mod allocator;
|
||||
mod bump_allocator;
|
||||
pub mod sharedptr;
|
||||
|
||||
pub fn get_shared_mem_fd() -> i32 {
|
||||
let allocator = BUMP_ALLOCATOR.lock().unwrap();
|
||||
|
||||
allocator.get_fd()
|
||||
}
|
||||
|
||||
@@ -1,46 +1,58 @@
|
||||
use core::slice;
|
||||
use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
usize,
|
||||
};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use crate::allocator::ALLOCATOR;
|
||||
|
||||
pub struct SharedPtr<'a>(&'a mut [u8]);
|
||||
#[derive(Debug)]
|
||||
pub struct SharedPtr<const N: usize>(*mut u8);
|
||||
|
||||
impl SharedPtr<'_> {
|
||||
pub fn new(size: usize) -> Option<Self> {
|
||||
unsafe impl<const N: usize> Send for SharedPtr<N> {}
|
||||
unsafe impl<const N: usize> Sync for SharedPtr<N> {}
|
||||
|
||||
impl<const N: usize> SharedPtr<N> {
|
||||
pub fn new() -> Option<Self> {
|
||||
let mut allocator = ALLOCATOR.lock().unwrap();
|
||||
|
||||
let buf = unsafe {
|
||||
let buf = allocator.allocate(size)?;
|
||||
slice::from_raw_parts_mut(buf, size)
|
||||
};
|
||||
let buf = unsafe { allocator.allocate(N)? };
|
||||
|
||||
Some(SharedPtr(buf))
|
||||
}
|
||||
|
||||
pub fn get_offset(&self) -> usize {
|
||||
let allocator = ALLOCATOR.lock().unwrap();
|
||||
|
||||
unsafe { allocator.get_offset(self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deref for SharedPtr<'a> {
|
||||
type Target = &'a mut [u8];
|
||||
impl<const N: usize> Deref for SharedPtr<N> {
|
||||
type Target = [u8; N];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
unsafe {
|
||||
slice::from_raw_parts(self.0, N)
|
||||
.try_into()
|
||||
.expect("This should never fail")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DerefMut for SharedPtr<'a> {
|
||||
impl<const N: usize> DerefMut for SharedPtr<N> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(self.0, N)
|
||||
.try_into()
|
||||
.expect("This should never fail")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SharedPtr<'_> {
|
||||
impl<const N: usize> Drop for SharedPtr<N> {
|
||||
fn drop(&mut self) {
|
||||
let mut allocator = ALLOCATOR.lock().unwrap();
|
||||
|
||||
unsafe {
|
||||
allocator.deallocate(self.0.as_mut_ptr());
|
||||
allocator.deallocate(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,9 +63,17 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let mut x = SharedPtr::new(10).unwrap();
|
||||
let mut x = SharedPtr::<10>::new().unwrap();
|
||||
x[0] = 1;
|
||||
assert_eq!(x[0], 1);
|
||||
drop(x);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slice() {
|
||||
let mut x = SharedPtr::<10>::new().unwrap();
|
||||
x[0] = 1;
|
||||
x[1] = 2;
|
||||
assert_eq!(x[0..=1], [1, 2]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user