1use crate::{shm::ShmMemory, JitMemory, JitResetableMemory};
2use memmap2::{MmapMut, MmapOptions};
3use std::{
4 fs::File,
5 io,
6 ops::{Deref, DerefMut},
7 os::fd::AsRawFd,
8};
9
10pub struct AnonymousMemory {
12 pub mem_fd: File,
13 pub memory: MmapMut,
14}
15
16impl AsRawFd for AnonymousMemory {
17 fn as_raw_fd(&self) -> i32 {
18 self.mem_fd.as_raw_fd()
19 }
20}
21
22impl Deref for AnonymousMemory {
23 type Target = [u8];
24
25 fn deref(&self) -> &<Self as Deref>::Target {
26 self.memory.deref()
27 }
28}
29
30impl DerefMut for AnonymousMemory {
31 fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
32 self.memory.deref_mut()
33 }
34}
35
36impl JitMemory for AnonymousMemory {
37 fn new(memory_size: usize) -> Self {
38 let file = create_anonymous_file(memory_size);
39
40 let memory = unsafe {
41 MmapOptions::new().no_reserve_swap().map_mut(&file).expect("Failed to call mmap")
42 };
43
44 Self { mem_fd: file, memory }
45 }
46}
47
48impl JitResetableMemory for AnonymousMemory {
49 fn reset(&mut self) {
50 let memory_size = self.memory.len();
52
53 self.mem_fd = create_anonymous_file(memory_size);
55
56 self.memory = unsafe {
57 MmapOptions::new()
58 .no_reserve_swap()
59 .map_mut(&self.mem_fd)
60 .expect("Failed to map memory")
61 };
62 }
63}
64
65#[cfg(target_os = "linux")]
66fn create_anonymous_file(size: usize) -> File {
67 let fd = memfd::MemfdOptions::default()
68 .create(uuid::Uuid::new_v4().to_string())
69 .expect("Failed to create jit memory");
70 let file = fd.into_file();
71 file.set_len(size as u64).expect("Faile to set length for jit memory");
72 file
73}
74
75#[cfg(target_os = "macos")]
76fn create_anonymous_file(size: usize) -> File {
77 use libc::{c_char, c_uint, ftruncate, shm_open, O_CREAT, O_RDWR, S_IRUSR, S_IWUSR};
78 use std::io;
79 use std::os::fd::FromRawFd;
80
81 const SHM_ANON: *const c_char = -1isize as *const c_char;
83
84 let fd = unsafe { shm_open(SHM_ANON, O_RDWR | O_CREAT, (S_IRUSR | S_IWUSR) as c_uint) };
85 if fd < 0 {
86 panic!("Error creating anonymous memory file: {}", io::Error::last_os_error());
87 }
88
89 let res = unsafe { ftruncate(fd, size as _) };
90 if res != 0 {
91 panic!("Error setting file size: {}", io::Error::last_os_error());
92 }
93
94 unsafe { File::from_raw_fd(fd) }
95}
96
97pub struct SharedMemory {
99 handle: Option<ShmMemory>,
100}
101
102impl SharedMemory {
103 pub fn create_readonly(id: &str, memory_size: usize) -> io::Result<Self> {
104 Ok(Self { handle: Some(ShmMemory::create_readonly(id, memory_size)?) })
105 }
106
107 pub fn open_readwrite(&mut self, id: &str) -> io::Result<()> {
108 self.handle = Some(ShmMemory::open_readwrite(id)?);
109 Ok(())
110 }
111}
112
113impl AsRawFd for SharedMemory {
114 fn as_raw_fd(&self) -> i32 {
115 self.handle.as_ref().unwrap().as_raw_fd()
116 }
117}
118
119impl Deref for SharedMemory {
120 type Target = [u8];
121
122 fn deref(&self) -> &<Self as Deref>::Target {
123 self.handle.as_ref().unwrap().deref()
124 }
125}
126
127impl DerefMut for SharedMemory {
128 fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
129 self.handle.as_mut().unwrap().deref_mut()
130 }
131}
132
133impl JitMemory for SharedMemory {
134 fn new(_memory_size: usize) -> Self {
135 Self { handle: None }
136 }
137}